abcjs 6.0.0-beta.7 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (204) hide show
  1. package/.github/workflows/tests.yml +29 -0
  2. package/CODE_OF_CONDUCT.md +76 -0
  3. package/CONTRIBUTING.md +1 -0
  4. package/LICENSE.md +1 -1
  5. package/README.md +92 -3
  6. package/RELEASE.md +957 -1
  7. package/abcjs-audio.css +14 -5
  8. package/dist/.gitignore +1 -2
  9. package/dist/abcjs-basic-min.js +3 -0
  10. package/dist/abcjs-basic-min.js.LICENSE +23 -0
  11. package/dist/abcjs-basic.js +28231 -0
  12. package/dist/abcjs-basic.js.map +1 -0
  13. package/dist/abcjs-plugin-min.js +3 -0
  14. package/dist/abcjs-plugin-min.js.LICENSE +23 -0
  15. package/dist/report-basic.html +37 -0
  16. package/dist/report-before-glyph-compress.html +37 -0
  17. package/dist/report-brown-ts-target-es5.html +37 -0
  18. package/dist/report-dev-orig-no-babel.html +37 -0
  19. package/dist/report-synth.html +37 -0
  20. package/docker-build.sh +1 -0
  21. package/glyphs.json +1 -0
  22. package/index.js +27 -2
  23. package/{static-wrappers/license.js → license.js} +1 -1
  24. package/package.json +26 -29
  25. package/{src/plugin/abc_plugin.js → plugin.js} +31 -19
  26. package/src/api/abc_animation.js +1 -17
  27. package/src/api/abc_tablatures.js +144 -0
  28. package/src/api/abc_timing_callbacks.js +234 -116
  29. package/src/api/abc_tunebook.js +18 -67
  30. package/src/api/abc_tunebook_svg.js +38 -46
  31. package/src/data/abc_tune.js +232 -972
  32. package/src/data/deline-tune.js +199 -0
  33. package/src/edit/abc_editarea.js +112 -0
  34. package/src/edit/abc_editor.js +95 -221
  35. package/src/midi/abc_midi_create.js +48 -50
  36. package/src/parse/abc_common.js +0 -14
  37. package/src/parse/abc_parse.js +167 -1321
  38. package/src/parse/abc_parse_book.js +62 -0
  39. package/src/parse/abc_parse_directive.js +164 -41
  40. package/src/parse/abc_parse_header.js +116 -145
  41. package/src/parse/abc_parse_key_voice.js +26 -20
  42. package/src/parse/abc_parse_music.js +1337 -0
  43. package/src/parse/abc_tokenizer.js +21 -15
  44. package/src/parse/abc_transpose.js +3 -15
  45. package/src/parse/tune-builder.js +896 -0
  46. package/src/parse/wrap_lines.js +205 -453
  47. package/src/synth/abc_midi_flattener.js +1292 -0
  48. package/src/{midi → synth}/abc_midi_renderer.js +44 -17
  49. package/src/synth/abc_midi_sequencer.js +648 -0
  50. package/src/synth/active-audio-context.js +3 -14
  51. package/src/synth/cents-to-factor.js +10 -0
  52. package/src/synth/create-note-map.js +21 -32
  53. package/src/synth/create-synth-control.js +20 -103
  54. package/src/synth/create-synth.js +185 -77
  55. package/src/synth/download-buffer.js +7 -21
  56. package/src/synth/get-midi-file.js +13 -20
  57. package/src/synth/images/{loading.svg → loading.svg.js} +4 -0
  58. package/src/synth/images/loop.svg.js +65 -0
  59. package/src/synth/images/pause.svg.js +10 -0
  60. package/src/synth/images/play.svg.js +9 -0
  61. package/src/synth/images/{reset.svg → reset.svg.js} +5 -1
  62. package/src/synth/instrument-index-to-name.js +1 -16
  63. package/src/synth/load-note.js +37 -76
  64. package/src/synth/pitch-to-note-name.js +0 -15
  65. package/src/synth/pitches-to-perc.js +64 -0
  66. package/src/synth/place-note.js +78 -68
  67. package/src/synth/play-event.js +17 -18
  68. package/src/synth/register-audio-context.js +11 -23
  69. package/src/synth/sounds-cache.js +0 -15
  70. package/src/synth/supports-audio.js +9 -23
  71. package/src/synth/synth-controller.js +80 -49
  72. package/src/synth/synth-sequence.js +20 -34
  73. package/src/tablatures/instruments/guitar/guitar-fonts.js +19 -0
  74. package/src/tablatures/instruments/guitar/guitar-patterns.js +23 -0
  75. package/src/tablatures/instruments/guitar/tab-guitar.js +50 -0
  76. package/src/tablatures/instruments/string-patterns.js +277 -0
  77. package/src/tablatures/instruments/string-tablature.js +56 -0
  78. package/src/tablatures/instruments/tab-note.js +282 -0
  79. package/src/tablatures/instruments/tab-notes.js +41 -0
  80. package/src/tablatures/instruments/violin/tab-violin.js +47 -0
  81. package/src/tablatures/instruments/violin/violin-fonts.js +19 -0
  82. package/src/tablatures/instruments/violin/violin-patterns.js +23 -0
  83. package/src/tablatures/tab-absolute-elements.js +310 -0
  84. package/src/tablatures/tab-common.js +29 -0
  85. package/src/tablatures/tab-renderer.js +243 -0
  86. package/src/tablatures/transposer.js +110 -0
  87. package/src/test/abc_midi_lint.js +5 -22
  88. package/src/test/abc_midi_sequencer_lint.js +11 -14
  89. package/src/test/abc_parser_lint.js +136 -32
  90. package/src/test/abc_vertical_lint.js +94 -32
  91. package/src/test/rendering-lint.js +38 -5
  92. package/src/write/abc_absolute_element.js +112 -120
  93. package/src/write/abc_abstract_engraver.js +102 -253
  94. package/src/write/abc_beam_element.js +30 -290
  95. package/src/write/abc_brace_element.js +12 -121
  96. package/src/write/abc_create_clef.js +21 -32
  97. package/src/write/abc_create_key_signature.js +8 -26
  98. package/src/write/abc_create_note_head.js +107 -0
  99. package/src/write/abc_create_time_signature.js +2 -21
  100. package/src/write/abc_crescendo_element.js +3 -50
  101. package/src/write/abc_decoration.js +7 -30
  102. package/src/write/abc_dynamic_decoration.js +3 -37
  103. package/src/write/abc_ending_element.js +1 -57
  104. package/src/write/abc_engraver_controller.js +111 -234
  105. package/src/write/abc_glyphs.js +9 -19
  106. package/src/write/abc_relative_element.js +57 -97
  107. package/src/write/abc_renderer.js +10 -832
  108. package/src/write/abc_spacing.js +0 -15
  109. package/src/write/abc_staff_group_element.js +14 -349
  110. package/src/write/abc_tempo_element.js +9 -117
  111. package/src/write/abc_tie_element.js +5 -68
  112. package/src/write/abc_triplet_element.js +6 -124
  113. package/src/write/abc_voice_element.js +7 -222
  114. package/src/write/add-chord.js +103 -0
  115. package/src/write/add-text-if.js +33 -0
  116. package/src/write/bottom-text.js +79 -0
  117. package/src/write/calcHeight.js +17 -0
  118. package/src/write/classes.js +100 -0
  119. package/src/write/draw/absolute.js +68 -0
  120. package/src/write/draw/beam.js +56 -0
  121. package/src/write/draw/brace.js +106 -0
  122. package/src/write/draw/crescendo.js +38 -0
  123. package/src/write/draw/debug-box.js +8 -0
  124. package/src/write/draw/draw.js +56 -0
  125. package/src/write/draw/dynamics.js +20 -0
  126. package/src/write/draw/ending.js +46 -0
  127. package/src/write/draw/group-elements.js +66 -0
  128. package/src/write/draw/horizontal-line.js +25 -0
  129. package/src/write/draw/non-music.js +50 -0
  130. package/src/write/draw/print-line.js +24 -0
  131. package/src/write/draw/print-path.js +7 -0
  132. package/src/write/draw/print-stem.js +30 -0
  133. package/src/write/draw/print-symbol.js +59 -0
  134. package/src/write/draw/print-vertical-line.js +18 -0
  135. package/src/write/draw/relative.js +77 -0
  136. package/src/write/draw/round-number.js +5 -0
  137. package/src/write/draw/selectables.js +59 -0
  138. package/src/write/draw/separator.js +16 -0
  139. package/src/write/draw/set-paper-size.js +45 -0
  140. package/src/write/{sprintf.js → draw/sprintf.js} +0 -0
  141. package/src/write/draw/staff-group.js +226 -0
  142. package/src/write/draw/staff-line.js +9 -0
  143. package/src/write/draw/staff.js +33 -0
  144. package/src/write/draw/tab-line.js +40 -0
  145. package/src/write/draw/tempo.js +45 -0
  146. package/src/write/draw/text.js +71 -0
  147. package/src/write/draw/tie.js +97 -0
  148. package/src/write/draw/triplet.js +46 -0
  149. package/src/write/draw/voice.js +102 -0
  150. package/src/write/format-jazz-chord.js +15 -0
  151. package/src/write/free-text.js +41 -0
  152. package/src/write/get-font-and-attr.js +37 -0
  153. package/src/write/get-text-size.js +56 -0
  154. package/src/write/highlight.js +11 -0
  155. package/src/write/layout/VoiceElements.js +121 -0
  156. package/src/write/layout/beam.js +213 -0
  157. package/src/write/layout/get-left-edge-of-staff.js +56 -0
  158. package/src/write/layout/getBarYAt.js +6 -0
  159. package/src/write/layout/layout.js +94 -0
  160. package/src/write/layout/setUpperAndLowerElements.js +232 -0
  161. package/src/write/layout/staffGroup.js +146 -0
  162. package/src/write/layout/triplet.js +75 -0
  163. package/src/write/layout/voice.js +137 -0
  164. package/src/write/selection.js +188 -70
  165. package/src/write/separator.js +10 -0
  166. package/src/write/set-class.js +21 -0
  167. package/src/write/subtitle.js +12 -0
  168. package/src/write/svg.js +95 -43
  169. package/src/write/top-text.js +54 -0
  170. package/src/write/unhighlight.js +11 -0
  171. package/temp.txt +17 -0
  172. package/test.js +27 -64
  173. package/types/index.d.ts +1095 -0
  174. package/version.js +1 -1
  175. package/.babelrc +0 -5
  176. package/.eslintrc +0 -3
  177. package/.gitmodules +0 -3
  178. package/abcjs-midi.css +0 -166
  179. package/build-utils/loadPresets.js +0 -14
  180. package/build-utils/presets/webpack.analyze.js +0 -6
  181. package/build-utils/presets/webpack.optimize.js +0 -30
  182. package/build-utils/webpack.development.js +0 -14
  183. package/build-utils/webpack.production.js +0 -35
  184. package/deploy-docs.sh +0 -25
  185. package/docs/README.md +0 -33
  186. package/fix-versions.sh +0 -23
  187. package/mei.js +0 -43
  188. package/midi.js +0 -62
  189. package/src/api/abc_tunebook_midi.js +0 -116
  190. package/src/midi/abc_midi_controls.js +0 -701
  191. package/src/midi/abc_midi_flattener.js +0 -1119
  192. package/src/midi/abc_midi_js_preparer.js +0 -243
  193. package/src/midi/abc_midi_sequencer.js +0 -401
  194. package/src/midi/abc_midi_ui_generator.js +0 -86
  195. package/src/plugin/abc_plugin_midi.js +0 -220
  196. package/src/synth/images/loop.svg +0 -61
  197. package/src/synth/images/pause.svg +0 -6
  198. package/src/synth/images/play.svg +0 -5
  199. package/src/transform/abc2abc_write.js +0 -395
  200. package/static-wrappers/basic.js +0 -2
  201. package/static-wrappers/midi.js +0 -2
  202. package/static-wrappers/plugin-midi.js +0 -6
  203. package/static-wrappers/plugin.js +0 -6
  204. package/webpack.config.js +0 -29
@@ -0,0 +1,71 @@
1
+ var roundNumber = require("./round-number");
2
+
3
+ function renderText(renderer, params, alreadyInGroup) {
4
+ var y = params.y;
5
+ if (params.lane) {
6
+ var laneMargin = params.dim.font.size*0.25;
7
+ y += (params.dim.font.size + laneMargin) * params.lane;
8
+ }
9
+
10
+ var hash;
11
+ if (params.dim) {
12
+ hash = params.dim;
13
+ hash.attr.class = params.klass;
14
+ } else
15
+ hash = renderer.controller.getFontAndAttr.calc(params.type, params.klass);
16
+ if (params.anchor)
17
+ hash.attr["text-anchor"] = params.anchor;
18
+ hash.attr.x = params.x;
19
+ hash.attr.y = y;
20
+ if (!params.centerVertically)
21
+ hash.attr.y += hash.font.size;
22
+ if (params.type === 'debugfont') {
23
+ console.log("Debug msg: " + params.text);
24
+ hash.attr.stroke = "#ff0000";
25
+ }
26
+ if (params.cursor) {
27
+ hash.attr.cursor = params.cursor;
28
+ }
29
+
30
+ var text = params.text.replace(/\n\n/g, "\n \n");
31
+ text = text.replace(/^\n/, "\xA0\n");
32
+
33
+ if (hash.font.box) {
34
+ if (!alreadyInGroup)
35
+ renderer.paper.openGroup({klass: hash.attr['class'], fill: renderer.foregroundColor, "data-name": params.name});
36
+ if (hash.attr["text-anchor"] === "end") {
37
+ hash.attr.x -= hash.font.padding;
38
+ } else if (hash.attr["text-anchor"] === "start") {
39
+ hash.attr.x += hash.font.padding;
40
+ }
41
+ hash.attr.y += hash.font.padding;
42
+ delete hash.attr['class'];
43
+ }
44
+ if (params.noClass)
45
+ delete hash.attr['class'];
46
+ hash.attr.x = roundNumber(hash.attr.x);
47
+ hash.attr.y = roundNumber(hash.attr.y);
48
+ if (params.name)
49
+ hash.attr["data-name"] = params.name;
50
+ var elem = renderer.paper.text(text, hash.attr);
51
+ if (hash.font.box) {
52
+ var size = elem.getBBox();
53
+
54
+ var delta = 0;
55
+ if (hash.attr["text-anchor"] === "middle") {
56
+ delta = size.width / 2 + hash.font.padding;
57
+ } else if (hash.attr["text-anchor"] === "end") {
58
+ delta = size.width + hash.font.padding * 2;
59
+ }
60
+ var deltaY = 0;
61
+ if (params.centerVertically) {
62
+ deltaY = size.height - hash.font.padding;
63
+ }
64
+ renderer.paper.rect({ "data-name": "box", x: Math.round(params.x - delta), y: Math.round(y - deltaY), width: Math.round(size.width + hash.font.padding*2), height: Math.round(size.height + hash.font.padding*2)});
65
+ if (!alreadyInGroup)
66
+ elem = renderer.paper.closeGroup();
67
+ }
68
+ return elem;
69
+ }
70
+
71
+ module.exports = renderText;
@@ -0,0 +1,97 @@
1
+ var sprintf = require('./sprintf');
2
+ var roundNumber = require("./round-number");
3
+
4
+ function drawTie(renderer, params, linestartx, lineendx, selectables) {
5
+ layout(params, linestartx, lineendx);
6
+
7
+ var klass = '';
8
+ if (params.anchor1) {
9
+ klass += 'abcjs-start-m' + params.anchor1.parent.counters.measure + '-n' + params.anchor1.parent.counters.note;
10
+ } else
11
+ klass += 'abcjs-start-edge';
12
+ if (params.anchor2) {
13
+ klass += ' abcjs-end-m' + params.anchor2.parent.counters.measure + '-n' + params.anchor2.parent.counters.note;
14
+ } else
15
+ klass += ' abcjs-end-edge';
16
+ if (params.hint)
17
+ klass = "abcjs-hint";
18
+ var fudgeY = params.fixedY ? 1.5 : 0; // TODO-PER: This just compensates for drawArc, which contains too much knowledge of ties and slurs.
19
+ var el = drawArc(renderer, params.startX, params.endX, params.startY+fudgeY, params.endY+fudgeY, params.above, klass, params.isTie, params.dotted);
20
+ selectables.wrapSvgEl({ el_type: "slur", startChar: -1, endChar: -1 }, el);
21
+ return [el];
22
+ }
23
+
24
+ // TODO-PER: I think params part should have been done earlier in the layout pass.
25
+ var layout = function (params, lineStartX, lineEndX) {
26
+ // We now have all of the input variables set, so we can figure out the start and ending x,y coordinates, and finalize the direction of the arc.
27
+
28
+ // Ties and slurs are handled a little differently, so do calculations for them separately.
29
+ if (!params.anchor1 || !params.anchor2)
30
+ params.isTie = true; // if the slur goes off the end of the line, then draw it like a tie
31
+ else if (params.anchor1.pitch === params.anchor2.pitch && params.internalNotes.length === 0)
32
+ params.isTie = true;
33
+ else
34
+ params.isTie = false;
35
+
36
+ if (params.isTie) {
37
+ params.calcTieDirection();
38
+ params.calcX(lineStartX, lineEndX);
39
+ params.calcTieY();
40
+
41
+ } else {
42
+ params.calcSlurDirection();
43
+ params.calcX(lineStartX, lineEndX);
44
+ params.calcSlurY();
45
+ }
46
+ params.avoidCollisionAbove();
47
+ };
48
+
49
+ var drawArc = function(renderer, x1, x2, pitch1, pitch2, above, klass, isTie, dotted) {
50
+ // If it is a tie vs. a slur, draw it shallower.
51
+ var spacing = isTie ? 1.2 : 1.5;
52
+
53
+ x1 = roundNumber(x1 + 6);
54
+ x2 = roundNumber(x2 + 4);
55
+ pitch1 = pitch1 + ((above)?spacing:-spacing);
56
+ pitch2 = pitch2 + ((above)?spacing:-spacing);
57
+ var y1 = roundNumber(renderer.calcY(pitch1));
58
+ var y2 = roundNumber(renderer.calcY(pitch2));
59
+
60
+ //unit direction vector
61
+ var dx = x2-x1;
62
+ var dy = y2-y1;
63
+ var norm= Math.sqrt(dx*dx+dy*dy);
64
+ var ux = dx/norm;
65
+ var uy = dy/norm;
66
+
67
+ var flatten = norm/3.5;
68
+ var maxFlatten = isTie ? 10 : 25; // If it is a tie vs. a slur, draw it shallower.
69
+ var curve = ((above)?-1:1)*Math.min(maxFlatten, Math.max(4, flatten));
70
+
71
+ var controlx1 = roundNumber(x1+flatten*ux-curve*uy);
72
+ var controly1 = roundNumber(y1+flatten*uy+curve*ux);
73
+ var controlx2 = roundNumber(x2-flatten*ux-curve*uy);
74
+ var controly2 = roundNumber(y2-flatten*uy+curve*ux);
75
+ var thickness = 2;
76
+ if (klass)
77
+ klass += ' slur';
78
+ else
79
+ klass = 'slur';
80
+ klass += isTie ? ' tie' : ' legato';
81
+ var ret;
82
+ if (dotted) {
83
+ klass += ' dotted';
84
+ var pathString2 = sprintf("M %f %f C %f %f %f %f %f %f", x1, y1,
85
+ controlx1, controly1, controlx2, controly2, x2, y2);
86
+ ret = renderer.paper.path({path:pathString2, stroke:renderer.foregroundColor, fill:"none", 'stroke-dasharray': "5 5", 'class': renderer.controller.classes.generate(klass), "data-name": isTie ? "tie" : "slur"});
87
+ } else {
88
+ var pathString = sprintf("M %f %f C %f %f %f %f %f %f C %f %f %f %f %f %f z", x1, y1,
89
+ controlx1, controly1, controlx2, controly2, x2, y2,
90
+ roundNumber(controlx2 - thickness * uy), roundNumber(controly2 + thickness * ux), roundNumber(controlx1 - thickness * uy), roundNumber(controly1 + thickness * ux), x1, y1);
91
+ ret = renderer.paper.path({path:pathString, stroke:"none", fill:renderer.foregroundColor, 'class': renderer.controller.classes.generate(klass), "data-name": isTie ? "tie" : "slur"});
92
+ }
93
+
94
+ return ret;
95
+ };
96
+
97
+ module.exports = drawTie;
@@ -0,0 +1,46 @@
1
+ var sprintf = require('./sprintf');
2
+ var renderText = require('./text');
3
+ var printPath = require('./print-path');
4
+ var roundNumber = require("./round-number");
5
+
6
+ function drawTriplet(renderer, params, selectables) {
7
+ renderer.paper.openGroup({ klass: renderer.controller.classes.generate('triplet '+params.durationClass), "data-name": "triplet"});
8
+ if (!params.hasBeam) {
9
+ drawBracket(renderer, params.anchor1.x, params.startNote, params.anchor2.x + params.anchor2.w, params.endNote);
10
+ }
11
+ // HACK: adjust the position of "3". It is too high in all cases so we fudge it by subtracting 1 here.
12
+ renderText(renderer, {x: params.xTextPos, y: renderer.calcY(params.yTextPos - 1), text: "" + params.number, type: 'tripletfont', anchor: "middle", centerVertically: true, noClass: true, name: ""+params.number}, true);
13
+ var g = renderer.paper.closeGroup();
14
+ selectables.wrapSvgEl({ el_type: "triplet", startChar: -1, endChar: -1 }, g);
15
+ return g;
16
+ }
17
+
18
+ function drawLine(l, t, r, b) {
19
+ return sprintf("M %f %f L %f %f", roundNumber(l), roundNumber(t), roundNumber(r), roundNumber(b));
20
+ }
21
+
22
+ function drawBracket(renderer, x1, y1, x2, y2) {
23
+ y1 = renderer.calcY(y1);
24
+ y2 = renderer.calcY(y2);
25
+ var bracketHeight = 5;
26
+
27
+ // Draw vertical lines at the beginning and end
28
+ var pathString = "";
29
+ pathString += drawLine(x1, y1, x1, y1 + bracketHeight);
30
+ pathString += drawLine(x2, y2, x2, y2 + bracketHeight);
31
+
32
+ // figure out midpoints to draw the broken line.
33
+ var midX = x1 + (x2-x1)/2;
34
+ //var midY = y1 + (y2-y1)/2;
35
+ var gapWidth = 8;
36
+ var slope = (y2 - y1) / (x2 - x1);
37
+ var leftEndX = midX - gapWidth;
38
+ var leftEndY = y1 + (leftEndX - x1) * slope;
39
+ pathString += drawLine( x1, y1, leftEndX, leftEndY);
40
+ var rightStartX = midX + gapWidth;
41
+ var rightStartY = y1 + (rightStartX - x1) * slope;
42
+ pathString += drawLine( rightStartX, rightStartY, x2, y2);
43
+ printPath(renderer, {path: pathString, stroke: renderer.foregroundColor, "data-name": "triplet-bracket"});
44
+ }
45
+
46
+ module.exports = drawTriplet;
@@ -0,0 +1,102 @@
1
+ var drawCrescendo = require('./crescendo');
2
+ var drawDynamics = require('./dynamics');
3
+ var drawTriplet = require('./triplet');
4
+ var drawEnding = require('./ending');
5
+ var drawTie = require('./tie');
6
+ var drawBeam = require('./beam');
7
+ var renderText = require('./text');
8
+ var drawAbsolute = require('./absolute');
9
+
10
+ function drawVoice(renderer, params, bartop, selectables, staffPos) {
11
+ var width = params.w-1;
12
+ renderer.staffbottom = params.staff.bottom;
13
+
14
+ if (params.header) { // print voice name
15
+ var textEl = renderText(renderer, {x: renderer.padding.left, y: renderer.calcY(params.headerPosition), text: params.header, type: 'voicefont', klass: 'staff-extra voice-name', anchor: 'start', centerVertically: true, name: "voice-name"}, true);
16
+ selectables.wrapSvgEl({ el_type: "voiceName", startChar: -1, endChar: -1, text: params.header }, textEl);
17
+ }
18
+
19
+ var i;
20
+ var child;
21
+ var foundNote = false;
22
+ for (i=0; i < params.children.length; i++) {
23
+ child = params.children[i];
24
+ if (child.type === 'note' || child.type === 'rest')
25
+ foundNote = true;
26
+ var justInitializedMeasureNumber = false;
27
+ if (child.type !== 'staff-extra' && !renderer.controller.classes.isInMeasure()) {
28
+ renderer.controller.classes.startMeasure();
29
+ justInitializedMeasureNumber = true;
30
+ }
31
+ switch (child.type) {
32
+ // case "tempo":
33
+ // child.elemset = drawTempo(renderer, child);
34
+ // break;
35
+ default:
36
+ if (params.staff.isTabStaff) {
37
+ child.invisible = false;
38
+ if ( child.type == 'bar' ) {
39
+ if (child.abcelem.lastBar) {
40
+ bartop = params.topLine;
41
+ }
42
+ }
43
+ }
44
+ drawAbsolute(renderer, child,(params.barto || i === params.children.length - 1) ? bartop : 0, selectables, staffPos);
45
+ }
46
+ if (child.type === 'note' || isNonSpacerRest(child))
47
+ renderer.controller.classes.incrNote();
48
+ if (child.type === 'bar' && !justInitializedMeasureNumber && foundNote) {
49
+ renderer.controller.classes.incrMeasure();
50
+ }
51
+ }
52
+
53
+ renderer.controller.classes.startMeasure();
54
+
55
+ for (i = 0; i < params.beams.length; i++) {
56
+ var beam = params.beams[i];
57
+ if (beam === 'bar') {
58
+ renderer.controller.classes.incrMeasure();
59
+ } else
60
+ drawBeam(renderer, beam, selectables); // beams must be drawn first for proper printing of triplets, slurs and ties.
61
+ }
62
+
63
+ renderer.controller.classes.startMeasure();
64
+ for (i = 0; i < params.otherchildren.length; i++) {
65
+ child = params.otherchildren[i];
66
+ if (child === 'bar') {
67
+ renderer.controller.classes.incrMeasure();
68
+ } else {
69
+ switch (child.type) {
70
+ case "CrescendoElem":
71
+ child.elemset = drawCrescendo(renderer, child, selectables);
72
+ break;
73
+ case "DynamicDecoration":
74
+ child.elemset = drawDynamics(renderer, child, selectables);
75
+ break;
76
+ case "TripletElem":
77
+ drawTriplet(renderer, child, selectables);
78
+ break;
79
+ case "EndingElem":
80
+ child.elemset = drawEnding(renderer, child, params.startx + 10, width, selectables);
81
+ break;
82
+ case "TieElem":
83
+ child.elemset = drawTie(renderer, child, params.startx + 10, width, selectables);
84
+ break;
85
+ default:
86
+ console.log(child);
87
+ drawAbsolute(renderer, child, params.startx + 10, width, selectables, staffPos);
88
+ }
89
+ }
90
+ }
91
+
92
+ }
93
+
94
+ function isNonSpacerRest(elem) {
95
+ if (elem.type !== 'rest')
96
+ return false;
97
+ if (elem.abcelem && elem.abcelem.rest && elem.abcelem.rest.type !== 'spacer')
98
+ return true;
99
+ return false;
100
+ }
101
+
102
+ module.exports = drawVoice;
@@ -0,0 +1,15 @@
1
+ function formatJazzChord(chordString) {
2
+ // This puts markers in the pieces of the chord that are read by the svg creator.
3
+ // After the main part of the chord (the letter, a sharp or flat, and "m") a marker is added. Before a slash a marker is added.
4
+ var lines = chordString.split("\n");
5
+ for (var i = 0; i < lines.length; i++) {
6
+ var chord = lines[i];
7
+ // If the chord isn't in a recognizable format then just skip the formatting.
8
+ var reg = chord.match(/^([ABCDEFG][♯♭]?)?([^\/]+)?(\/[ABCDEFG][#b]?)?/);
9
+ if (reg)
10
+ lines[i] = (reg[1]?reg[1]:'') + "\x03" + (reg[2]?reg[2]:'') + "\x03" + (reg[3]?reg[3]:'');
11
+ }
12
+ return lines.join("\n");
13
+ }
14
+
15
+ module.exports = formatJazzChord;
@@ -0,0 +1,41 @@
1
+ function FreeText(info, vskip, getFontAndAttr, paddingLeft, width, getTextSize) {
2
+ var text = info.text;
3
+ this.rows = [];
4
+ var size;
5
+ if (vskip)
6
+ this.rows.push({move: vskip});
7
+ var hash = getFontAndAttr.calc('textfont', 'defined-text');
8
+ if (text === "") { // we do want to print out blank lines if they have been specified.
9
+ this.rows.push({move: hash.attr['font-size'] * 2}); // move the distance of the line, plus the distance of the margin, which is also one line.
10
+ } else if (typeof text === 'string') {
11
+ this.rows.push({move: hash.attr['font-size']/2}); // TODO-PER: move down some - the y location should be the top of the text, but we output text specifying the center line.
12
+ this.rows.push({left: paddingLeft, text: text, font: 'textfont', klass: 'defined-text', anchor: "start", startChar: info.startChar, endChar: info.endChar, absElemType: "freeText", name: "free-text"});
13
+ size = getTextSize.calc(text, 'textfont', 'defined-text');
14
+ this.rows.push({move: size.height});
15
+ } else if (text) {
16
+ var maxHeight = 0;
17
+ var leftSide = paddingLeft;
18
+ var currentFont = 'textfont';
19
+ for (var i = 0; i < text.length; i++) {
20
+ if (text[i].font) {
21
+ currentFont = text[i].font;
22
+ } else
23
+ currentFont = 'textfont';
24
+ this.rows.push({left: leftSide, text: text[i].text, font: currentFont, klass: 'defined-text', anchor: 'start', startChar: info.startChar, endChar: info.endChar, absElemType: "freeText", name: "free-text"});
25
+ size = getTextSize.calc(text[i].text, getFontAndAttr.calc(currentFont, 'defined-text').font, 'defined-text');
26
+ leftSide += size.width + size.height/2; // add a little padding to the right side. The height of the font is probably a close enough approximation.
27
+ maxHeight = Math.max(maxHeight, size.height)
28
+ }
29
+ this.rows.push({move: maxHeight});
30
+ } else {
31
+ // The structure is wrong here: it requires an array to do centering, but it shouldn't have.
32
+ if (info.length === 1) {
33
+ var x = width / 2;
34
+ this.rows.push({left: x, text: info[0].text, font: 'textfont', klass: 'defined-text', anchor: 'middle', startChar: info.startChar, endChar: info.endChar, absElemType: "freeText", name: "free-text"});
35
+ size = getTextSize.calc(info[0].text, 'textfont', 'defined-text');
36
+ this.rows.push({move: size.height});
37
+ }
38
+ }
39
+ }
40
+
41
+ module.exports = FreeText;
@@ -0,0 +1,37 @@
1
+ var GetFontAndAttr = function GetFontAndAttr(formatting, classes) {
2
+ this.formatting = formatting;
3
+ this.classes = classes;
4
+ };
5
+
6
+ GetFontAndAttr.prototype.updateFonts = function(fontOverrides) {
7
+ if (fontOverrides.gchordfont)
8
+ this.formatting.gchordfont = fontOverrides.gchordfont;
9
+ if (fontOverrides.tripletfont)
10
+ this.formatting.tripletfont = fontOverrides.tripletfont;
11
+ if (fontOverrides.annotationfont)
12
+ this.formatting.annotationfont = fontOverrides.annotationfont;
13
+ if (fontOverrides.vocalfont)
14
+ this.formatting.vocalfont = fontOverrides.vocalfont;
15
+ };
16
+
17
+ GetFontAndAttr.prototype.calc = function(type, klass) {
18
+ var font;
19
+ if (typeof type === 'string') {
20
+ font = this.formatting[type];
21
+ // Raphael deliberately changes the font units to pixels for some reason, so we need to change points to pixels here.
22
+ if (font)
23
+ font = {face: font.face, size: Math.round(font.size * 4 / 3), decoration: font.decoration, style: font.style, weight: font.weight, box: font.box};
24
+ else
25
+ font = {face: "Arial", size: Math.round(12 * 4 / 3), decoration: "underline", style: "normal", weight: "normal"};
26
+ } else
27
+ font = {face: type.face, size: Math.round(type.size * 4 / 3), decoration: type.decoration, style: type.style, weight: type.weight, box: type.box};
28
+ var paddingPercent = this.formatting.fontboxpadding ? this.formatting.fontboxpadding : 0.1
29
+ font.padding = font.size * paddingPercent;
30
+
31
+ var attr = {"font-size": font.size, 'font-style': font.style,
32
+ "font-family": font.face, 'font-weight': font.weight, 'text-decoration': font.decoration,
33
+ 'class': this.classes.generate(klass) };
34
+ return { font: font, attr: attr };
35
+ };
36
+
37
+ module.exports = GetFontAndAttr;
@@ -0,0 +1,56 @@
1
+ var GetTextSize = function GetTextSize(getFontAndAttr, svg) {
2
+ this.getFontAndAttr = getFontAndAttr;
3
+ this.svg = svg;
4
+ };
5
+
6
+ GetTextSize.prototype.updateFonts = function(fontOverrides) {
7
+ this.getFontAndAttr.updateFonts(fontOverrides);
8
+ };
9
+
10
+ GetTextSize.prototype.attr = function(type, klass) {
11
+ return this.getFontAndAttr.calc(type, klass);
12
+ };
13
+
14
+ GetTextSize.prototype.calc = function(text, type, klass, el) {
15
+ var hash;
16
+ // This can be passed in either a string or a font. If it is a string it names one of the standard fonts.
17
+ if (typeof type === 'string')
18
+ hash = this.attr(type, klass);
19
+ else {
20
+ hash = {
21
+ font: {
22
+ face: type.face,
23
+ size: type.size,
24
+ decoration: type.decoration,
25
+ style: type.style,
26
+ weight: type.weight
27
+ },
28
+ attr: {
29
+ "font-size": type.size,
30
+ "font-style": type.style,
31
+ "font-family": type.face,
32
+ "font-weight": type.weight,
33
+ "text-decoration": type.decoration,
34
+ "class": this.getFontAndAttr.classes.generate(klass)
35
+ }
36
+ }
37
+ }
38
+ var size = this.svg.getTextSize(text, hash.attr, el);
39
+ if (hash.font.box) {
40
+ // Add padding and an equal margin to each side.
41
+ return { height: size.height + hash.font.padding*4, width: size.width + hash.font.padding*4 };
42
+ }
43
+ return size;
44
+ };
45
+
46
+ GetTextSize.prototype.baselineToCenter = function(text, type, klass, index, total) {
47
+ // This is for the case where SVG wants to use the baseline of the first line as the Y coordinate.
48
+ // If there are multiple lines of text or there is an array of text then that will not be centered so this adjusts it.
49
+ var height = this.calc(text, type, klass).height;
50
+ var fontHeight = this.attr(type, klass).font.size;
51
+
52
+ return height * 0.5 + (total - index - 2) * fontHeight;
53
+ };
54
+
55
+
56
+ module.exports = GetTextSize;
@@ -0,0 +1,11 @@
1
+ var setClass = require('./set-class');
2
+
3
+ var highlight = function (klass, color) {
4
+ if (klass === undefined)
5
+ klass = "abcjs-note_selected";
6
+ if (color === undefined)
7
+ color = "#ff0000";
8
+ setClass(this.elemset, klass, "", color);
9
+ };
10
+
11
+ module.exports = highlight;
@@ -0,0 +1,121 @@
1
+ var VoiceElement = function VoiceElements() {}
2
+
3
+ VoiceElement.beginLayout = function (startx, voice) {
4
+ voice.i=0;
5
+ voice.durationindex=0;
6
+ //this.ii=this.children.length;
7
+ voice.startx=startx;
8
+ voice.minx=startx; // furthest left to where negatively positioned elements are allowed to go
9
+ voice.nextx=startx; // x position where the next element of this voice should be placed assuming no other voices and no fixed width constraints
10
+ voice.spacingduration=0; // duration left to be laid out in current iteration (omitting additional spacing due to other aspects, such as bars, dots, sharps and flats)
11
+ };
12
+
13
+ VoiceElement.layoutEnded = function (voice) {
14
+ return (voice.i>=voice.children.length);
15
+ };
16
+
17
+ VoiceElement.getNextX = function (voice) {
18
+ return Math.max(voice.minx, voice.nextx);
19
+ };
20
+
21
+ // number of spacing units expected for next positioning
22
+ VoiceElement.getSpacingUnits = function (voice) {
23
+ return Math.sqrt(voice.spacingduration*8);
24
+ };
25
+
26
+ // Try to layout the element at index this.i
27
+ // x - position to try to layout the element at
28
+ // spacing - base spacing
29
+ // can't call this function more than once per iteration
30
+ VoiceElement.layoutOneItem = function (x, spacing, voice, minPadding, firstVoice) {
31
+ var child = voice.children[voice.i];
32
+ if (!child) return 0;
33
+ var er = x - voice.minx; // available extrawidth to the left
34
+ var pad = voice.durationindex + child.duration > 0 ? minPadding : 0; // only add padding to the items that aren't fixed to the left edge.
35
+ // See if this item overlaps the item in the first voice. If firstVoice is undefined then there's nothing to compare.
36
+ if (child.abcelem.el_type === "note" && !child.abcelem.rest && voice.voicenumber !== 0 && firstVoice) {
37
+ var firstChild = firstVoice.children[firstVoice.i];
38
+ // It overlaps if the either the child's top or bottom is inside the firstChild's or at least within 1
39
+ // A special case is if the element is on the same line then it can share a note head, if the notehead is the same
40
+ var overlaps = firstChild &&
41
+ ((child.abcelem.maxpitch <= firstChild.abcelem.maxpitch+1 && child.abcelem.maxpitch >= firstChild.abcelem.minpitch-1) ||
42
+ (child.abcelem.minpitch <= firstChild.abcelem.maxpitch+1 && child.abcelem.minpitch >= firstChild.abcelem.minpitch-1))
43
+ // See if they can share a note head
44
+ if (overlaps && child.abcelem.minpitch === firstChild.abcelem.minpitch && child.abcelem.maxpitch === firstChild.abcelem.maxpitch &&
45
+ firstChild.heads && firstChild.heads.length > 0 && child.heads && child.heads.length > 0 &&
46
+ firstChild.heads[0].c === child.heads[0].c)
47
+ overlaps = false;
48
+ // If this note overlaps the note in the first voice and we haven't moved the note yet (this can be called multiple times)
49
+ if (overlaps) {
50
+ // I think that firstChild should always have at least one note head, but defensively make sure.
51
+ // There was a problem with this being called more than once so if a value is adjusted then it is saved so it is only adjusted once.
52
+ var firstChildNoteWidth = firstChild.heads && firstChild.heads.length > 0 ? firstChild.heads[0].realWidth : firstChild.fixed.w;
53
+ if (!child.adjustedWidth)
54
+ child.adjustedWidth = firstChildNoteWidth + child.w;
55
+ child.w = child.adjustedWidth
56
+ for (var j = 0; j < child.children.length; j++) {
57
+ var relativeChild = child.children[j];
58
+ if (relativeChild.name.indexOf("accidental") < 0) {
59
+ if (!relativeChild.adjustedWidth)
60
+ relativeChild.adjustedWidth = relativeChild.dx + firstChildNoteWidth;
61
+ relativeChild.dx = relativeChild.adjustedWidth
62
+ }
63
+ }
64
+
65
+ }
66
+ }
67
+ var extraWidth = getExtraWidth(child, pad);
68
+ if (er<extraWidth) { // shift right by needed amount
69
+ // There's an exception if a bar element is after a Part element, there is no shift.
70
+ if (voice.i === 0 || child.type !== 'bar' || (voice.children[voice.i-1].type !== 'part' && voice.children[voice.i-1].type !== 'tempo') )
71
+ x+=extraWidth-er;
72
+ }
73
+ child.setX(x);
74
+
75
+ voice.spacingduration = child.duration;
76
+ //update minx
77
+ voice.minx = x+getMinWidth(child); // add necessary layout space
78
+ if (voice.i!==voice.children.length-1) voice.minx+=child.minspacing; // add minimumspacing except on last elem
79
+
80
+ this.updateNextX(x, spacing, voice);
81
+
82
+ // contribute to staff y position
83
+ //this.staff.top = Math.max(child.top,this.staff.top);
84
+ //this.staff.bottom = Math.min(child.bottom,this.staff.bottom);
85
+
86
+ return x; // where we end up having placed the child
87
+ };
88
+
89
+ VoiceElement.shiftRight = function (dx, voice) {
90
+ var child = voice.children[voice.i];
91
+ if (!child) return;
92
+ child.setX(child.x+dx);
93
+ voice.minx+=dx;
94
+ voice.nextx+=dx;
95
+ };
96
+
97
+ // call when spacingduration has been updated
98
+ VoiceElement.updateNextX = function (x, spacing, voice) {
99
+ voice.nextx= x + (spacing*Math.sqrt(voice.spacingduration*8));
100
+ };
101
+
102
+ VoiceElement.updateIndices = function (voice) {
103
+ if (!this.layoutEnded(voice)) {
104
+ voice.durationindex += voice.children[voice.i].duration;
105
+ if (voice.children[voice.i].type === 'bar') voice.durationindex = Math.round(voice.durationindex*64)/64; // everytime we meet a barline, do rounding to nearest 64th
106
+ voice.i++;
107
+ }
108
+ };
109
+
110
+ function getExtraWidth(child, minPadding) { // space needed to the left of the note
111
+ var padding = 0;
112
+ if (child.type === 'note' || child.type === 'bar')
113
+ padding = minPadding;
114
+ return -child.extraw + padding;
115
+ }
116
+
117
+ function getMinWidth(child) { // absolute space taken to the right of the note
118
+ return child.w;
119
+ }
120
+
121
+ module.exports = VoiceElement;