abcjs 6.0.0-beta.8 → 6.0.1

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 +959 -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 +28232 -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 +239 -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 +8 -18
  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 +15256 -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,100 @@
1
+ var Classes = function Classes(options) {
2
+ this.shouldAddClasses = options.shouldAddClasses;
3
+ this.reset();
4
+ }
5
+
6
+ Classes.prototype.reset = function () {
7
+ this.lineNumber = null;
8
+ this.voiceNumber = null;
9
+ this.measureNumber = null;
10
+ this.measureTotalPerLine = [];
11
+ this.noteNumber = null;
12
+ }
13
+
14
+ Classes.prototype.incrLine = function () {
15
+ if (this.lineNumber === null)
16
+ this.lineNumber = 0;
17
+ else
18
+ this.lineNumber++;
19
+ this.voiceNumber = null;
20
+ this.measureNumber = null;
21
+ this.noteNumber = null;
22
+ };
23
+
24
+ Classes.prototype.incrVoice = function () {
25
+ if (this.voiceNumber === null)
26
+ this.voiceNumber = 0;
27
+ else
28
+ this.voiceNumber++;
29
+ this.measureNumber = null;
30
+ this.noteNumber = null;
31
+ };
32
+
33
+ Classes.prototype.isInMeasure = function () {
34
+ return this.measureNumber !== null;
35
+ };
36
+
37
+ Classes.prototype.newMeasure = function () {
38
+ if (this.measureNumber)
39
+ this.measureTotalPerLine[this.lineNumber] = this.measureNumber;
40
+ this.measureNumber = null;
41
+ this.noteNumber = null;
42
+ };
43
+
44
+ Classes.prototype.startMeasure = function () {
45
+ this.measureNumber = 0;
46
+ this.noteNumber = 0;
47
+ };
48
+
49
+ Classes.prototype.incrMeasure = function () {
50
+ this.measureNumber++;
51
+ this.noteNumber = 0;
52
+ };
53
+
54
+ Classes.prototype.incrNote = function () {
55
+ this.noteNumber++;
56
+ };
57
+
58
+ Classes.prototype.measureTotal = function () {
59
+ var total = 0;
60
+ for (var i = 0; i < this.lineNumber; i++)
61
+ total += this.measureTotalPerLine[i] ? this.measureTotalPerLine[i] : 0; // This can be null when non-music things are present.
62
+ if (this.measureNumber)
63
+ total += this.measureNumber;
64
+ return total;
65
+ };
66
+
67
+ Classes.prototype.getCurrent = function (c) {
68
+ return {
69
+ line: this.lineNumber,
70
+ measure: this.measureNumber,
71
+ measureTotal: this.measureTotal(),
72
+ voice: this.voiceNumber,
73
+ note: this.noteNumber
74
+ };
75
+ };
76
+
77
+ Classes.prototype.generate = function (c) {
78
+ if (!this.shouldAddClasses)
79
+ return "";
80
+ var ret = [];
81
+ if (c && c.length > 0) ret.push(c);
82
+ if (this.lineNumber !== null) ret.push("l"+this.lineNumber);
83
+ if (this.measureNumber !== null) ret.push("m"+this.measureNumber);
84
+ if (this.measureNumber !== null) ret.push("mm"+this.measureTotal()); // measureNumber is null between measures so this is still the test for measureTotal
85
+ if (this.voiceNumber !== null) ret.push("v"+this.voiceNumber);
86
+ if (c && (c.indexOf('note') >= 0 || c.indexOf('rest') >= 0 || c.indexOf('lyric') >= 0 ) && this.noteNumber !== null) ret.push("n"+this.noteNumber);
87
+ // add a prefix to all classes that abcjs adds.
88
+ if (ret.length > 0) {
89
+ ret = ret.join(' '); // Some strings are compound classes - that is, specify more than one class in a string.
90
+ ret = ret.split(' ');
91
+ for (var i = 0; i < ret.length; i++) {
92
+ if (ret[i].indexOf('abcjs-') !== 0 && ret[i].length > 0) // if the prefix doesn't already exist and the class is not blank.
93
+ ret[i] = 'abcjs-' + ret[i];
94
+ }
95
+ }
96
+ return ret.join(' ');
97
+ };
98
+
99
+
100
+ module.exports = Classes;
@@ -0,0 +1,68 @@
1
+ var drawTempo = require('./tempo');
2
+ var drawRelativeElement = require('./relative');
3
+ var spacing = require('../abc_spacing');
4
+ var setClass = require('../set-class');
5
+ var elementGroup = require('./group-elements');
6
+
7
+ function drawAbsolute(renderer, params, bartop, selectables, staffPos) {
8
+ if (params.invisible) return;
9
+ var isTempo = params.children.length > 0 && params.children[0].type === "TempoElement";
10
+ params.elemset = [];
11
+ elementGroup.beginGroup(renderer.paper, renderer.controller);
12
+ for (var i=0; i<params.children.length; i++) {
13
+ var child = params.children[i];
14
+ switch (child.type) {
15
+ case "TempoElement":
16
+ drawTempo(renderer, child);
17
+ break;
18
+ default:
19
+ drawRelativeElement(renderer, child, bartop);
20
+ }
21
+ }
22
+ var klass = params.type;
23
+ if (params.type === 'note' || params.type === 'rest') {
24
+ params.counters = renderer.controller.classes.getCurrent();
25
+ klass += ' d' + Math.round(params.durationClass*1000)/1000;
26
+ klass = klass.replace(/\./g, '-');
27
+ if (params.abcelem.pitches) {
28
+ for (var j = 0; j < params.abcelem.pitches.length; j++) {
29
+ klass += ' p' + params.abcelem.pitches[j].pitch;
30
+ }
31
+ }
32
+ }
33
+ var g = elementGroup.endGroup(klass, params.type);
34
+ if (g) {
35
+ if (isTempo) {
36
+ params.startChar = params.abcelem.startChar;
37
+ params.endChar = params.abcelem.endChar;
38
+ selectables.add(params, g, false, staffPos);
39
+ } else {
40
+ params.elemset.push(g);
41
+ var isSelectable = false;
42
+ if (params.type === 'note' || params.type === 'tabNumber') {
43
+ isSelectable = true;
44
+ }
45
+ selectables.add(params, g, isSelectable, staffPos);
46
+ }
47
+ } else if (params.elemset.length > 0)
48
+ selectables.add(params, params.elemset[0], params.type === 'note', staffPos);
49
+ // If there was no output, then don't add to the selectables. This happens when using the "y" spacer, for instance.
50
+
51
+ if (params.klass)
52
+ setClass(params.elemset, "mark", "", "#00ff00");
53
+ if (params.hint)
54
+ setClass(params.elemset, "abcjs-hint", "", null);
55
+ params.abcelem.abselem = params;
56
+
57
+ if (params.heads && params.heads.length > 0) {
58
+ params.notePositions = [];
59
+ for (var jj = 0; jj < params.heads.length; jj++) {
60
+ params.notePositions.push({
61
+ x: params.heads[jj].x + params.heads[jj].w/2,
62
+ y: staffPos.zero - params.heads[jj].pitch * spacing.STEP
63
+ });
64
+ }
65
+ }
66
+ }
67
+
68
+ module.exports = drawAbsolute;
@@ -0,0 +1,56 @@
1
+ var printPath = require('./print-path');
2
+ var roundNumber = require("./round-number");
3
+
4
+ function drawBeam(renderer, params) {
5
+ if (params.beams.length === 0) return;
6
+
7
+ var pathString = "";
8
+ for (var i = 0; i < params.beams.length; i++) {
9
+ var beam = params.beams[i];
10
+ if (beam.split) {
11
+ var slope = getSlope(renderer, beam.startX, beam.startY, beam.endX, beam.endY);
12
+ var xes = [ ];
13
+ for (var j = 0; j < beam.split.length; j+=2) {
14
+ xes.push([beam.split[j], beam.split[j+1]]);
15
+ }
16
+ for (j = 0; j < xes.length; j++) {
17
+ var y1 = getY(beam.startX, beam.startY, slope, xes[j][0]);
18
+ var y2 = getY(beam.startX, beam.startY, slope, xes[j][1]);
19
+ pathString += draw(renderer, xes[j][0], y1, xes[j][1], y2, beam.dy);
20
+ }
21
+ } else
22
+ pathString += draw(renderer, beam.startX, beam.startY, beam.endX, beam.endY, beam.dy);
23
+ }
24
+ var durationClass = ("abcjs-d"+params.duration).replace(/\./g,"-");
25
+ var klasses = renderer.controller.classes.generate('beam-elem '+durationClass);
26
+ var el = printPath(renderer, {
27
+ path: pathString,
28
+ stroke: "none",
29
+ fill: renderer.foregroundColor,
30
+ 'class': klasses
31
+ });
32
+ return [el];
33
+ }
34
+
35
+ function draw(renderer, startX, startY, endX, endY, dy) {
36
+ // the X coordinates are actual coordinates, but the Y coordinates are in pitches.
37
+ startY = roundNumber(renderer.calcY(startY));
38
+ endY = roundNumber(renderer.calcY(endY));
39
+ startX = roundNumber(startX);
40
+ endX = roundNumber(endX);
41
+ var startY2 = roundNumber(startY+dy);
42
+ var endY2 = roundNumber(endY+dy);
43
+ return "M" + startX + " " + startY + " L" + endX + " " + endY +
44
+ "L" + endX + " " + endY2 + " L" + startX + " " + startY2 + "z";
45
+ }
46
+
47
+ function getSlope(renderer, startX, startY, endX, endY) {
48
+ return (endY - startY) / (endX - startX);
49
+ }
50
+
51
+ function getY(startX, startY, slope, currentX) {
52
+ var x = currentX - startX;
53
+ return startY + x*slope;
54
+ }
55
+
56
+ module.exports = drawBeam;
@@ -0,0 +1,106 @@
1
+ var sprintf = require('./sprintf');
2
+ var spacing = require('../abc_spacing');
3
+ var renderText = require('./text');
4
+
5
+ function drawBrace(renderer, params, selectables) {
6
+ // The absoluteY number is the spot where the note on the first ledger line is drawn (i.e. middle C if treble clef)
7
+ // The STEP offset here moves it to the top and bottom lines
8
+ var startY = params.startVoice.staff.absoluteY - spacing.STEP*10;
9
+ if (params.endVoice && params.endVoice.staff)
10
+ params.endY = params.endVoice.staff.absoluteY - spacing.STEP*2;
11
+ else if (params.lastContinuedVoice && params.lastContinuedVoice.staff)
12
+ params.endY = params.lastContinuedVoice.staff.absoluteY - spacing.STEP*2;
13
+ else
14
+ params.endY = params.startVoice.staff.absoluteY - spacing.STEP*2;
15
+ return draw(renderer, params.x,startY, params.endY, params.type, params.header, selectables);
16
+ }
17
+
18
+ function straightPath(renderer, xLeft, yTop, yBottom, type) {
19
+ xLeft += spacing.STEP;
20
+ var xLineWidth = spacing.STEP*0.75;
21
+ var yOverlap = spacing.STEP*0.75;
22
+ var height = yBottom - yTop;
23
+ // Straight line
24
+ var pathString = sprintf("M %f %f l %f %f l %f %f l %f %f z",
25
+ xLeft, yTop-yOverlap, // top left line
26
+ 0, height+yOverlap*2, // bottom left line
27
+ xLineWidth, 0, // bottom right line
28
+ 0, - (height+yOverlap*2) // top right line
29
+ );
30
+ // Top arm
31
+ var wCurve = spacing.STEP*2;
32
+ var hCurve = spacing.STEP;
33
+ pathString += sprintf("M %f %f q %f %f %f %f q %f %f %f %f z",
34
+ xLeft+xLineWidth, yTop-yOverlap, // top left arm
35
+ wCurve*0.6, hCurve*0.2,
36
+ wCurve, -hCurve, // right point
37
+ -wCurve*0.1, hCurve*0.3,
38
+ -wCurve, hCurve+spacing.STEP // left bottom
39
+ );
40
+ // Bottom arm
41
+ pathString += sprintf("M %f %f q %f %f %f %f q %f %f %f %f z",
42
+ xLeft+xLineWidth, yTop+yOverlap+height, // bottom left arm
43
+ wCurve*0.6, -hCurve*0.2,
44
+ wCurve, hCurve, // right point
45
+ -wCurve*0.1, -hCurve*0.3,
46
+ -wCurve, -hCurve-spacing.STEP // left bottom
47
+ );
48
+ return renderer.paper.path({path:pathString, stroke:renderer.foregroundColor, fill:renderer.foregroundColor, 'class': renderer.controller.classes.generate(type), "data-name": type});
49
+ }
50
+
51
+ function curvyPath(renderer, xLeft, yTop, yBottom, type) {
52
+ var yHeight = yBottom - yTop;
53
+
54
+ var pathString = curve(xLeft,
55
+ yTop,
56
+ [7.5, -8, 21, 0, 18.5, -10.5, 7.5],
57
+ [0, yHeight/5.5, yHeight/3.14, yHeight/2, yHeight/2.93, yHeight/4.88, 0]);
58
+
59
+ pathString += curve(xLeft,
60
+ yTop,
61
+ [0, 17.5, -7.5, 6.6, -5, 20, 0],
62
+ [yHeight/2, yHeight/1.46, yHeight/1.22, yHeight, yHeight/1.19, yHeight/1.42, yHeight/2]);
63
+
64
+ return renderer.paper.path({path:pathString, stroke:renderer.foregroundColor, fill:renderer.foregroundColor, 'class': renderer.controller.classes.generate(type), "data-name": type});
65
+ }
66
+
67
+ function curve(xLeft, yTop, xCurve, yCurve) {
68
+ return sprintf("M %f %f C %f %f %f %f %f %f C %f %f %f %f %f %f z",
69
+ xLeft+xCurve[0], yTop+yCurve[0],
70
+ xLeft+xCurve[1], yTop+yCurve[1],
71
+ xLeft+xCurve[2], yTop+yCurve[2],
72
+ xLeft+xCurve[3], yTop+yCurve[3],
73
+ xLeft+xCurve[4], yTop+yCurve[4],
74
+ xLeft+xCurve[5], yTop+yCurve[5],
75
+ xLeft+xCurve[6], yTop+yCurve[6]);
76
+ }
77
+
78
+ var draw = function (renderer, xLeft, yTop, yBottom, type, header, selectables) {//Tony
79
+ var ret;
80
+ if (header) {
81
+ renderer.paper.openGroup({klass: renderer.controller.classes.generate("staff-extra voice-name"), "data-name": type});
82
+ var position = yTop + (yBottom - yTop) / 2;
83
+ position = position - renderer.controller.getTextSize.baselineToCenter(header, "voicefont", 'staff-extra voice-name', 0, 1);
84
+
85
+ renderText(renderer, {
86
+ x: renderer.padding.left,
87
+ y: position,
88
+ text: header,
89
+ type: 'voicefont',
90
+ klass: 'staff-extra voice-name',
91
+ anchor: 'start',
92
+ centerVertically: true
93
+ });
94
+ }
95
+ if (type === "brace")
96
+ ret = curvyPath(renderer, xLeft, yTop, yBottom, type);
97
+ else if (type === "bracket")
98
+ ret = straightPath(renderer, xLeft, yTop, yBottom, type);
99
+ if (header) {
100
+ ret = renderer.paper.closeGroup();
101
+ }
102
+ selectables.wrapSvgEl({el_type: type, startChar: -1, endChar: -1}, ret);
103
+
104
+ return ret;
105
+ };
106
+ module.exports = drawBrace;
@@ -0,0 +1,38 @@
1
+ var sprintf = require('./sprintf');
2
+ var printPath = require('./print-path');
3
+ var roundNumber = require("./round-number");
4
+
5
+ function drawCrescendo(renderer, params, selectables) {
6
+ if (params.pitch === undefined)
7
+ window.console.error("Crescendo Element y-coordinate not set.");
8
+ var y = renderer.calcY(params.pitch) + 4; // This is the top pixel to use (it is offset a little so that it looks good with the volume marks.)
9
+ var height = 8;
10
+
11
+ // TODO-PER: This is just a quick hack to make the dynamic marks not crash if they are mismatched. See the slur treatment for the way to get the beginning and end.
12
+ var left = params.anchor1 ? params.anchor1.x : 0;
13
+ var right = params.anchor2 ? params.anchor2.x : 800;
14
+
15
+ var el;
16
+ if (params.dir === "<") {
17
+ el = drawLine(renderer, y+height/2, y, y+height/2, y+height, left, right);
18
+ } else {
19
+ el = drawLine(renderer, y, y+height/2, y+height, y+height/2, left, right);
20
+ }
21
+ selectables.wrapSvgEl({el_type: "dynamicDecoration", startChar: -1, endChar: -1}, el);
22
+ return [el];
23
+ }
24
+
25
+ var drawLine = function (renderer, y1, y2, y3, y4, left, right) {
26
+ y1 = roundNumber(y1);
27
+ y2 = roundNumber(y2);
28
+ y3 = roundNumber(y3);
29
+ y4 = roundNumber(y4);
30
+ left = roundNumber(left);
31
+ right = roundNumber(right);
32
+
33
+ var pathString = sprintf("M %f %f L %f %f M %f %f L %f %f",
34
+ left, y1, right, y2, left, y3, right, y4);
35
+ return printPath(renderer, {path:pathString, highlight: "stroke", stroke:renderer.foregroundColor, 'class': renderer.controller.classes.generate('dynamics decoration'), "data-name": "dynamics"});
36
+ };
37
+
38
+ module.exports = drawCrescendo;
@@ -0,0 +1,8 @@
1
+ function printDebugBox(renderer, attr, comment) {
2
+ var box = renderer.paper.rectBeneath(attr);
3
+ if (comment)
4
+ renderer.paper.text(comment, {x: 0, y: attr.y+7, "text-anchor": "start", "font-size":"14px", fill: "rgba(0,0,255,.4)", stroke: "rgba(0,0,255,.4)" });
5
+ return box;
6
+ }
7
+
8
+ module.exports = printDebugBox;
@@ -0,0 +1,56 @@
1
+ var drawStaffGroup = require('./staff-group');
2
+ var setPaperSize = require('./set-paper-size');
3
+ var nonMusic = require('./non-music');
4
+ var spacing = require('../abc_spacing');
5
+ var Selectables = require('./selectables');
6
+
7
+ function draw(renderer, classes, abcTune, width, maxWidth, responsive, scale, selectTypes, tuneNumber, lineOffset) {
8
+ var selectables = new Selectables(renderer.paper, selectTypes, tuneNumber);
9
+ renderer.moveY(renderer.padding.top);
10
+ nonMusic(renderer, abcTune.topText, selectables);
11
+ renderer.moveY(renderer.spacing.music);
12
+ var staffgroups = [];
13
+ for (var line = 0; line < abcTune.lines.length; line++) {
14
+ classes.incrLine();
15
+ var abcLine = abcTune.lines[line];
16
+ if (abcLine.staff) {
17
+ if (abcLine.vskip) {
18
+ renderer.moveY(abcLine.vskip);
19
+ }
20
+ if (staffgroups.length >= 1)
21
+ addStaffPadding(renderer, renderer.spacing.staffSeparation, staffgroups[staffgroups.length - 1], abcLine.staffGroup);
22
+ var staffgroup = engraveStaffLine(renderer, abcLine.staffGroup, selectables,line);
23
+ staffgroup.line = lineOffset+line; // If there are non-music lines then the staffgroup array won't line up with the line array, so this keeps track.
24
+ staffgroups.push(staffgroup);
25
+ } else if (abcLine.nonMusic) {
26
+ nonMusic(renderer, abcLine.nonMusic, selectables);
27
+ }
28
+ }
29
+
30
+ classes.reset();
31
+ if (abcTune.bottomText && abcTune.bottomText.rows && abcTune.bottomText.rows.length > 0) {
32
+ renderer.moveY(24); // TODO-PER: Empirically discovered. What variable should this be?
33
+ nonMusic(renderer, abcTune.bottomText, selectables);
34
+ }
35
+ setPaperSize(renderer, maxWidth, scale, responsive);
36
+ return { staffgroups: staffgroups, selectables: selectables.getElements() };
37
+ }
38
+
39
+ function engraveStaffLine(renderer, staffGroup, selectables,lineNumber) {
40
+ drawStaffGroup(renderer, staffGroup, selectables,lineNumber);
41
+ var height = staffGroup.height * spacing.STEP;
42
+ renderer.y += height;
43
+ return staffGroup;
44
+ }
45
+
46
+ function addStaffPadding(renderer, staffSeparation, lastStaffGroup, thisStaffGroup) {
47
+ var lastStaff = lastStaffGroup.staffs[lastStaffGroup.staffs.length-1];
48
+ var lastBottomLine = -(lastStaff.bottom - 2); // The 2 is because the scale goes to 2 below the last line.
49
+ var nextTopLine = thisStaffGroup.staffs[0].top - 10; // Because 10 represents the top line.
50
+ var naturalSeparation = nextTopLine + lastBottomLine; // This is how far apart they'd be without extra spacing
51
+ var separationInPixels = naturalSeparation * spacing.STEP;
52
+ if (separationInPixels < staffSeparation)
53
+ renderer.moveY(staffSeparation-separationInPixels);
54
+ }
55
+
56
+ module.exports = draw;
@@ -0,0 +1,20 @@
1
+ var printSymbol = require('./print-symbol');
2
+
3
+ function drawDynamics(renderer, params, selectables) {
4
+ if (params.pitch === undefined)
5
+ window.console.error("Dynamic Element y-coordinate not set.");
6
+ var scalex = 1;
7
+ var scaley = 1;
8
+ var el = printSymbol(renderer, params.anchor.x, params.pitch, params.dec, {
9
+ scalex: scalex,
10
+ scaley: scaley,
11
+ klass: renderer.controller.classes.generate('decoration dynamics'),
12
+ fill:renderer.foregroundColor,
13
+ stroke: "none",
14
+ name: "dynamics"
15
+ });
16
+ selectables.wrapSvgEl({el_type: "dynamicDecoration", startChar: -1, endChar: -1, decoration: params.dec}, el);
17
+ return [el];
18
+ }
19
+
20
+ module.exports = drawDynamics;
@@ -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 drawEnding(renderer, params, linestartx, lineendx, selectables) {
7
+ if (params.pitch === undefined)
8
+ window.console.error("Ending Element y-coordinate not set.");
9
+ var y = roundNumber(renderer.calcY(params.pitch));
10
+ var height = 20;
11
+ var pathString = '';
12
+
13
+ if (params.anchor1) {
14
+ linestartx = roundNumber(params.anchor1.x+params.anchor1.w);
15
+ pathString += sprintf("M %f %f L %f %f ",
16
+ linestartx, y, linestartx, roundNumber(y+height));
17
+ }
18
+
19
+ if (params.anchor2) {
20
+ lineendx = roundNumber(params.anchor2.x);
21
+ pathString += sprintf("M %f %f L %f %f ",
22
+ lineendx, y, lineendx, roundNumber(y+height));
23
+ }
24
+
25
+ pathString += sprintf("M %f %f L %f %f ",
26
+ linestartx, y, lineendx, y);
27
+
28
+ renderer.paper.openGroup({klass: renderer.controller.classes.generate("ending"), "data-name": "ending"});
29
+ printPath(renderer, {path: pathString, stroke: renderer.foregroundColor, fill: renderer.foregroundColor, "data-name": "line"});
30
+ if (params.anchor1)
31
+ renderText(renderer, {
32
+ x: roundNumber(linestartx + 5),
33
+ y: roundNumber(renderer.calcY(params.pitch - 0.5)),
34
+ text: params.text,
35
+ type: 'repeatfont',
36
+ klass: 'ending',
37
+ anchor: "start",
38
+ noClass: true,
39
+ name: params.text
40
+ });
41
+ var g = renderer.paper.closeGroup();
42
+ selectables.wrapSvgEl({el_type: "ending", startChar: -1, endChar: -1}, g);
43
+ return [g];
44
+ }
45
+
46
+ module.exports = drawEnding;
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Begin a group of glyphs that will always be moved, scaled and highlighted together
3
+ */
4
+
5
+ var roundNumber = require("./round-number");
6
+
7
+ function Group() {
8
+ this.ingroup = false;
9
+ }
10
+
11
+ Group.prototype.beginGroup = function (paper, controller) {
12
+ this.paper = paper;
13
+ this.controller = controller;
14
+ this.path = [];
15
+ this.lastM = [0, 0];
16
+ this.ingroup = true;
17
+ this.paper.openGroup();
18
+ };
19
+
20
+ Group.prototype.isInGroup = function() {
21
+ return this.ingroup;
22
+ }
23
+
24
+ Group.prototype.addPath = function (path) {
25
+ path = path || [];
26
+ if (path.length === 0) return;
27
+ path[0][0] = "m";
28
+ path[0][1] = roundNumber(path[0][1] - this.lastM[0]);
29
+ path[0][2] = roundNumber(path[0][2] - this.lastM[1]);
30
+ this.lastM[0] += path[0][1];
31
+ this.lastM[1] += path[0][2];
32
+ this.path.push(path[0]);
33
+ for (var i = 1, ii = path.length; i < ii; i++) {
34
+ if (path[i][0] === "m") {
35
+ this.lastM[0] += path[i][1];
36
+ this.lastM[1] += path[i][2];
37
+ }
38
+ this.path.push(path[i]);
39
+ }
40
+ };
41
+
42
+ /**
43
+ * End a group of glyphs that will always be moved, scaled and highlighted together
44
+ */
45
+ Group.prototype.endGroup = function (klass, name) {
46
+ this.ingroup = false;
47
+ //if (this.path.length === 0) return null;
48
+ var path = "";
49
+ for (var i = 0; i < this.path.length; i++)
50
+ path += this.path[i].join(" ");
51
+ this.path = [];
52
+
53
+ var ret = this.paper.closeGroup();
54
+ if (ret) {
55
+ ret.setAttribute("class", this.controller.classes.generate(klass))
56
+ ret.setAttribute("fill", this.controller.renderer.foregroundColor)
57
+ ret.setAttribute("stroke", "none")
58
+ ret.setAttribute("data-name", name)
59
+ }
60
+ return ret;
61
+ };
62
+
63
+ // There is just a singleton of this object.
64
+ var elementGroup = new Group();
65
+
66
+ module.exports = elementGroup;
@@ -0,0 +1,25 @@
1
+ // For debugging, it is sometimes useful to know where you are vertically.
2
+ var sprintf = require("./sprintf");
3
+
4
+ function printHorizontalLine(renderer, width, vertical, comment) {
5
+ var dy = 0.35;
6
+ var fill = "rgba(0,0,255,.4)";
7
+ var y = renderer.y;
8
+ if (vertical) y = vertical;
9
+ y = Math.round(y);
10
+ renderer.paper.text(""+Math.round(y), {x: 10, y: y, "text-anchor": "start", "font-size":"18px", fill: fill, stroke: fill });
11
+ var x1 = 50;
12
+ var x2 = width;
13
+ var pathString = sprintf("M %f %f L %f %f L %f %f L %f %f z", x1, y-dy, x1+x2, y-dy,
14
+ x2, y+dy, x1, y+dy);
15
+ renderer.paper.pathToBack({path:pathString, stroke:"none", fill:fill, 'class': renderer.controller.classes.generate('staff')});
16
+ for (var i = 1; i < width/100; i++) {
17
+ pathString = sprintf("M %f %f L %f %f L %f %f L %f %f z", i*100-dy, y-5, i*100-dy, y+5,
18
+ i*100+dy, y-5, i*100+dy, y+5);
19
+ renderer.paper.pathToBack({path:pathString, stroke:"none", fill:fill, 'class': renderer.controller.classes.generate('staff')});
20
+ }
21
+ if (comment)
22
+ renderer.paper.text(comment, {x: width+70, y: y, "text-anchor": "start", "font-size":"18px", fill: fill, stroke: fill });
23
+ }
24
+
25
+ module.exports = printHorizontalLine;
@@ -0,0 +1,50 @@
1
+ var drawSeparator = require('./separator');
2
+ var renderText = require('./text');
3
+
4
+ function nonMusic(renderer, obj, selectables) {
5
+ for (var i = 0; i < obj.rows.length; i++) {
6
+ var row = obj.rows[i];
7
+ if (row.absmove) {
8
+ renderer.absolutemoveY(row.absmove);
9
+ } else if (row.move) {
10
+ renderer.moveY(row.move);
11
+ } else if (row.text) {
12
+ var x = row.left ? row.left : 0;
13
+ var el = renderText(renderer, {
14
+ x: x,
15
+ y: renderer.y,
16
+ text: row.text,
17
+ type: row.font,
18
+ klass: row.klass,
19
+ name: row.name,
20
+ anchor: row.anchor
21
+ });
22
+ if (row.absElemType) {
23
+ selectables.wrapSvgEl({
24
+ el_type: row.absElemType,
25
+ name: row.name,
26
+ startChar: row.startChar,
27
+ endChar: row.endChar,
28
+ text: row.text
29
+ }, el);
30
+ }
31
+ } else if (row.separator) {
32
+ drawSeparator(renderer, row.separator)
33
+ } else if (row.startGroup) {
34
+ renderer.paper.openGroup({klass: row.klass, "data-name": row.name});
35
+ } else if (row.endGroup) {
36
+ // TODO-PER: also create a history element with the title "row.endGroup"
37
+ var g = renderer.paper.closeGroup();
38
+ if (row.absElemType)
39
+ selectables.wrapSvgEl({
40
+ el_type: row.absElemType,
41
+ name: row.name,
42
+ startChar: row.startChar,
43
+ endChar: row.endChar,
44
+ text: ""
45
+ }, g);
46
+ }
47
+ }
48
+ }
49
+
50
+ module.exports = nonMusic;
@@ -0,0 +1,24 @@
1
+ var sprintf = require('./sprintf');
2
+ var roundNumber = require("./round-number");
3
+
4
+ function printLine(renderer, x1, x2, y , klass, name ,dy ) {
5
+ if (!dy ) dy = 0.35;
6
+ var fill = renderer.foregroundColor;
7
+ x1 = roundNumber(x1);
8
+ x2 = roundNumber(x2);
9
+ var y1 = roundNumber(y - dy);
10
+ var y2 = roundNumber(y + dy);
11
+ var pathString = sprintf("M %f %f L %f %f L %f %f L %f %f z", x1, y1, x2, y1,
12
+ x2, y2, x1, y2);
13
+ var options = { path: pathString, stroke: "none", fill: fill };
14
+ if (name)
15
+ options['data-name'] = name;
16
+ if (klass)
17
+ options['class'] = klass;
18
+ var ret = renderer.paper.pathToBack(options);
19
+
20
+ return ret;
21
+ }
22
+
23
+ module.exports = printLine;
24
+
@@ -0,0 +1,7 @@
1
+ function printPath(renderer, attrs, params) {
2
+ var ret = renderer.paper.path(attrs);
3
+
4
+ return ret;
5
+ }
6
+
7
+ module.exports = printPath;