abcjs 6.1.9 → 6.2.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 (135) hide show
  1. package/LICENSE.md +1 -1
  2. package/RELEASE.md +58 -0
  3. package/dist/abcjs-basic-min.js +2 -2
  4. package/dist/abcjs-basic-min.js.LICENSE +1 -1
  5. package/dist/abcjs-basic.js +4505 -4556
  6. package/dist/abcjs-basic.js.map +1 -1
  7. package/dist/abcjs-plugin-min.js +2 -2
  8. package/dist/abcjs-plugin-min.js.LICENSE +1 -1
  9. package/index.js +2 -2
  10. package/license.js +1 -1
  11. package/package.json +1 -1
  12. package/plugin.js +2 -2
  13. package/src/api/abc_timing_callbacks.js +8 -4
  14. package/src/api/abc_tunebook_svg.js +1 -2
  15. package/src/data/abc_tune.js +3 -3
  16. package/src/parse/abc_common.js +0 -47
  17. package/src/parse/abc_parse.js +16 -16
  18. package/src/parse/abc_parse_book.js +3 -3
  19. package/src/parse/abc_parse_directive.js +26 -7
  20. package/src/parse/abc_parse_header.js +11 -9
  21. package/src/parse/abc_parse_key_voice.js +17 -17
  22. package/src/parse/abc_parse_music.js +88 -105
  23. package/src/parse/abc_tokenizer.js +60 -60
  24. package/src/parse/tune-builder.js +19 -14
  25. package/src/synth/abc_midi_flattener.js +25 -9
  26. package/src/synth/create-synth.js +71 -4
  27. package/src/synth/load-note.js +1 -1
  28. package/src/synth/note-to-midi.js +50 -0
  29. package/src/synth/place-note.js +10 -2
  30. package/src/tablatures/instruments/guitar/tab-guitar.js +0 -2
  31. package/src/tablatures/instruments/string-patterns.js +47 -29
  32. package/src/tablatures/instruments/tab-note.js +26 -103
  33. package/src/tablatures/instruments/violin/tab-violin.js +0 -2
  34. package/src/tablatures/tab-absolute-elements.js +9 -31
  35. package/src/tablatures/tab-renderer.js +2 -2
  36. package/src/test/abc_parser_lint.js +7 -4
  37. package/src/write/README.md +31 -0
  38. package/src/write/creation/abstract-engraver.js +1036 -0
  39. package/src/write/creation/add-chord.js +102 -0
  40. package/src/write/{add-text-if.js → creation/add-text-if.js} +6 -6
  41. package/src/write/{calcHeight.js → creation/calc-height.js} +2 -2
  42. package/src/write/creation/create-clef.js +72 -0
  43. package/src/write/creation/create-key-signature.js +31 -0
  44. package/src/write/creation/create-note-head.js +107 -0
  45. package/src/write/creation/create-time-signature.js +55 -0
  46. package/src/write/creation/decoration.js +357 -0
  47. package/src/write/{abc_absolute_element.js → creation/elements/absolute-element.js} +14 -15
  48. package/src/write/creation/elements/beam-element.js +113 -0
  49. package/src/write/{bottom-text.js → creation/elements/bottom-text.js} +14 -15
  50. package/src/write/{abc_brace_element.js → creation/elements/brace-element.js} +5 -5
  51. package/src/write/creation/elements/free-text.js +41 -0
  52. package/src/write/{abc_relative_element.js → creation/elements/relative-element.js} +7 -7
  53. package/src/write/{separator.js → creation/elements/separator.js} +2 -2
  54. package/src/write/{abc_staff_group_element.js → creation/elements/staff-group-element.js} +4 -4
  55. package/src/write/{subtitle.js → creation/elements/subtitle.js} +3 -3
  56. package/src/write/creation/elements/tempo-element.js +63 -0
  57. package/src/write/{abc_tie_element.js → creation/elements/tie-element.js} +15 -11
  58. package/src/write/{top-text.js → creation/elements/top-text.js} +12 -12
  59. package/src/write/creation/elements/triplet-element.js +28 -0
  60. package/src/write/{abc_voice_element.js → creation/elements/voice-element.js} +3 -3
  61. package/src/write/creation/glyphs.js +226 -0
  62. package/src/write/creation/translate-chord.js +37 -0
  63. package/src/write/draw/absolute.js +5 -5
  64. package/src/write/draw/beam.js +8 -8
  65. package/src/write/draw/brace.js +33 -33
  66. package/src/write/draw/crescendo.js +4 -4
  67. package/src/write/draw/debug-box.js +1 -1
  68. package/src/write/draw/draw.js +7 -7
  69. package/src/write/draw/dynamics.js +2 -2
  70. package/src/write/draw/ending.js +6 -6
  71. package/src/write/draw/glissando.js +17 -17
  72. package/src/write/draw/group-elements.js +51 -51
  73. package/src/write/draw/horizontal-line.js +9 -9
  74. package/src/write/draw/non-music.js +1 -1
  75. package/src/write/draw/print-line.js +25 -16
  76. package/src/write/draw/print-stem.js +15 -5
  77. package/src/write/draw/print-symbol.js +12 -12
  78. package/src/write/draw/print-vertical-line.js +8 -8
  79. package/src/write/draw/relative.js +17 -16
  80. package/src/write/draw/selectables.js +5 -5
  81. package/src/write/draw/separator.js +4 -4
  82. package/src/write/draw/set-paper-size.js +2 -2
  83. package/src/write/draw/sprintf.js +31 -31
  84. package/src/write/draw/staff-group.js +36 -30
  85. package/src/write/draw/staff-line.js +2 -2
  86. package/src/write/draw/staff.js +4 -4
  87. package/src/write/draw/tab-line.js +26 -26
  88. package/src/write/draw/tempo.js +30 -30
  89. package/src/write/draw/text.js +5 -5
  90. package/src/write/draw/tie.js +18 -18
  91. package/src/write/draw/triplet.js +6 -6
  92. package/src/write/draw/voice.js +16 -17
  93. package/src/write/{abc_engraver_controller.js → engraver-controller.js} +58 -51
  94. package/src/write/{classes.js → helpers/classes.js} +6 -6
  95. package/src/write/{get-font-and-attr.js → helpers/get-font-and-attr.js} +9 -7
  96. package/src/write/{get-text-size.js → helpers/get-text-size.js} +5 -5
  97. package/src/write/{set-class.js → helpers/set-class.js} +1 -1
  98. package/src/write/{abc_spacing.js → helpers/spacing.js} +1 -1
  99. package/src/write/{highlight.js → interactive/highlight.js} +1 -1
  100. package/src/write/{selection.js → interactive/selection.js} +34 -31
  101. package/src/write/{unhighlight.js → interactive/unhighlight.js} +1 -1
  102. package/src/write/layout/beam.js +13 -13
  103. package/src/write/layout/get-left-edge-of-staff.js +4 -4
  104. package/src/write/layout/layout.js +74 -74
  105. package/src/write/layout/{setUpperAndLowerElements.js → set-upper-and-lower-elements.js} +8 -8
  106. package/src/write/layout/{staffGroup.js → staff-group.js} +32 -32
  107. package/src/write/layout/triplet.js +4 -4
  108. package/src/write/layout/{VoiceElements.js → voice-elements.js} +23 -23
  109. package/src/write/layout/voice.js +6 -6
  110. package/src/write/{abc_renderer.js → renderer.js} +36 -32
  111. package/src/write/svg.js +35 -35
  112. package/test.js +2 -2
  113. package/types/index.d.ts +37 -8
  114. package/version.js +1 -1
  115. package/src/tablatures/instruments/guitar/guitar-fonts.js +0 -19
  116. package/src/tablatures/instruments/violin/violin-fonts.js +0 -19
  117. package/src/tablatures/transposer.js +0 -110
  118. package/src/write/abc_abstract_engraver.js +0 -1026
  119. package/src/write/abc_beam_element.js +0 -113
  120. package/src/write/abc_create_clef.js +0 -72
  121. package/src/write/abc_create_key_signature.js +0 -33
  122. package/src/write/abc_create_note_head.js +0 -107
  123. package/src/write/abc_create_time_signature.js +0 -55
  124. package/src/write/abc_decoration.js +0 -357
  125. package/src/write/abc_glyphs.js +0 -224
  126. package/src/write/abc_tempo_element.js +0 -63
  127. package/src/write/abc_triplet_element.js +0 -28
  128. package/src/write/add-chord.js +0 -103
  129. package/src/write/format-jazz-chord.js +0 -15
  130. package/src/write/free-text.js +0 -41
  131. /package/src/write/{abc_crescendo_element.js → creation/elements/crescendo-element.js} +0 -0
  132. /package/src/write/{abc_dynamic_decoration.js → creation/elements/dynamic-decoration.js} +0 -0
  133. /package/src/write/{abc_ending_element.js → creation/elements/ending-element.js} +0 -0
  134. /package/src/write/{abc_glissando_element.js → creation/elements/glissando-element.js} +0 -0
  135. /package/src/write/layout/{getBarYAt.js → get-bar-y-at.js} +0 -0
@@ -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;
@@ -19,8 +19,8 @@ var RelativeElement = function RelativeElement(c, dx, w, pitch, opt) {
19
19
  this.bottom = pitch;
20
20
  if (this.pitch2 !== undefined && this.pitch2 < this.bottom) this.bottom = this.pitch2;
21
21
  if (opt.thickness) {
22
- this.top += opt.thickness/2;
23
- this.bottom -= opt.thickness/2;
22
+ this.top += opt.thickness / 2;
23
+ this.bottom -= opt.thickness / 2;
24
24
  }
25
25
  if (opt.stemHeight) {
26
26
  if (opt.stemHeight > 0)
@@ -91,10 +91,10 @@ RelativeElement.prototype.getChordDim = function () {
91
91
  // margin = margin / 2;
92
92
  var margin = 0;
93
93
 
94
- var offset = this.type === "chord" ? this.realWidth/2 : 0;
94
+ var offset = this.type === "chord" ? this.realWidth / 2 : 0;
95
95
  var left = this.x - offset - margin;
96
96
  var right = left + this.realWidth + margin;
97
- return { left: left, right: right};
97
+ return { left: left, right: right };
98
98
  };
99
99
 
100
100
  RelativeElement.prototype.invertLane = function (total) {
@@ -107,9 +107,9 @@ RelativeElement.prototype.putChordInLane = function (i) {
107
107
  this.lane = i;
108
108
  // Add some extra space to account for the character's descenders.
109
109
  if (this.chordHeightAbove)
110
- this.chordHeightAbove = (this.height*1.25)*this.lane;
110
+ this.chordHeightAbove = (this.height * 1.25) * this.lane;
111
111
  else
112
- this.chordHeightBelow = (this.height*1.25)*this.lane;
112
+ this.chordHeightBelow = (this.height * 1.25) * this.lane;
113
113
  };
114
114
 
115
115
  RelativeElement.prototype.getLane = function () {
@@ -119,7 +119,7 @@ RelativeElement.prototype.getLane = function () {
119
119
  };
120
120
 
121
121
  RelativeElement.prototype.setX = function (x) {
122
- this.x = x+this.dx;
122
+ this.x = x + this.dx;
123
123
  };
124
124
 
125
125
  module.exports = RelativeElement;
@@ -1,10 +1,10 @@
1
1
  function Separator(spaceAbove, lineLength, spaceBelow) {
2
2
  this.rows = [];
3
3
  if (spaceAbove)
4
- this.rows.push({move: spaceAbove});
4
+ this.rows.push({ move: spaceAbove });
5
5
  this.rows.push({ separator: lineLength, absElemType: "separator" });
6
6
  if (spaceBelow)
7
- this.rows.push({move: spaceBelow});
7
+ this.rows.push({ move: spaceBelow });
8
8
  }
9
9
 
10
10
  module.exports = Separator;
@@ -26,9 +26,9 @@
26
26
  // TODO-PER: Where is that used? It looks like it might not be needed.
27
27
  // height: Set in the draw() method to the height actually used. Used by the calling function to know where to start the next staff group.
28
28
  // TODO-PER: This should actually be set in the layout method and passed back as a return value.
29
- var calcHeight = require('./calcHeight');
29
+ var calcHeight = require('../calc-height');
30
30
 
31
- var StaffGroupElement = function(getTextSize) {
31
+ var StaffGroupElement = function (getTextSize) {
32
32
  this.getTextSize = getTextSize;
33
33
  this.voices = [];
34
34
  this.staffs = [];
@@ -36,7 +36,7 @@ var StaffGroupElement = function(getTextSize) {
36
36
  this.bracket = undefined;
37
37
  };
38
38
 
39
- StaffGroupElement.prototype.setLimit = function(member, voice) {
39
+ StaffGroupElement.prototype.setLimit = function (member, voice) {
40
40
  if (!voice.specialY[member]) return;
41
41
  if (!voice.staff.specialY[member])
42
42
  voice.staff.specialY[member] = voice.specialY[member];
@@ -81,7 +81,7 @@ StaffGroupElement.prototype.setHeight = function () {
81
81
 
82
82
  StaffGroupElement.prototype.setWidth = function (width) {
83
83
  this.w = width;
84
- for (var i=0;i<this.voices.length;i++) {
84
+ for (var i = 0; i < this.voices.length; i++) {
85
85
  this.voices[i].setWidth(width);
86
86
  }
87
87
  };
@@ -1,12 +1,12 @@
1
1
  function Subtitle(spaceAbove, formatting, info, center, paddingLeft, getTextSize) {
2
2
  this.rows = [];
3
3
  if (spaceAbove)
4
- this.rows.push({move: spaceAbove});
4
+ this.rows.push({ move: spaceAbove });
5
5
  var tAnchor = formatting.titleleft ? 'start' : 'middle';
6
6
  var tLeft = formatting.titleleft ? paddingLeft : center;
7
- this.rows.push({left: tLeft, text: info.text, font: 'subtitlefont', klass: 'text subtitle', anchor: tAnchor, startChar: info.startChar, endChar: info.endChar, absElemType: "subtitle", name: "subtitle"});
7
+ this.rows.push({ left: tLeft, text: info.text, font: 'subtitlefont', klass: 'text subtitle', anchor: tAnchor, startChar: info.startChar, endChar: info.endChar, absElemType: "subtitle", name: "subtitle" });
8
8
  var size = getTextSize.calc(info.text, 'subtitlefont', 'text subtitle');
9
- this.rows.push({move: size.height});
9
+ this.rows.push({ move: size.height });
10
10
  }
11
11
 
12
12
  module.exports = Subtitle;
@@ -0,0 +1,63 @@
1
+ // abc_tempo_element.js: Definition of the TempoElement class.
2
+
3
+ var AbsoluteElement = require('./absolute-element');
4
+ var RelativeElement = require('./relative-element');
5
+
6
+ var TempoElement = function TempoElement(tempo, tuneNumber, createNoteHead) {
7
+ this.type = "TempoElement";
8
+ this.tempo = tempo;
9
+ this.tempo.type = "tempo"; /// TODO-PER: this should be set earlier, in the parser, probably.
10
+ this.tuneNumber = tuneNumber;
11
+ // TODO: can these two properties be merged?
12
+ this.totalHeightInPitches = 6;
13
+ this.tempoHeightAbove = this.totalHeightInPitches;
14
+ this.pitch = undefined; // This will be set later
15
+ if (this.tempo.duration && !this.tempo.suppressBpm) {
16
+ this.note = this.createNote(createNoteHead, tempo, tuneNumber);
17
+ }
18
+ };
19
+
20
+ TempoElement.prototype.setX = function (x) {
21
+ this.x = x;
22
+ };
23
+
24
+ TempoElement.prototype.createNote = function (createNoteHead, tempo, tuneNumber) {
25
+ var temposcale = 0.75;
26
+ var duration = tempo.duration[0]; // TODO when multiple durations
27
+ var absElem = new AbsoluteElement(tempo, duration, 1, 'tempo', tuneNumber);
28
+ // There aren't an infinite number of note values, but we are passed a float, so just in case something is off upstream,
29
+ // merge all of the in between points.
30
+ var dot;
31
+ var flag;
32
+ var note;
33
+ if (duration <= 1 / 32) { note = "noteheads.quarter"; flag = "flags.u32nd"; dot = 0; }
34
+ else if (duration <= 1 / 16) { note = "noteheads.quarter"; flag = "flags.u16th"; dot = 0; }
35
+ else if (duration <= 3 / 32) { note = "noteheads.quarter"; flag = "flags.u16nd"; dot = 1; }
36
+ else if (duration <= 1 / 8) { note = "noteheads.quarter"; flag = "flags.u8th"; dot = 0; }
37
+ else if (duration <= 3 / 16) { note = "noteheads.quarter"; flag = "flags.u8th"; dot = 1; }
38
+ else if (duration <= 1 / 4) { note = "noteheads.quarter"; dot = 0; }
39
+ else if (duration <= 3 / 8) { note = "noteheads.quarter"; dot = 1; }
40
+ else if (duration <= 1 / 2) { note = "noteheads.half"; dot = 0; }
41
+ else if (duration <= 3 / 4) { note = "noteheads.half"; dot = 1; }
42
+ else if (duration <= 1) { note = "noteheads.whole"; dot = 0; }
43
+ else if (duration <= 1.5) { note = "noteheads.whole"; dot = 1; }
44
+ else if (duration <= 2) { note = "noteheads.dbl"; dot = 0; }
45
+ else { note = "noteheads.dbl"; dot = 1; }
46
+
47
+ var ret = createNoteHead(absElem, note, { verticalPos: 0 }, // This is just temporary: we'll offset the vertical positioning when we get the actual vertical spot.
48
+ { dir: "up", flag: flag, dot: dot, scale: temposcale });
49
+ var tempoNote = ret.notehead;
50
+ absElem.addHead(tempoNote);
51
+ var stem;
52
+ if (note !== "noteheads.whole" && note !== "noteheads.dbl") {
53
+ var p1 = 1 / 3 * temposcale;
54
+ var p2 = 5 * temposcale;
55
+ var dx = tempoNote.dx + tempoNote.w;
56
+ var width = -0.6;
57
+ stem = new RelativeElement(null, dx, 0, p1, { "type": "stem", "pitch2": p2, linewidth: width });
58
+ absElem.addRight(stem);
59
+ }
60
+ return absElem;
61
+ };
62
+
63
+ module.exports = TempoElement;
@@ -2,7 +2,7 @@
2
2
 
3
3
  var TieElem = function TieElem(options) {
4
4
  this.type = "TieElem";
5
- // console.log("constructor", options.anchor1 ? options.anchor1.pitch : "N/A", options.anchor2 ? options.anchor2.pitch : "N/A", options.isTie, options.isGrace);
5
+ // console.log("constructor", options.anchor1 ? options.anchor1.pitch : "N/A", options.anchor2 ? options.anchor2.pitch : "N/A", options.isTie, options.isGrace);
6
6
  this.anchor1 = options.anchor1; // must have a .x and a .pitch, and a .parent property or be null (means starts at the "beginning" of the line - after keysig)
7
7
  this.anchor2 = options.anchor2; // must have a .x and a .pitch property or be null (means ends at the end of the line)
8
8
  if (options.isGrace)
@@ -18,12 +18,12 @@ var TieElem = function TieElem(options) {
18
18
  this.internalNotes = [];
19
19
  };
20
20
 
21
- TieElem.prototype.addInternalNote = function(note) {
21
+ TieElem.prototype.addInternalNote = function (note) {
22
22
  this.internalNotes.push(note);
23
23
  };
24
24
 
25
- TieElem.prototype.setEndAnchor = function(anchor2) {
26
- // console.log("end", this.anchor1 ? this.anchor1.pitch : "N/A", anchor2 ? anchor2.pitch : "N/A", this.isTie, this.isGrace);
25
+ TieElem.prototype.setEndAnchor = function (anchor2) {
26
+ // console.log("end", this.anchor1 ? this.anchor1.pitch : "N/A", anchor2 ? anchor2.pitch : "N/A", this.isTie, this.isGrace);
27
27
  this.anchor2 = anchor2; // must have a .x and a .pitch property or be null (means ends at the end of the line)
28
28
 
29
29
  // we don't really have enough info to know what the vertical extent is yet and we won't until drawing. This will just give it enough
@@ -39,11 +39,11 @@ TieElem.prototype.setEndAnchor = function(anchor2) {
39
39
  };
40
40
 
41
41
  // If we encounter a repeat sign, then we don't want to extend either a tie or a slur past it, so these are called to be a limit.
42
- TieElem.prototype.setStartX = function(startLimitElem) {
42
+ TieElem.prototype.setStartX = function (startLimitElem) {
43
43
  this.startLimitX = startLimitElem;
44
44
  };
45
45
 
46
- TieElem.prototype.setEndX = function(endLimitElem) {
46
+ TieElem.prototype.setEndX = function (endLimitElem) {
47
47
  this.endLimitX = endLimitElem;
48
48
  };
49
49
 
@@ -121,9 +121,13 @@ TieElem.prototype.calcX = function (lineStartX, lineEndX) {
121
121
  if (this.anchor1.scalex < 1) // this is a grace note - don't offset the tie as much.
122
122
  this.startX -= 3;
123
123
  } else if (this.startLimitX)
124
- this.startX = this.startLimitX.x+this.startLimitX.w; // if there is no start element, but there is a repeat mark before the start of the line.
125
- else
126
- this.startX = lineStartX; // There is no element and no repeat mark: extend to the beginning of the line.
124
+ this.startX = this.startLimitX.x + this.startLimitX.w; // if there is no start element, but there is a repeat mark before the start of the line.
125
+ else {
126
+ if (this.anchor2)
127
+ this.startX = this.anchor2.x - 20; // There is no element and no repeat mark: make a small arc
128
+ else
129
+ this.startX = lineStartX; // Don't have any guidance, so extend to beginning of line
130
+ }
127
131
  if (!this.anchor1 && this.dotted)
128
132
  this.startX -= 3; // The arc needs to be long enough to tell that it is dotted.
129
133
 
@@ -160,7 +164,7 @@ TieElem.prototype.calcSlurY = function () {
160
164
  if (this.anchor1 && this.anchor2) {
161
165
  if (this.above && this.anchor1.stemDir === "up" && !this.fixedY) {
162
166
  this.startY = (this.anchor1.highestVert + this.anchor1.pitch) / 2;
163
- this.startX += this.anchor1.w/2; // When going to the middle of the stem, bump the line to the right a little bit to make it look right.
167
+ this.startX += this.anchor1.w / 2; // When going to the middle of the stem, bump the line to the right a little bit to make it look right.
164
168
  } else
165
169
  this.startY = this.anchor1.pitch;
166
170
 
@@ -169,7 +173,7 @@ TieElem.prototype.calcSlurY = function () {
169
173
  var midPoint = (this.anchor2.highestVert + this.anchor2.pitch) / 2;
170
174
  if (this.above && this.anchor2.stemDir === "up" && !this.fixedY && !beamInterferes && (midPoint < this.startY)) {
171
175
  this.endY = midPoint;
172
- this.endX += Math.round(this.anchor2.w/2); // When going to the middle of the stem, bump the line to the right a little bit to make it look right.
176
+ this.endX += Math.round(this.anchor2.w / 2); // When going to the middle of the stem, bump the line to the right a little bit to make it look right.
173
177
  } else
174
178
  this.endY = this.above && beamInterferes ? this.anchor2.highestVert : this.anchor2.pitch;
175
179
 
@@ -1,4 +1,4 @@
1
- const addTextIf = require("./add-text-if");
1
+ const addTextIf = require("../add-text-if");
2
2
 
3
3
  function TopText(metaText, metaTextInfo, formatting, lines, width, isPrint, paddingLeft, spacing, getTextSize) {
4
4
  this.rows = [];
@@ -7,38 +7,38 @@ function TopText(metaText, metaTextInfo, formatting, lines, width, isPrint, padd
7
7
  // Note: whether there is a header or not doesn't change any other positioning, so this doesn't change the Y-coordinate.
8
8
  // This text goes above the margin, so we'll temporarily move up.
9
9
  var headerTextHeight = getTextSize.calc("X", "headerfont", 'abcjs-header abcjs-meta-top').height;
10
- addTextIf(this.rows, { marginLeft: paddingLeft, text: metaText.header.left, font: 'headerfont', klass: 'header meta-top', marginTop: -headerTextHeight, info: metaTextInfo.header, name: "header"}, getTextSize);
11
- addTextIf(this.rows, { marginLeft: paddingLeft + width / 2, text: metaText.header.center, font: 'headerfont', klass: 'header meta-top', marginTop: -headerTextHeight, anchor: 'middle', info: metaTextInfo.header, name: "header"}, getTextSize);
12
- addTextIf(this.rows, { marginLeft: paddingLeft + width, text: metaText.header.right, font: 'headerfont', klass: 'header meta-top', marginTop: -headerTextHeight, anchor: 'end', info: metaTextInfo.header, name: "header"}, getTextSize);
10
+ addTextIf(this.rows, { marginLeft: paddingLeft, text: metaText.header.left, font: 'headerfont', klass: 'header meta-top', marginTop: -headerTextHeight, info: metaTextInfo.header, name: "header" }, getTextSize);
11
+ addTextIf(this.rows, { marginLeft: paddingLeft + width / 2, text: metaText.header.center, font: 'headerfont', klass: 'header meta-top', marginTop: -headerTextHeight, anchor: 'middle', info: metaTextInfo.header, name: "header" }, getTextSize);
12
+ addTextIf(this.rows, { marginLeft: paddingLeft + width, text: metaText.header.right, font: 'headerfont', klass: 'header meta-top', marginTop: -headerTextHeight, anchor: 'end', info: metaTextInfo.header, name: "header" }, getTextSize);
13
13
 
14
- // TopText.prototype.addTextIf = function (marginLeft, text, font, klass, marginTop, marginBottom, anchor, getTextSize, absElemType, noMove) {
14
+ // TopText.prototype.addTextIf = function (marginLeft, text, font, klass, marginTop, marginBottom, anchor, getTextSize, absElemType, noMove) {
15
15
  }
16
16
  if (isPrint)
17
- this.rows.push({move: spacing.top});
17
+ this.rows.push({ move: spacing.top });
18
18
  var tAnchor = formatting.titleleft ? 'start' : 'middle';
19
19
  var tLeft = formatting.titleleft ? paddingLeft : paddingLeft + width / 2;
20
20
  if (metaText.title) {
21
- addTextIf(this.rows, { marginLeft: tLeft, text: metaText.title, font: 'titlefont', klass: 'title meta-top', marginTop: spacing.title, anchor: tAnchor, absElemType: "title", info: metaTextInfo.title, name: "title"}, getTextSize);
21
+ addTextIf(this.rows, { marginLeft: tLeft, text: metaText.title, font: 'titlefont', klass: 'title meta-top', marginTop: spacing.title, anchor: tAnchor, absElemType: "title", info: metaTextInfo.title, name: "title" }, getTextSize);
22
22
  }
23
23
  if (lines.length) {
24
24
  var index = 0;
25
25
  while (index < lines.length && lines[index].subtitle) {
26
- addTextIf(this.rows, {marginLeft: tLeft, text: lines[index].subtitle.text, font: 'subtitlefont', klass: 'text meta-top subtitle', marginTop: spacing.subtitle, anchor: tAnchor, absElemType: "subtitle", info: lines[index].subtitle, name: "subtitle"}, getTextSize);
26
+ addTextIf(this.rows, { marginLeft: tLeft, text: lines[index].subtitle.text, font: 'subtitlefont', klass: 'text meta-top subtitle', marginTop: spacing.subtitle, anchor: tAnchor, absElemType: "subtitle", info: lines[index].subtitle, name: "subtitle" }, getTextSize);
27
27
  index++;
28
28
  }
29
29
  }
30
30
 
31
31
  if (metaText.rhythm || metaText.origin || metaText.composer) {
32
- this.rows.push({move: spacing.composer});
32
+ this.rows.push({ move: spacing.composer });
33
33
  if (metaText.rhythm && metaText.rhythm.length > 0) {
34
34
  var noMove = !!(metaText.composer || metaText.origin);
35
- addTextIf(this.rows, { marginLeft: paddingLeft, text: metaText.rhythm, font: 'infofont', klass: 'meta-top rhythm', absElemType: "rhythm", noMove: noMove, info: metaTextInfo.rhythm, name: "rhythm"}, getTextSize);
35
+ addTextIf(this.rows, { marginLeft: paddingLeft, text: metaText.rhythm, font: 'infofont', klass: 'meta-top rhythm', absElemType: "rhythm", noMove: noMove, info: metaTextInfo.rhythm, name: "rhythm" }, getTextSize);
36
36
  }
37
37
  var composerLine = "";
38
38
  if (metaText.composer) composerLine += metaText.composer;
39
39
  if (metaText.origin) composerLine += ' (' + metaText.origin + ')';
40
40
  if (composerLine.length > 0) {
41
- addTextIf(this.rows, { marginLeft: paddingLeft + width, text: composerLine, font: 'composerfont', klass: 'meta-top composer', anchor: "end", absElemType: "composer", info: metaTextInfo.composer, name: "composer"}, getTextSize);
41
+ addTextIf(this.rows, { marginLeft: paddingLeft + width, text: composerLine, font: 'composerfont', klass: 'meta-top composer', anchor: "end", absElemType: "composer", info: metaTextInfo.composer, name: "composer" }, getTextSize);
42
42
  }
43
43
  }
44
44
 
@@ -47,7 +47,7 @@ function TopText(metaText, metaTextInfo, formatting, lines, width, isPrint, padd
47
47
  }
48
48
 
49
49
  if (metaText.partOrder && metaText.partOrder.length > 0) {
50
- addTextIf(this.rows, { marginLeft: paddingLeft, text: metaText.partOrder, font: 'partsfont', klass: 'meta-top part-order', absElemType: "partOrder", info: metaTextInfo.partOrder, name: "part-order"}, getTextSize);
50
+ addTextIf(this.rows, { marginLeft: paddingLeft, text: metaText.partOrder, font: 'partsfont', klass: 'meta-top part-order', absElemType: "partOrder", info: metaTextInfo.partOrder, name: "part-order" }, getTextSize);
51
51
  }
52
52
  }
53
53
 
@@ -0,0 +1,28 @@
1
+ // abc_triplet_element.js: Definition of the TripletElem class.
2
+
3
+ var TripletElem = function TripletElem(number, anchor1, options) {
4
+ this.type = "TripletElem";
5
+ this.anchor1 = anchor1; // must have a .x and a .parent property or be null (means starts at the "beginning" of the line - after key signature)
6
+ this.number = number;
7
+ this.durationClass = ('d' + (Math.round(anchor1.parent.durationClass * 1000) / 1000)).replace(/\./, '-');
8
+ this.middleElems = []; // This is to calculate the highest interior pitch. It is used to make sure that the drawn bracket never crosses a really high middle note.
9
+ this.flatBeams = options.flatBeams;
10
+ };
11
+
12
+ TripletElem.prototype.isClosed = function () {
13
+ return !!this.anchor2;
14
+ };
15
+
16
+ TripletElem.prototype.middleNote = function (elem) {
17
+ this.middleElems.push(elem);
18
+ };
19
+
20
+ TripletElem.prototype.setCloseAnchor = function (anchor2) {
21
+ this.anchor2 = anchor2;
22
+ // TODO-PER: This used to be just for beamed triplets but it looks like bracketed triplets need extra room, too. The only one that doesn't is stem down and beamed
23
+ //if (this.anchor1.parent.beam)
24
+ if (!this.anchor1.parent.beam || this.anchor1.stemDir === 'up')
25
+ this.endingHeightAbove = 4;
26
+ };
27
+
28
+ module.exports = TripletElem;
@@ -43,7 +43,7 @@ VoiceElement.prototype.addChild = function (absElem) {
43
43
  this.setRange(absElem);
44
44
  };
45
45
 
46
- VoiceElement.prototype.setLimit = function(member, child) {
46
+ VoiceElement.prototype.setLimit = function (member, child) {
47
47
  // Sometimes we get an absolute element in here and sometimes we get some type of relative element.
48
48
  // If there is a "specialY" element, then assume it is an absolute element. If that doesn't exist, look for the
49
49
  // same members at the top level, because that's where they are in relative elements.
@@ -56,14 +56,14 @@ VoiceElement.prototype.setLimit = function(member, child) {
56
56
  this.specialY[member] = Math.max(this.specialY[member], specialY[member]);
57
57
  };
58
58
 
59
- VoiceElement.prototype.adjustRange = function(child) {
59
+ VoiceElement.prototype.adjustRange = function (child) {
60
60
  if (child.bottom !== undefined)
61
61
  this.bottom = Math.min(this.bottom, child.bottom);
62
62
  if (child.top !== undefined)
63
63
  this.top = Math.max(this.top, child.top);
64
64
  };
65
65
 
66
- VoiceElement.prototype.setRange = function(child) {
66
+ VoiceElement.prototype.setRange = function (child) {
67
67
  this.adjustRange(child);
68
68
  this.setLimit('tempoHeightAbove', child);
69
69
  this.setLimit('partHeightAbove', child);