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.
- package/LICENSE.md +1 -1
- package/RELEASE.md +58 -0
- package/dist/abcjs-basic-min.js +2 -2
- package/dist/abcjs-basic-min.js.LICENSE +1 -1
- package/dist/abcjs-basic.js +4505 -4556
- package/dist/abcjs-basic.js.map +1 -1
- package/dist/abcjs-plugin-min.js +2 -2
- package/dist/abcjs-plugin-min.js.LICENSE +1 -1
- package/index.js +2 -2
- package/license.js +1 -1
- package/package.json +1 -1
- package/plugin.js +2 -2
- package/src/api/abc_timing_callbacks.js +8 -4
- package/src/api/abc_tunebook_svg.js +1 -2
- package/src/data/abc_tune.js +3 -3
- package/src/parse/abc_common.js +0 -47
- package/src/parse/abc_parse.js +16 -16
- package/src/parse/abc_parse_book.js +3 -3
- package/src/parse/abc_parse_directive.js +26 -7
- package/src/parse/abc_parse_header.js +11 -9
- package/src/parse/abc_parse_key_voice.js +17 -17
- package/src/parse/abc_parse_music.js +88 -105
- package/src/parse/abc_tokenizer.js +60 -60
- package/src/parse/tune-builder.js +19 -14
- package/src/synth/abc_midi_flattener.js +25 -9
- package/src/synth/create-synth.js +71 -4
- package/src/synth/load-note.js +1 -1
- package/src/synth/note-to-midi.js +50 -0
- package/src/synth/place-note.js +10 -2
- package/src/tablatures/instruments/guitar/tab-guitar.js +0 -2
- package/src/tablatures/instruments/string-patterns.js +47 -29
- package/src/tablatures/instruments/tab-note.js +26 -103
- package/src/tablatures/instruments/violin/tab-violin.js +0 -2
- package/src/tablatures/tab-absolute-elements.js +9 -31
- package/src/tablatures/tab-renderer.js +2 -2
- package/src/test/abc_parser_lint.js +7 -4
- package/src/write/README.md +31 -0
- package/src/write/creation/abstract-engraver.js +1036 -0
- package/src/write/creation/add-chord.js +102 -0
- package/src/write/{add-text-if.js → creation/add-text-if.js} +6 -6
- package/src/write/{calcHeight.js → creation/calc-height.js} +2 -2
- package/src/write/creation/create-clef.js +72 -0
- package/src/write/creation/create-key-signature.js +31 -0
- package/src/write/creation/create-note-head.js +107 -0
- package/src/write/creation/create-time-signature.js +55 -0
- package/src/write/creation/decoration.js +357 -0
- package/src/write/{abc_absolute_element.js → creation/elements/absolute-element.js} +14 -15
- package/src/write/creation/elements/beam-element.js +113 -0
- package/src/write/{bottom-text.js → creation/elements/bottom-text.js} +14 -15
- package/src/write/{abc_brace_element.js → creation/elements/brace-element.js} +5 -5
- package/src/write/creation/elements/free-text.js +41 -0
- package/src/write/{abc_relative_element.js → creation/elements/relative-element.js} +7 -7
- package/src/write/{separator.js → creation/elements/separator.js} +2 -2
- package/src/write/{abc_staff_group_element.js → creation/elements/staff-group-element.js} +4 -4
- package/src/write/{subtitle.js → creation/elements/subtitle.js} +3 -3
- package/src/write/creation/elements/tempo-element.js +63 -0
- package/src/write/{abc_tie_element.js → creation/elements/tie-element.js} +15 -11
- package/src/write/{top-text.js → creation/elements/top-text.js} +12 -12
- package/src/write/creation/elements/triplet-element.js +28 -0
- package/src/write/{abc_voice_element.js → creation/elements/voice-element.js} +3 -3
- package/src/write/creation/glyphs.js +226 -0
- package/src/write/creation/translate-chord.js +37 -0
- package/src/write/draw/absolute.js +5 -5
- package/src/write/draw/beam.js +8 -8
- package/src/write/draw/brace.js +33 -33
- package/src/write/draw/crescendo.js +4 -4
- package/src/write/draw/debug-box.js +1 -1
- package/src/write/draw/draw.js +7 -7
- package/src/write/draw/dynamics.js +2 -2
- package/src/write/draw/ending.js +6 -6
- package/src/write/draw/glissando.js +17 -17
- package/src/write/draw/group-elements.js +51 -51
- package/src/write/draw/horizontal-line.js +9 -9
- package/src/write/draw/non-music.js +1 -1
- package/src/write/draw/print-line.js +25 -16
- package/src/write/draw/print-stem.js +15 -5
- package/src/write/draw/print-symbol.js +12 -12
- package/src/write/draw/print-vertical-line.js +8 -8
- package/src/write/draw/relative.js +17 -16
- package/src/write/draw/selectables.js +5 -5
- package/src/write/draw/separator.js +4 -4
- package/src/write/draw/set-paper-size.js +2 -2
- package/src/write/draw/sprintf.js +31 -31
- package/src/write/draw/staff-group.js +36 -30
- package/src/write/draw/staff-line.js +2 -2
- package/src/write/draw/staff.js +4 -4
- package/src/write/draw/tab-line.js +26 -26
- package/src/write/draw/tempo.js +30 -30
- package/src/write/draw/text.js +5 -5
- package/src/write/draw/tie.js +18 -18
- package/src/write/draw/triplet.js +6 -6
- package/src/write/draw/voice.js +16 -17
- package/src/write/{abc_engraver_controller.js → engraver-controller.js} +58 -51
- package/src/write/{classes.js → helpers/classes.js} +6 -6
- package/src/write/{get-font-and-attr.js → helpers/get-font-and-attr.js} +9 -7
- package/src/write/{get-text-size.js → helpers/get-text-size.js} +5 -5
- package/src/write/{set-class.js → helpers/set-class.js} +1 -1
- package/src/write/{abc_spacing.js → helpers/spacing.js} +1 -1
- package/src/write/{highlight.js → interactive/highlight.js} +1 -1
- package/src/write/{selection.js → interactive/selection.js} +34 -31
- package/src/write/{unhighlight.js → interactive/unhighlight.js} +1 -1
- package/src/write/layout/beam.js +13 -13
- package/src/write/layout/get-left-edge-of-staff.js +4 -4
- package/src/write/layout/layout.js +74 -74
- package/src/write/layout/{setUpperAndLowerElements.js → set-upper-and-lower-elements.js} +8 -8
- package/src/write/layout/{staffGroup.js → staff-group.js} +32 -32
- package/src/write/layout/triplet.js +4 -4
- package/src/write/layout/{VoiceElements.js → voice-elements.js} +23 -23
- package/src/write/layout/voice.js +6 -6
- package/src/write/{abc_renderer.js → renderer.js} +36 -32
- package/src/write/svg.js +35 -35
- package/test.js +2 -2
- package/types/index.d.ts +37 -8
- package/version.js +1 -1
- package/src/tablatures/instruments/guitar/guitar-fonts.js +0 -19
- package/src/tablatures/instruments/violin/violin-fonts.js +0 -19
- package/src/tablatures/transposer.js +0 -110
- package/src/write/abc_abstract_engraver.js +0 -1026
- package/src/write/abc_beam_element.js +0 -113
- package/src/write/abc_create_clef.js +0 -72
- package/src/write/abc_create_key_signature.js +0 -33
- package/src/write/abc_create_note_head.js +0 -107
- package/src/write/abc_create_time_signature.js +0 -55
- package/src/write/abc_decoration.js +0 -357
- package/src/write/abc_glyphs.js +0 -224
- package/src/write/abc_tempo_element.js +0 -63
- package/src/write/abc_triplet_element.js +0 -28
- package/src/write/add-chord.js +0 -103
- package/src/write/format-jazz-chord.js +0 -15
- package/src/write/free-text.js +0 -41
- /package/src/write/{abc_crescendo_element.js → creation/elements/crescendo-element.js} +0 -0
- /package/src/write/{abc_dynamic_decoration.js → creation/elements/dynamic-decoration.js} +0 -0
- /package/src/write/{abc_ending_element.js → creation/elements/ending-element.js} +0 -0
- /package/src/write/{abc_glissando_element.js → creation/elements/glissando-element.js} +0 -0
- /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('
|
|
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.
|
|
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("
|
|
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);
|