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,102 @@
|
|
|
1
|
+
var RelativeElement = require('./elements/relative-element');
|
|
2
|
+
var spacing = require('../helpers/spacing');
|
|
3
|
+
const translateChord = require("./translate-chord");
|
|
4
|
+
|
|
5
|
+
var addChord = function (getTextSize, abselem, elem, roomTaken, roomTakenRight, noteheadWidth, jazzchords, germanAlphabet) {
|
|
6
|
+
for (var i = 0; i < elem.chord.length; i++) {
|
|
7
|
+
var pos = elem.chord[i].position;
|
|
8
|
+
var rel_position = elem.chord[i].rel_position;
|
|
9
|
+
var chords = elem.chord[i].name.split("\n");
|
|
10
|
+
for (var j = chords.length - 1; j >= 0; j--) { // parse these in opposite order because we place them from bottom to top.
|
|
11
|
+
var chord = chords[j];
|
|
12
|
+
var x = 0;
|
|
13
|
+
var y;
|
|
14
|
+
var font;
|
|
15
|
+
var klass;
|
|
16
|
+
if (pos === "left" || pos === "right" || pos === "below" || pos === "above" || !!rel_position) {
|
|
17
|
+
font = 'annotationfont';
|
|
18
|
+
klass = "annotation";
|
|
19
|
+
} else {
|
|
20
|
+
font = 'gchordfont';
|
|
21
|
+
klass = "chord";
|
|
22
|
+
chord = translateChord(chord, jazzchords, germanAlphabet);
|
|
23
|
+
}
|
|
24
|
+
var attr = getTextSize.attr(font, klass);
|
|
25
|
+
var dim = getTextSize.calc(chord, font, klass);
|
|
26
|
+
var chordWidth = dim.width;
|
|
27
|
+
var chordHeight = dim.height / spacing.STEP;
|
|
28
|
+
switch (pos) {
|
|
29
|
+
case "left":
|
|
30
|
+
roomTaken += chordWidth + 7;
|
|
31
|
+
x = -roomTaken; // TODO-PER: This is just a guess from trial and error
|
|
32
|
+
y = elem.averagepitch;
|
|
33
|
+
abselem.addExtra(new RelativeElement(chord, x, chordWidth + 4, y, {
|
|
34
|
+
type: "text",
|
|
35
|
+
height: chordHeight,
|
|
36
|
+
dim: attr,
|
|
37
|
+
position: "left"
|
|
38
|
+
}));
|
|
39
|
+
break;
|
|
40
|
+
case "right":
|
|
41
|
+
roomTakenRight += 4;
|
|
42
|
+
x = roomTakenRight;// TODO-PER: This is just a guess from trial and error
|
|
43
|
+
y = elem.averagepitch;
|
|
44
|
+
abselem.addRight(new RelativeElement(chord, x, chordWidth + 4, y, {
|
|
45
|
+
type: "text",
|
|
46
|
+
height: chordHeight,
|
|
47
|
+
dim: attr,
|
|
48
|
+
position: "right"
|
|
49
|
+
}));
|
|
50
|
+
break;
|
|
51
|
+
case "below":
|
|
52
|
+
// setting the y-coordinate to undefined for now: it will be overwritten later on, after we figure out what the highest element on the line is.
|
|
53
|
+
abselem.addRight(new RelativeElement(chord, 0, 0, undefined, {
|
|
54
|
+
type: "text",
|
|
55
|
+
position: "below",
|
|
56
|
+
height: chordHeight,
|
|
57
|
+
dim: attr,
|
|
58
|
+
realWidth: chordWidth
|
|
59
|
+
}));
|
|
60
|
+
break;
|
|
61
|
+
case "above":
|
|
62
|
+
// setting the y-coordinate to undefined for now: it will be overwritten later on, after we figure out what the highest element on the line is.
|
|
63
|
+
abselem.addRight(new RelativeElement(chord, 0, 0, undefined, {
|
|
64
|
+
type: "text",
|
|
65
|
+
position: "above",
|
|
66
|
+
height: chordHeight,
|
|
67
|
+
dim: attr,
|
|
68
|
+
realWidth: chordWidth
|
|
69
|
+
}));
|
|
70
|
+
break;
|
|
71
|
+
default:
|
|
72
|
+
if (rel_position) {
|
|
73
|
+
var relPositionY = rel_position.y + 3 * spacing.STEP; // TODO-PER: this is a fudge factor to make it line up with abcm2ps
|
|
74
|
+
abselem.addRight(new RelativeElement(chord, x + rel_position.x, 0, elem.minpitch + relPositionY / spacing.STEP, {
|
|
75
|
+
position: "relative",
|
|
76
|
+
type: "text",
|
|
77
|
+
height: chordHeight,
|
|
78
|
+
dim: attr
|
|
79
|
+
}));
|
|
80
|
+
} else {
|
|
81
|
+
// setting the y-coordinate to undefined for now: it will be overwritten later on, after we figure out what the highest element on the line is.
|
|
82
|
+
var pos2 = 'above';
|
|
83
|
+
if (elem.positioning && elem.positioning.chordPosition)
|
|
84
|
+
pos2 = elem.positioning.chordPosition;
|
|
85
|
+
|
|
86
|
+
if (pos2 !== 'hidden') {
|
|
87
|
+
abselem.addCentered(new RelativeElement(chord, noteheadWidth / 2, chordWidth, undefined, {
|
|
88
|
+
type: "chord",
|
|
89
|
+
position: pos2,
|
|
90
|
+
height: chordHeight,
|
|
91
|
+
dim: attr,
|
|
92
|
+
realWidth: chordWidth
|
|
93
|
+
}));
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return { roomTaken: roomTaken, roomTakenRight: roomTakenRight };
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
module.exports = addChord;
|
|
@@ -4,11 +4,11 @@ function addTextIf(rows, params, getTextSize) {
|
|
|
4
4
|
if (!params.marginLeft) params.marginLeft = 0;
|
|
5
5
|
if (!params.klass) params.klass = '';
|
|
6
6
|
if (!params.anchor) params.anchor = 'start';
|
|
7
|
-
if (!params.info) params.info = { startChar: -2, endChar: -2}
|
|
7
|
+
if (!params.info) params.info = { startChar: -2, endChar: -2 }
|
|
8
8
|
|
|
9
9
|
if (params.marginTop)
|
|
10
|
-
rows.push({move: params.marginTop});
|
|
11
|
-
var attr = {left: params.marginLeft, text: params.text, font: params.font, anchor: params.anchor, startChar: params.info.startChar, endChar: params.info.endChar};
|
|
10
|
+
rows.push({ move: params.marginTop });
|
|
11
|
+
var attr = { left: params.marginLeft, text: params.text, font: params.font, anchor: params.anchor, startChar: params.info.startChar, endChar: params.info.endChar };
|
|
12
12
|
if (params.absElemType)
|
|
13
13
|
attr.absElemType = params.absElemType;
|
|
14
14
|
if (!params.inGroup)
|
|
@@ -20,13 +20,13 @@ function addTextIf(rows, params, getTextSize) {
|
|
|
20
20
|
// If there are blank lines they won't be counted by getTextSize, so just get the height of one line and multiply
|
|
21
21
|
var size = getTextSize.calc("A", params.font, params.klass);
|
|
22
22
|
var numLines = params.text.split("\n").length;
|
|
23
|
-
if (params.text[params.text.length-1] === '\n')
|
|
23
|
+
if (params.text[params.text.length - 1] === '\n')
|
|
24
24
|
numLines--; // If there is a new line at the end of the string, then an extra line will be counted.
|
|
25
25
|
if (!params.noMove) {
|
|
26
26
|
var h = (size.height * 1.1) * numLines;
|
|
27
|
-
rows.push({move: Math.round(h)});
|
|
27
|
+
rows.push({ move: Math.round(h) });
|
|
28
28
|
if (params.marginBottom)
|
|
29
|
-
rows.push({move: params.marginBottom});
|
|
29
|
+
rows.push({ move: params.marginBottom });
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
|
|
@@ -2,12 +2,12 @@ var calcHeight = function (staffGroup) {
|
|
|
2
2
|
// the height is calculated here in a parallel way to the drawing below in hopes that both of these functions will be modified together.
|
|
3
3
|
// TODO-PER: also add the space between staves. (That's systemStaffSeparation, which is the minimum distance between the staff LINES.)
|
|
4
4
|
var height = 0;
|
|
5
|
-
for (var i=0;i<staffGroup.voices.length;i++) {
|
|
5
|
+
for (var i = 0; i < staffGroup.voices.length; i++) {
|
|
6
6
|
var staff = staffGroup.voices[i].staff;
|
|
7
7
|
if (!staffGroup.voices[i].duplicate) {
|
|
8
8
|
height += staff.top;
|
|
9
9
|
//if (staff.bottom < 0)
|
|
10
|
-
|
|
10
|
+
height += -staff.bottom;
|
|
11
11
|
}
|
|
12
12
|
}
|
|
13
13
|
return height;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
// abc_create_clef.js
|
|
2
|
+
|
|
3
|
+
var AbsoluteElement = require('./elements/absolute-element');
|
|
4
|
+
var glyphs = require('./glyphs');
|
|
5
|
+
var RelativeElement = require('./elements/relative-element');
|
|
6
|
+
|
|
7
|
+
var createClef = function (elem, tuneNumber) {
|
|
8
|
+
var clef;
|
|
9
|
+
var octave = 0;
|
|
10
|
+
elem.el_type = "clef";
|
|
11
|
+
var abselem = new AbsoluteElement(elem, 0, 10, 'staff-extra clef', tuneNumber);
|
|
12
|
+
abselem.isClef = true;
|
|
13
|
+
switch (elem.type) {
|
|
14
|
+
case "treble": clef = "clefs.G"; break;
|
|
15
|
+
case "tenor": clef = "clefs.C"; break;
|
|
16
|
+
case "alto": clef = "clefs.C"; break;
|
|
17
|
+
case "bass": clef = "clefs.F"; break;
|
|
18
|
+
case 'treble+8': clef = "clefs.G"; octave = 1; break;
|
|
19
|
+
case 'tenor+8': clef = "clefs.C"; octave = 1; break;
|
|
20
|
+
case 'bass+8': clef = "clefs.F"; octave = 1; break;
|
|
21
|
+
case 'alto+8': clef = "clefs.C"; octave = 1; break;
|
|
22
|
+
case 'treble-8': clef = "clefs.G"; octave = -1; break;
|
|
23
|
+
case 'tenor-8': clef = "clefs.C"; octave = -1; break;
|
|
24
|
+
case 'bass-8': clef = "clefs.F"; octave = -1; break;
|
|
25
|
+
case 'alto-8': clef = "clefs.C"; octave = -1; break;
|
|
26
|
+
case 'none': return null;
|
|
27
|
+
case 'perc': clef = "clefs.perc"; break;
|
|
28
|
+
default: abselem.addFixed(new RelativeElement("clef=" + elem.type, 0, 0, undefined, { type: "debug" }));
|
|
29
|
+
}
|
|
30
|
+
// if (elem.verticalPos) {
|
|
31
|
+
// pitch = elem.verticalPos;
|
|
32
|
+
// }
|
|
33
|
+
var dx = 5;
|
|
34
|
+
if (clef) {
|
|
35
|
+
var height = glyphs.symbolHeightInPitches(clef);
|
|
36
|
+
var ofs = clefOffsets(clef);
|
|
37
|
+
abselem.addRight(new RelativeElement(clef, dx, glyphs.getSymbolWidth(clef), elem.clefPos, { top: height + elem.clefPos + ofs, bottom: elem.clefPos + ofs }));
|
|
38
|
+
|
|
39
|
+
if (octave !== 0) {
|
|
40
|
+
var scale = 2 / 3;
|
|
41
|
+
var adjustspacing = (glyphs.getSymbolWidth(clef) - glyphs.getSymbolWidth("8") * scale) / 2;
|
|
42
|
+
var pitch = (octave > 0) ? abselem.top + 3 : abselem.bottom - 1;
|
|
43
|
+
var top = (octave > 0) ? abselem.top + 3 : abselem.bottom - 3;
|
|
44
|
+
var bottom = top - 2;
|
|
45
|
+
if (elem.type === "bass-8") {
|
|
46
|
+
// The placement for bass octave is a little different. It should hug the clef.
|
|
47
|
+
pitch = 3;
|
|
48
|
+
adjustspacing = 0;
|
|
49
|
+
}
|
|
50
|
+
abselem.addRight(new RelativeElement("8", dx + adjustspacing, glyphs.getSymbolWidth("8") * scale, pitch, {
|
|
51
|
+
scalex: scale,
|
|
52
|
+
scaley: scale,
|
|
53
|
+
top: top,
|
|
54
|
+
bottom: bottom
|
|
55
|
+
}));
|
|
56
|
+
//abselem.top += 2;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
return abselem;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
function clefOffsets(clef) {
|
|
63
|
+
switch (clef) {
|
|
64
|
+
case "clefs.G": return -5;
|
|
65
|
+
case "clefs.C": return -4;
|
|
66
|
+
case "clefs.F": return -4;
|
|
67
|
+
case "clefs.perc": return -2;
|
|
68
|
+
default: return 0;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
module.exports = createClef;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// abc_create_key_signature.js
|
|
2
|
+
|
|
3
|
+
var AbsoluteElement = require('./elements/absolute-element');
|
|
4
|
+
var glyphs = require('./glyphs');
|
|
5
|
+
var RelativeElement = require('./elements/relative-element');
|
|
6
|
+
|
|
7
|
+
var createKeySignature = function (elem, tuneNumber) {
|
|
8
|
+
elem.el_type = "keySignature";
|
|
9
|
+
if (!elem.accidentals || elem.accidentals.length === 0)
|
|
10
|
+
return null;
|
|
11
|
+
var abselem = new AbsoluteElement(elem, 0, 10, 'staff-extra key-signature', tuneNumber);
|
|
12
|
+
abselem.isKeySig = true;
|
|
13
|
+
var dx = 0;
|
|
14
|
+
elem.accidentals.forEach(function (acc) {
|
|
15
|
+
var symbol;
|
|
16
|
+
var fudge = 0;
|
|
17
|
+
switch (acc.acc) {
|
|
18
|
+
case "sharp": symbol = "accidentals.sharp"; fudge = -3; break;
|
|
19
|
+
case "natural": symbol = "accidentals.nat"; break;
|
|
20
|
+
case "flat": symbol = "accidentals.flat"; fudge = -1.2; break;
|
|
21
|
+
case "quartersharp": symbol = "accidentals.halfsharp"; fudge = -2.5; break;
|
|
22
|
+
case "quarterflat": symbol = "accidentals.halfflat"; fudge = -1.2; break;
|
|
23
|
+
default: symbol = "accidentals.flat";
|
|
24
|
+
}
|
|
25
|
+
abselem.addRight(new RelativeElement(symbol, dx, glyphs.getSymbolWidth(symbol), acc.verticalPos, { thickness: glyphs.symbolHeightInPitches(symbol), top: acc.verticalPos + glyphs.symbolHeightInPitches(symbol) + fudge, bottom: acc.verticalPos + fudge }));
|
|
26
|
+
dx += glyphs.getSymbolWidth(symbol) + 2;
|
|
27
|
+
}, this);
|
|
28
|
+
return abselem;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
module.exports = createKeySignature;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
var glyphs = require('./glyphs');
|
|
2
|
+
var RelativeElement = require('./elements/relative-element');
|
|
3
|
+
|
|
4
|
+
var createNoteHead = function (abselem, c, pitchelem, options) {
|
|
5
|
+
if (!options) options = {};
|
|
6
|
+
var dir = (options.dir !== undefined) ? options.dir : null;
|
|
7
|
+
var headx = (options.headx !== undefined) ? options.headx : 0;
|
|
8
|
+
var extrax = (options.extrax !== undefined) ? options.extrax : 0;
|
|
9
|
+
var flag = (options.flag !== undefined) ? options.flag : null;
|
|
10
|
+
var dot = (options.dot !== undefined) ? options.dot : 0;
|
|
11
|
+
var dotshiftx = (options.dotshiftx !== undefined) ? options.dotshiftx : 0;
|
|
12
|
+
var scale = (options.scale !== undefined) ? options.scale : 1;
|
|
13
|
+
var accidentalSlot = (options.accidentalSlot !== undefined) ? options.accidentalSlot : [];
|
|
14
|
+
var shouldExtendStem = (options.shouldExtendStem !== undefined) ? options.shouldExtendStem : false;
|
|
15
|
+
var printAccidentals = (options.printAccidentals !== undefined) ? options.printAccidentals : true;
|
|
16
|
+
|
|
17
|
+
// TODO scale the dot as well
|
|
18
|
+
var pitch = pitchelem.verticalPos;
|
|
19
|
+
var notehead;
|
|
20
|
+
var accidentalshiftx = 0;
|
|
21
|
+
var newDotShiftX = 0;
|
|
22
|
+
var extraLeft = 0;
|
|
23
|
+
if (c === undefined)
|
|
24
|
+
abselem.addFixed(new RelativeElement("pitch is undefined", 0, 0, 0, { type: "debug" }));
|
|
25
|
+
else if (c === "") {
|
|
26
|
+
notehead = new RelativeElement(null, 0, 0, pitch);
|
|
27
|
+
} else {
|
|
28
|
+
var shiftheadx = headx;
|
|
29
|
+
if (pitchelem.printer_shift) {
|
|
30
|
+
var adjust = (pitchelem.printer_shift === "same") ? 1 : 0;
|
|
31
|
+
shiftheadx = (dir === "down") ? -glyphs.getSymbolWidth(c) * scale + adjust : glyphs.getSymbolWidth(c) * scale - adjust;
|
|
32
|
+
}
|
|
33
|
+
var opts = { scalex: scale, scaley: scale, thickness: glyphs.symbolHeightInPitches(c) * scale, name: pitchelem.name };
|
|
34
|
+
notehead = new RelativeElement(c, shiftheadx, glyphs.getSymbolWidth(c) * scale, pitch, opts);
|
|
35
|
+
notehead.stemDir = dir;
|
|
36
|
+
if (flag) {
|
|
37
|
+
var pos = pitch + ((dir === "down") ? -7 : 7) * scale;
|
|
38
|
+
// if this is a regular note, (not grace or tempo indicator) then the stem will have been stretched to the middle line if it is far from the center.
|
|
39
|
+
if (shouldExtendStem) {
|
|
40
|
+
if (dir === "down" && pos > 6)
|
|
41
|
+
pos = 6;
|
|
42
|
+
if (dir === "up" && pos < 6)
|
|
43
|
+
pos = 6;
|
|
44
|
+
}
|
|
45
|
+
//if (scale===1 && (dir==="down")?(pos>6):(pos<6)) pos=6;
|
|
46
|
+
var xdelta = (dir === "down") ? headx : headx + notehead.w - 0.6;
|
|
47
|
+
abselem.addRight(new RelativeElement(flag, xdelta, glyphs.getSymbolWidth(flag) * scale, pos, { scalex: scale, scaley: scale }));
|
|
48
|
+
}
|
|
49
|
+
newDotShiftX = notehead.w + dotshiftx - 2 + 5 * dot;
|
|
50
|
+
for (; dot > 0; dot--) {
|
|
51
|
+
var dotadjusty = (1 - Math.abs(pitch) % 2); //PER: take abs value of the pitch. And the shift still happens on ledger lines.
|
|
52
|
+
abselem.addRight(new RelativeElement("dots.dot", notehead.w + dotshiftx - 2 + 5 * dot, glyphs.getSymbolWidth("dots.dot"), pitch + dotadjusty));
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
if (notehead)
|
|
56
|
+
notehead.highestVert = pitchelem.highestVert;
|
|
57
|
+
|
|
58
|
+
if (printAccidentals && pitchelem.accidental) {
|
|
59
|
+
var symb;
|
|
60
|
+
switch (pitchelem.accidental) {
|
|
61
|
+
case "quartersharp":
|
|
62
|
+
symb = "accidentals.halfsharp";
|
|
63
|
+
break;
|
|
64
|
+
case "dblsharp":
|
|
65
|
+
symb = "accidentals.dblsharp";
|
|
66
|
+
break;
|
|
67
|
+
case "sharp":
|
|
68
|
+
symb = "accidentals.sharp";
|
|
69
|
+
break;
|
|
70
|
+
case "quarterflat":
|
|
71
|
+
symb = "accidentals.halfflat";
|
|
72
|
+
break;
|
|
73
|
+
case "flat":
|
|
74
|
+
symb = "accidentals.flat";
|
|
75
|
+
break;
|
|
76
|
+
case "dblflat":
|
|
77
|
+
symb = "accidentals.dblflat";
|
|
78
|
+
break;
|
|
79
|
+
case "natural":
|
|
80
|
+
symb = "accidentals.nat";
|
|
81
|
+
}
|
|
82
|
+
// if a note is at least a sixth away, it can share a slot with another accidental
|
|
83
|
+
var accSlotFound = false;
|
|
84
|
+
var accPlace = extrax;
|
|
85
|
+
for (var j = 0; j < accidentalSlot.length; j++) {
|
|
86
|
+
if (pitch - accidentalSlot[j][0] >= 6) {
|
|
87
|
+
accidentalSlot[j][0] = pitch;
|
|
88
|
+
accPlace = accidentalSlot[j][1];
|
|
89
|
+
accSlotFound = true;
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
if (accSlotFound === false) {
|
|
94
|
+
accPlace -= (glyphs.getSymbolWidth(symb) * scale + 2);
|
|
95
|
+
accidentalSlot.push([pitch, accPlace]);
|
|
96
|
+
accidentalshiftx = (glyphs.getSymbolWidth(symb) * scale + 2);
|
|
97
|
+
}
|
|
98
|
+
var h = glyphs.symbolHeightInPitches(symb);
|
|
99
|
+
abselem.addExtra(new RelativeElement(symb, accPlace, glyphs.getSymbolWidth(symb), pitch, { scalex: scale, scaley: scale, top: pitch + h / 2, bottom: pitch - h / 2 }));
|
|
100
|
+
extraLeft = glyphs.getSymbolWidth(symb) / 2; // TODO-PER: We need a little extra width if there is an accidental, but I'm not sure why it isn't the full width of the accidental.
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return { notehead: notehead, accidentalshiftx: accidentalshiftx, dotshiftx: newDotShiftX, extraLeft: extraLeft };
|
|
104
|
+
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
module.exports = createNoteHead;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// abc_create_time_signature.js
|
|
2
|
+
|
|
3
|
+
var AbsoluteElement = require('./elements/absolute-element');
|
|
4
|
+
var glyphs = require('./glyphs');
|
|
5
|
+
var RelativeElement = require('./elements/relative-element');
|
|
6
|
+
|
|
7
|
+
var createTimeSignature = function (elem, tuneNumber) {
|
|
8
|
+
elem.el_type = "timeSignature";
|
|
9
|
+
var abselem = new AbsoluteElement(elem, 0, 10, 'staff-extra time-signature', tuneNumber);
|
|
10
|
+
if (elem.type === "specified") {
|
|
11
|
+
var x = 0;
|
|
12
|
+
for (var i = 0; i < elem.value.length; i++) {
|
|
13
|
+
if (i !== 0) {
|
|
14
|
+
abselem.addRight(new RelativeElement('+', x + 1, glyphs.getSymbolWidth("+"), 6, { thickness: glyphs.symbolHeightInPitches("+") }));
|
|
15
|
+
x += glyphs.getSymbolWidth("+") + 2;
|
|
16
|
+
}
|
|
17
|
+
if (elem.value[i].den) {
|
|
18
|
+
var numWidth = 0;
|
|
19
|
+
for (var i2 = 0; i2 < elem.value[i].num.length; i2++)
|
|
20
|
+
numWidth += glyphs.getSymbolWidth(elem.value[i].num[i2]);
|
|
21
|
+
var denWidth = 0;
|
|
22
|
+
for (i2 = 0; i2 < elem.value[i].num.length; i2++)
|
|
23
|
+
denWidth += glyphs.getSymbolWidth(elem.value[i].den[i2]);
|
|
24
|
+
var maxWidth = Math.max(numWidth, denWidth);
|
|
25
|
+
abselem.addRight(new RelativeElement(elem.value[i].num, x + (maxWidth - numWidth) / 2, numWidth, 8, { thickness: glyphs.symbolHeightInPitches(elem.value[i].num[0]) }));
|
|
26
|
+
abselem.addRight(new RelativeElement(elem.value[i].den, x + (maxWidth - denWidth) / 2, denWidth, 4, { thickness: glyphs.symbolHeightInPitches(elem.value[i].den[0]) }));
|
|
27
|
+
x += maxWidth
|
|
28
|
+
} else {
|
|
29
|
+
var thisWidth = 0;
|
|
30
|
+
for (var i3 = 0; i3 < elem.value[i].num.length; i3++)
|
|
31
|
+
thisWidth += glyphs.getSymbolWidth(elem.value[i].num[i3]);
|
|
32
|
+
abselem.addRight(new RelativeElement(elem.value[i].num, x, thisWidth, 6, { thickness: glyphs.symbolHeightInPitches(elem.value[i].num[0]) }));
|
|
33
|
+
x += thisWidth;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
} else if (elem.type === "common_time") {
|
|
37
|
+
abselem.addRight(new RelativeElement("timesig.common", 0, glyphs.getSymbolWidth("timesig.common"), 6, { thickness: glyphs.symbolHeightInPitches("timesig.common") }));
|
|
38
|
+
|
|
39
|
+
} else if (elem.type === "cut_time") {
|
|
40
|
+
abselem.addRight(new RelativeElement("timesig.cut", 0, glyphs.getSymbolWidth("timesig.cut"), 6, { thickness: glyphs.symbolHeightInPitches("timesig.cut") }));
|
|
41
|
+
} else if (elem.type === "tempus_imperfectum") {
|
|
42
|
+
abselem.addRight(new RelativeElement("timesig.imperfectum", 0, glyphs.getSymbolWidth("timesig.imperfectum"), 6, { thickness: glyphs.symbolHeightInPitches("timesig.imperfectum") }));
|
|
43
|
+
} else if (elem.type === "tempus_imperfectum_prolatio") {
|
|
44
|
+
abselem.addRight(new RelativeElement("timesig.imperfectum2", 0, glyphs.getSymbolWidth("timesig.imperfectum2"), 6, { thickness: glyphs.symbolHeightInPitches("timesig.imperfectum2") }));
|
|
45
|
+
} else if (elem.type === "tempus_perfectum") {
|
|
46
|
+
abselem.addRight(new RelativeElement("timesig.perfectum", 0, glyphs.getSymbolWidth("timesig.perfectum"), 6, { thickness: glyphs.symbolHeightInPitches("timesig.perfectum") }));
|
|
47
|
+
} else if (elem.type === "tempus_perfectum_prolatio") {
|
|
48
|
+
abselem.addRight(new RelativeElement("timesig.perfectum2", 0, glyphs.getSymbolWidth("timesig.perfectum2"), 6, { thickness: glyphs.symbolHeightInPitches("timesig.perfectum2") }));
|
|
49
|
+
} else {
|
|
50
|
+
console.log("time signature:", elem);
|
|
51
|
+
}
|
|
52
|
+
return abselem;
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
module.exports = createTimeSignature;
|