abcjs 6.0.0-beta.9 → 6.0.2
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/.github/workflows/tests.yml +29 -0
- package/CODE_OF_CONDUCT.md +76 -0
- package/CONTRIBUTING.md +1 -0
- package/LICENSE.md +1 -1
- package/README.md +88 -7
- package/RELEASE.md +961 -1
- package/abcjs-audio.css +14 -5
- package/dist/.gitignore +1 -2
- package/dist/abcjs-basic-min.js +3 -0
- package/dist/abcjs-basic-min.js.LICENSE +23 -0
- package/dist/abcjs-basic.js +28232 -0
- package/dist/abcjs-basic.js.map +1 -0
- package/dist/abcjs-plugin-min.js +3 -0
- package/dist/abcjs-plugin-min.js.LICENSE +23 -0
- package/index.js +27 -2
- package/{static-wrappers/license.js → license.js} +1 -1
- package/package.json +26 -29
- package/{src/plugin/abc_plugin.js → plugin.js} +31 -19
- package/src/api/abc_animation.js +1 -17
- package/src/api/abc_tablatures.js +144 -0
- package/src/api/abc_timing_callbacks.js +216 -117
- package/src/api/abc_tunebook.js +18 -67
- package/src/api/abc_tunebook_svg.js +40 -48
- package/src/data/abc_tune.js +232 -972
- package/src/data/deline-tune.js +199 -0
- package/src/edit/abc_editarea.js +112 -0
- package/src/edit/abc_editor.js +95 -221
- package/src/midi/abc_midi_create.js +48 -50
- package/src/parse/abc_common.js +0 -14
- package/src/parse/abc_parse.js +167 -1321
- package/src/parse/abc_parse_book.js +62 -0
- package/src/parse/abc_parse_directive.js +164 -41
- package/src/parse/abc_parse_header.js +116 -145
- package/src/parse/abc_parse_key_voice.js +26 -20
- package/src/parse/abc_parse_music.js +1337 -0
- package/src/parse/abc_tokenizer.js +21 -15
- package/src/parse/abc_transpose.js +3 -15
- package/src/parse/tune-builder.js +896 -0
- package/src/parse/wrap_lines.js +205 -453
- package/src/synth/abc_midi_flattener.js +1292 -0
- package/src/{midi → synth}/abc_midi_renderer.js +44 -17
- package/src/synth/abc_midi_sequencer.js +648 -0
- package/src/synth/active-audio-context.js +3 -14
- package/src/synth/cents-to-factor.js +10 -0
- package/src/synth/create-note-map.js +21 -32
- package/src/synth/create-synth-control.js +20 -103
- package/src/synth/create-synth.js +185 -77
- package/src/synth/download-buffer.js +7 -21
- package/src/synth/get-midi-file.js +13 -20
- package/src/synth/images/{loading.svg → loading.svg.js} +4 -0
- package/src/synth/images/loop.svg.js +65 -0
- package/src/synth/images/pause.svg.js +10 -0
- package/src/synth/images/play.svg.js +9 -0
- package/src/synth/images/{reset.svg → reset.svg.js} +5 -1
- package/src/synth/instrument-index-to-name.js +1 -16
- package/src/synth/load-note.js +37 -76
- package/src/synth/pitch-to-note-name.js +0 -15
- package/src/synth/pitches-to-perc.js +64 -0
- package/src/synth/place-note.js +78 -68
- package/src/synth/play-event.js +17 -18
- package/src/synth/register-audio-context.js +11 -23
- package/src/synth/sounds-cache.js +0 -15
- package/src/synth/supports-audio.js +9 -23
- package/src/synth/synth-controller.js +80 -49
- package/src/synth/synth-sequence.js +20 -34
- package/src/tablatures/instruments/guitar/guitar-fonts.js +19 -0
- package/src/tablatures/instruments/guitar/guitar-patterns.js +23 -0
- package/src/tablatures/instruments/guitar/tab-guitar.js +50 -0
- package/src/tablatures/instruments/string-patterns.js +277 -0
- package/src/tablatures/instruments/string-tablature.js +56 -0
- package/src/tablatures/instruments/tab-note.js +282 -0
- package/src/tablatures/instruments/tab-notes.js +41 -0
- package/src/tablatures/instruments/violin/tab-violin.js +47 -0
- package/src/tablatures/instruments/violin/violin-fonts.js +19 -0
- package/src/tablatures/instruments/violin/violin-patterns.js +23 -0
- package/src/tablatures/tab-absolute-elements.js +310 -0
- package/src/tablatures/tab-common.js +29 -0
- package/src/tablatures/tab-renderer.js +243 -0
- package/src/tablatures/transposer.js +110 -0
- package/src/test/abc_midi_lint.js +5 -22
- package/src/test/abc_midi_sequencer_lint.js +11 -14
- package/src/test/abc_parser_lint.js +136 -32
- package/src/test/abc_vertical_lint.js +94 -32
- package/src/test/rendering-lint.js +38 -5
- package/src/write/abc_absolute_element.js +112 -120
- package/src/write/abc_abstract_engraver.js +102 -253
- package/src/write/abc_beam_element.js +30 -290
- package/src/write/abc_brace_element.js +12 -121
- package/src/write/abc_create_clef.js +21 -32
- package/src/write/abc_create_key_signature.js +8 -26
- package/src/write/abc_create_note_head.js +107 -0
- package/src/write/abc_create_time_signature.js +2 -21
- package/src/write/abc_crescendo_element.js +3 -50
- package/src/write/abc_decoration.js +7 -30
- package/src/write/abc_dynamic_decoration.js +3 -37
- package/src/write/abc_ending_element.js +1 -57
- package/src/write/abc_engraver_controller.js +111 -234
- package/src/write/abc_glyphs.js +8 -18
- package/src/write/abc_relative_element.js +57 -97
- package/src/write/abc_renderer.js +10 -832
- package/src/write/abc_spacing.js +0 -15
- package/src/write/abc_staff_group_element.js +14 -349
- package/src/write/abc_tempo_element.js +9 -117
- package/src/write/abc_tie_element.js +5 -68
- package/src/write/abc_triplet_element.js +6 -124
- package/src/write/abc_voice_element.js +7 -222
- package/src/write/add-chord.js +103 -0
- package/src/write/add-text-if.js +33 -0
- package/src/write/bottom-text.js +79 -0
- package/src/write/calcHeight.js +17 -0
- package/src/write/classes.js +100 -0
- package/src/write/draw/absolute.js +68 -0
- package/src/write/draw/beam.js +56 -0
- package/src/write/draw/brace.js +106 -0
- package/src/write/draw/crescendo.js +38 -0
- package/src/write/draw/debug-box.js +8 -0
- package/src/write/draw/draw.js +56 -0
- package/src/write/draw/dynamics.js +20 -0
- package/src/write/draw/ending.js +46 -0
- package/src/write/draw/group-elements.js +66 -0
- package/src/write/draw/horizontal-line.js +25 -0
- package/src/write/draw/non-music.js +50 -0
- package/src/write/draw/print-line.js +24 -0
- package/src/write/draw/print-path.js +7 -0
- package/src/write/draw/print-stem.js +30 -0
- package/src/write/draw/print-symbol.js +59 -0
- package/src/write/draw/print-vertical-line.js +18 -0
- package/src/write/draw/relative.js +77 -0
- package/src/write/draw/round-number.js +5 -0
- package/src/write/draw/selectables.js +59 -0
- package/src/write/draw/separator.js +16 -0
- package/src/write/draw/set-paper-size.js +45 -0
- package/src/write/{sprintf.js → draw/sprintf.js} +0 -0
- package/src/write/draw/staff-group.js +226 -0
- package/src/write/draw/staff-line.js +9 -0
- package/src/write/draw/staff.js +33 -0
- package/src/write/draw/tab-line.js +40 -0
- package/src/write/draw/tempo.js +45 -0
- package/src/write/draw/text.js +71 -0
- package/src/write/draw/tie.js +97 -0
- package/src/write/draw/triplet.js +46 -0
- package/src/write/draw/voice.js +102 -0
- package/src/write/format-jazz-chord.js +15 -0
- package/src/write/free-text.js +41 -0
- package/src/write/get-font-and-attr.js +37 -0
- package/src/write/get-text-size.js +56 -0
- package/src/write/highlight.js +11 -0
- package/src/write/layout/VoiceElements.js +121 -0
- package/src/write/layout/beam.js +213 -0
- package/src/write/layout/get-left-edge-of-staff.js +56 -0
- package/src/write/layout/getBarYAt.js +6 -0
- package/src/write/layout/layout.js +94 -0
- package/src/write/layout/setUpperAndLowerElements.js +232 -0
- package/src/write/layout/staffGroup.js +146 -0
- package/src/write/layout/triplet.js +75 -0
- package/src/write/layout/voice.js +137 -0
- package/src/write/selection.js +188 -70
- package/src/write/separator.js +10 -0
- package/src/write/set-class.js +21 -0
- package/src/write/subtitle.js +12 -0
- package/src/write/svg.js +95 -43
- package/src/write/top-text.js +54 -0
- package/src/write/unhighlight.js +11 -0
- package/test.js +27 -64
- package/types/index.d.ts +1095 -0
- package/version.js +1 -1
- package/.babelrc +0 -5
- package/.eslintrc +0 -3
- package/.gitmodules +0 -3
- package/Dockerfile +0 -8
- package/abcjs-midi.css +0 -166
- package/build-utils/loadPresets.js +0 -14
- package/build-utils/presets/webpack.analyze.js +0 -6
- package/build-utils/presets/webpack.optimize.js +0 -30
- package/build-utils/webpack.development.js +0 -14
- package/build-utils/webpack.production.js +0 -35
- package/deploy-docs.sh +0 -25
- package/docker-compose.yml +0 -13
- package/docs/README.md +0 -33
- package/fix-versions.sh +0 -23
- package/midi.js +0 -62
- package/src/api/abc_tunebook_midi.js +0 -116
- package/src/midi/abc_midi_controls.js +0 -701
- package/src/midi/abc_midi_flattener.js +0 -1119
- package/src/midi/abc_midi_js_preparer.js +0 -243
- package/src/midi/abc_midi_sequencer.js +0 -401
- package/src/midi/abc_midi_ui_generator.js +0 -86
- package/src/plugin/abc_plugin_midi.js +0 -220
- package/src/synth/images/loop.svg +0 -61
- package/src/synth/images/pause.svg +0 -6
- package/src/synth/images/play.svg +0 -5
- package/src/transform/abc2abc_write.js +0 -395
- package/static-wrappers/basic.js +0 -2
- package/static-wrappers/midi.js +0 -2
- package/static-wrappers/plugin-midi.js +0 -6
- package/static-wrappers/plugin.js +0 -6
- package/webpack.config.js +0 -29
|
@@ -1,24 +1,11 @@
|
|
|
1
1
|
// abc_abstract_engraver.js: Creates a data structure suitable for printing a line of abc
|
|
2
|
-
// Copyright (C) 2010-2020 Gregory Dyke (gregdyke at gmail dot com)
|
|
3
|
-
//
|
|
4
|
-
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
|
5
|
-
// documentation files (the "Software"), to deal in the Software without restriction, including without limitation
|
|
6
|
-
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and
|
|
7
|
-
// to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
8
|
-
//
|
|
9
|
-
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
10
|
-
//
|
|
11
|
-
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
|
|
12
|
-
// BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
13
|
-
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
14
|
-
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
15
|
-
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
16
2
|
|
|
17
3
|
var AbsoluteElement = require('./abc_absolute_element');
|
|
18
4
|
var BeamElem = require('./abc_beam_element');
|
|
19
5
|
var BraceElem = require('./abc_brace_element');
|
|
20
6
|
var createClef = require('./abc_create_clef');
|
|
21
7
|
var createKeySignature = require('./abc_create_key_signature');
|
|
8
|
+
var createNoteHead = require('./abc_create_note_head');
|
|
22
9
|
var createTimeSignature = require('./abc_create_time_signature');
|
|
23
10
|
var Decoration = require('./abc_decoration');
|
|
24
11
|
var EndingElem = require('./abc_ending_element');
|
|
@@ -30,14 +17,11 @@ var TempoElement = require('./abc_tempo_element');
|
|
|
30
17
|
var TieElem = require('./abc_tie_element');
|
|
31
18
|
var TripletElem = require('./abc_triplet_element');
|
|
32
19
|
var VoiceElement = require('./abc_voice_element');
|
|
20
|
+
var addChord = require('./add-chord');
|
|
21
|
+
var pitchesToPerc = require('../synth/pitches-to-perc')
|
|
33
22
|
|
|
34
23
|
var parseCommon = require('../parse/abc_common');
|
|
35
24
|
|
|
36
|
-
var AbstractEngraver;
|
|
37
|
-
|
|
38
|
-
(function() {
|
|
39
|
-
"use strict";
|
|
40
|
-
|
|
41
25
|
var getDuration = function(elem) {
|
|
42
26
|
var d = 0;
|
|
43
27
|
if (elem.duration) {
|
|
@@ -54,16 +38,21 @@ var hint = false;
|
|
|
54
38
|
rhythm:{"-1": "noteheads.slash.whole", 0:"noteheads.slash.whole", 1:"noteheads.slash.whole", 2:"noteheads.slash.quarter", 3:"noteheads.slash.quarter", 4:"noteheads.slash.quarter", 5:"noteheads.slash.quarter", 6:"noteheads.slash.quarter", 7:"noteheads.slash.quarter", nostem: "noteheads.slash.nostem"},
|
|
55
39
|
x:{"-1": "noteheads.indeterminate", 0:"noteheads.indeterminate", 1:"noteheads.indeterminate", 2:"noteheads.indeterminate", 3:"noteheads.indeterminate", 4:"noteheads.indeterminate", 5:"noteheads.indeterminate", 6:"noteheads.indeterminate", 7:"noteheads.indeterminate", nostem: "noteheads.indeterminate"},
|
|
56
40
|
harmonic:{"-1": "noteheads.harmonic.quarter", 0:"noteheads.harmonic.quarter", 1:"noteheads.harmonic.quarter", 2:"noteheads.harmonic.quarter", 3:"noteheads.harmonic.quarter", 4:"noteheads.harmonic.quarter", 5:"noteheads.harmonic.quarter", 6:"noteheads.harmonic.quarter", 7:"noteheads.harmonic.quarter", nostem: "noteheads.harmonic.quarter"},
|
|
41
|
+
triangle:{"-1": "noteheads.triangle.quarter", 0:"noteheads.triangle.quarter", 1:"noteheads.triangle.quarter", 2:"noteheads.triangle.quarter", 3:"noteheads.triangle.quarter", 4:"noteheads.triangle.quarter", 5:"noteheads.triangle.quarter", 6:"noteheads.triangle.quarter", 7:"noteheads.triangle.quarter", nostem: "noteheads.triangle.quarter"},
|
|
57
42
|
uflags:{3:"flags.u8th", 4:"flags.u16th", 5:"flags.u32nd", 6:"flags.u64th"},
|
|
58
43
|
dflags:{3:"flags.d8th", 4:"flags.d16th", 5:"flags.d32nd", 6:"flags.d64th"}
|
|
59
44
|
};
|
|
60
45
|
|
|
61
|
-
AbstractEngraver = function(
|
|
46
|
+
var AbstractEngraver = function(getTextSize, tuneNumber, options) {
|
|
62
47
|
this.decoration = new Decoration();
|
|
63
|
-
this.
|
|
48
|
+
this.getTextSize = getTextSize;
|
|
64
49
|
this.tuneNumber = tuneNumber;
|
|
65
50
|
this.isBagpipes = options.bagpipes;
|
|
66
51
|
this.flatBeams = options.flatbeams;
|
|
52
|
+
this.graceSlurs = options.graceSlurs;
|
|
53
|
+
this.percmap = options.percmap;
|
|
54
|
+
this.initialClef = options.initialClef
|
|
55
|
+
this.jazzchords = !!options.jazzchords
|
|
67
56
|
this.reset();
|
|
68
57
|
};
|
|
69
58
|
|
|
@@ -127,23 +116,24 @@ AbstractEngraver.prototype.popCrossLineElems = function(s,v) {
|
|
|
127
116
|
}
|
|
128
117
|
};
|
|
129
118
|
|
|
130
|
-
AbstractEngraver.prototype.createABCLine = function(staffs, tempo) {
|
|
119
|
+
AbstractEngraver.prototype.createABCLine = function(staffs, tempo, l) {
|
|
131
120
|
this.minY = 2; // PER: This will be the lowest that any note reaches. It will be used to set the dynamics row.
|
|
132
121
|
// See if there are any lyrics on this line.
|
|
133
122
|
this.containsLyrics(staffs);
|
|
134
|
-
var staffgroup = new StaffGroupElement();
|
|
123
|
+
var staffgroup = new StaffGroupElement(this.getTextSize);
|
|
135
124
|
this.tempoSet = false;
|
|
136
125
|
for (var s = 0; s < staffs.length; s++) {
|
|
137
126
|
if (hint)
|
|
138
127
|
this.restoreState();
|
|
139
128
|
hint = false;
|
|
140
|
-
this.createABCStaff(staffgroup, staffs[s], tempo, s);
|
|
129
|
+
this.createABCStaff(staffgroup, staffs[s], tempo, s, l);
|
|
141
130
|
}
|
|
142
131
|
return staffgroup;
|
|
143
132
|
};
|
|
144
133
|
|
|
145
|
-
AbstractEngraver.prototype.createABCStaff = function(staffgroup, abcstaff, tempo, s) {
|
|
134
|
+
AbstractEngraver.prototype.createABCStaff = function(staffgroup, abcstaff, tempo, s, l) {
|
|
146
135
|
// If the tempo is passed in, then the first element should get the tempo attached to it.
|
|
136
|
+
staffgroup.getTextSize.updateFonts(abcstaff);
|
|
147
137
|
for (var v = 0; v < abcstaff.voices.length; v++) {
|
|
148
138
|
var voice = new VoiceElement(v,abcstaff.voices.length);
|
|
149
139
|
if (v===0) {
|
|
@@ -152,13 +142,19 @@ AbstractEngraver.prototype.createABCStaff = function(staffgroup, abcstaff, tempo
|
|
|
152
142
|
} else {
|
|
153
143
|
voice.duplicate = true; // bar lines and other duplicate info need not be created
|
|
154
144
|
}
|
|
155
|
-
if (abcstaff.title && abcstaff.title[v])
|
|
156
|
-
|
|
145
|
+
if (abcstaff.title && abcstaff.title[v]) {
|
|
146
|
+
voice.header=abcstaff.title[v].replace(/\\n/g, "\n");
|
|
147
|
+
voice.headerPosition = 6 + staffgroup.getTextSize.baselineToCenter(voice.header, "voicefont", 'staff-extra voice-name', v, abcstaff.voices.length)/spacing.STEP;
|
|
148
|
+
}
|
|
149
|
+
if (abcstaff.clef && abcstaff.clef.type === "perc")
|
|
150
|
+
voice.isPercussion = true;
|
|
151
|
+
var clef = (!this.initialClef || l === 0) && createClef(abcstaff.clef, this.tuneNumber);
|
|
157
152
|
if (clef) {
|
|
158
153
|
if (v ===0 && abcstaff.barNumber) {
|
|
159
154
|
this.addMeasureNumber(abcstaff.barNumber, clef);
|
|
160
155
|
}
|
|
161
156
|
voice.addChild(clef);
|
|
157
|
+
this.startlimitelem = clef; // limit ties here
|
|
162
158
|
}
|
|
163
159
|
var keySig = createKeySignature(abcstaff.key, this.tuneNumber);
|
|
164
160
|
if (keySig) {
|
|
@@ -181,22 +177,27 @@ AbstractEngraver.prototype.createABCStaff = function(staffgroup, abcstaff, tempo
|
|
|
181
177
|
var isSingleLineStaff = staffLines === 1;
|
|
182
178
|
this.createABCVoice(abcstaff.voices[v],tempo, s, v, isSingleLineStaff, voice);
|
|
183
179
|
staffgroup.setStaffLimits(voice);
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
180
|
+
if (v === 0) {
|
|
181
|
+
// only do brace and bracket processing on the first voice, otherwise it would be done twice.
|
|
182
|
+
if (abcstaff.brace === "start" || (!staffgroup.brace && abcstaff.brace)) {
|
|
183
|
+
if (!staffgroup.brace)
|
|
184
|
+
staffgroup.brace = [];
|
|
185
|
+
staffgroup.brace.push(new BraceElem(voice, "brace"));
|
|
186
|
+
} else if (abcstaff.brace === "end" && staffgroup.brace) {
|
|
187
|
+
staffgroup.brace[staffgroup.brace.length - 1].setBottomStaff(voice);
|
|
188
|
+
} else if (abcstaff.brace === "continue" && staffgroup.brace) {
|
|
189
|
+
staffgroup.brace[staffgroup.brace.length - 1].continuing(voice);
|
|
190
|
+
}
|
|
191
|
+
if (abcstaff.bracket === "start" || (!staffgroup.bracket && abcstaff.bracket)) {
|
|
192
|
+
if (!staffgroup.bracket)
|
|
193
|
+
staffgroup.bracket = [];
|
|
194
|
+
staffgroup.bracket.push(new BraceElem(voice, "bracket"));
|
|
195
|
+
} else if (abcstaff.bracket === "end" && staffgroup.bracket) {
|
|
196
|
+
staffgroup.bracket[staffgroup.bracket.length - 1].setBottomStaff(voice);
|
|
197
|
+
} else if (abcstaff.bracket === "continue" && staffgroup.bracket) {
|
|
198
|
+
staffgroup.bracket[staffgroup.bracket.length - 1].continuing(voice);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
200
201
|
}
|
|
201
202
|
};
|
|
202
203
|
|
|
@@ -228,14 +229,14 @@ AbstractEngraver.prototype.createABCVoice = function(abcline, tempo, s, v, isSin
|
|
|
228
229
|
for (var slur in this.slurs) {
|
|
229
230
|
if (this.slurs.hasOwnProperty(slur)) {
|
|
230
231
|
// this is already a slur element, but it was created for the last line, so recreate it.
|
|
231
|
-
this.slurs[slur]= new TieElem({force: this.slurs[slur].force, voiceNumber: voiceNumber, stemDir: this.slurs[slur].stemDir});
|
|
232
|
+
this.slurs[slur]= new TieElem({force: this.slurs[slur].force, voiceNumber: voiceNumber, stemDir: this.slurs[slur].stemDir, style: this.slurs[slur].dotted});
|
|
232
233
|
if (hint) this.slurs[slur].setHint();
|
|
233
234
|
voice.addOther(this.slurs[slur]);
|
|
234
235
|
}
|
|
235
236
|
}
|
|
236
237
|
for (var i=0; i<this.ties.length; i++) {
|
|
237
238
|
// this is already a tie element, but it was created for the last line, so recreate it.
|
|
238
|
-
this.ties[i]=new TieElem({ force: this.ties[i].force, stemDir: this.ties[i].stemDir, voiceNumber: voiceNumber });
|
|
239
|
+
this.ties[i]=new TieElem({ force: this.ties[i].force, stemDir: this.ties[i].stemDir, voiceNumber: voiceNumber, style: this.ties[i].dotted });
|
|
239
240
|
if (hint) this.ties[i].setHint();
|
|
240
241
|
voice.addOther(this.ties[i]);
|
|
241
242
|
}
|
|
@@ -254,8 +255,8 @@ AbstractEngraver.prototype.createABCVoice = function(abcline, tempo, s, v, isSin
|
|
|
254
255
|
for (i = 0; i < abselems.length; i++) {
|
|
255
256
|
if (!this.tempoSet && tempo && !tempo.suppress) {
|
|
256
257
|
this.tempoSet = true;
|
|
257
|
-
var tempoElement = new AbsoluteElement(
|
|
258
|
-
tempoElement.
|
|
258
|
+
var tempoElement = new AbsoluteElement(tempo, 0, 0, "tempo", this.tuneNumber, {});
|
|
259
|
+
tempoElement.addFixedX(new TempoElement(tempo, this.tuneNumber, createNoteHead));
|
|
259
260
|
voice.addChild(tempoElement);
|
|
260
261
|
}
|
|
261
262
|
voice.addChild(abselems[i]);
|
|
@@ -331,17 +332,17 @@ AbstractEngraver.prototype.createABCElement = function(isFirstStaff, isSingleLin
|
|
|
331
332
|
if (voice.duplicate && elemset.length > 0) elemset[0].invisible = true;
|
|
332
333
|
break;
|
|
333
334
|
case "stem":
|
|
334
|
-
this.stemdir=elem.direction;
|
|
335
|
+
this.stemdir=elem.direction === "auto" ? undefined : elem.direction;
|
|
335
336
|
break;
|
|
336
337
|
case "part":
|
|
337
338
|
var abselem = new AbsoluteElement(elem,0,0, 'part', this.tuneNumber);
|
|
338
|
-
var dim = this.
|
|
339
|
-
abselem.
|
|
339
|
+
var dim = this.getTextSize.calc(elem.title, 'partsfont', "part");
|
|
340
|
+
abselem.addFixedX(new RelativeElement(elem.title, 0, 0, undefined, {type:"part", height: dim.height/spacing.STEP}));
|
|
340
341
|
elemset[0] = abselem;
|
|
341
342
|
break;
|
|
342
343
|
case "tempo":
|
|
343
344
|
var abselem3 = new AbsoluteElement(elem,0,0, 'tempo', this.tuneNumber);
|
|
344
|
-
abselem3.
|
|
345
|
+
abselem3.addFixedX(new TempoElement(elem, this.tuneNumber, createNoteHead));
|
|
345
346
|
elemset[0] = abselem3;
|
|
346
347
|
break;
|
|
347
348
|
case "style":
|
|
@@ -363,7 +364,7 @@ AbstractEngraver.prototype.createABCElement = function(isFirstStaff, isSingleLin
|
|
|
363
364
|
|
|
364
365
|
default:
|
|
365
366
|
var abselem2 = new AbsoluteElement(elem,0,0, 'unsupported', this.tuneNumber);
|
|
366
|
-
abselem2.
|
|
367
|
+
abselem2.addFixed(new RelativeElement("element type "+elem.el_type, 0, 0, undefined, {type:"debug"}));
|
|
367
368
|
elemset[0] = abselem2;
|
|
368
369
|
}
|
|
369
370
|
|
|
@@ -383,26 +384,11 @@ AbstractEngraver.prototype.createABCElement = function(isFirstStaff, isSingleLin
|
|
|
383
384
|
}
|
|
384
385
|
}
|
|
385
386
|
|
|
386
|
-
AbstractEngraver.prototype.calcBeamDir = function (isSingleLineStaff, voice, elems) {
|
|
387
|
-
if (this.stemdir) // If the user or voice is forcing the stem direction, we already know the answer.
|
|
388
|
-
return this.stemdir;
|
|
389
|
-
var beamelem = new BeamElem(this.stemHeight * this.voiceScale, this.stemdir, this.flatBeams);
|
|
390
|
-
for (var i = 0; i < elems.length; i++) {
|
|
391
|
-
beamelem.add({abcelem: elems[i]}); // This is a hack to call beam elem with just a minimum of processing: for our purposes, we don't need to construct the whole note.
|
|
392
|
-
}
|
|
393
|
-
|
|
394
|
-
var dir = beamelem.calcDir();
|
|
395
|
-
return dir ? "up" : "down";
|
|
396
|
-
};
|
|
397
|
-
|
|
398
387
|
AbstractEngraver.prototype.createBeam = function (isSingleLineStaff, voice, elems) {
|
|
399
388
|
var abselemset = [];
|
|
400
389
|
|
|
401
|
-
var
|
|
402
|
-
var beamelem = new BeamElem(this.stemHeight * this.voiceScale, dir, this.flatBeams, elems[0]);
|
|
390
|
+
var beamelem = new BeamElem(this.stemHeight * this.voiceScale, this.stemdir, this.flatBeams, elems[0]);
|
|
403
391
|
if (hint) beamelem.setHint();
|
|
404
|
-
var oldDir = this.stemdir;
|
|
405
|
-
this.stemdir = dir;
|
|
406
392
|
for (var i = 0; i < elems.length; i++) {
|
|
407
393
|
var elem = elems[i];
|
|
408
394
|
var abselem = this.createNote(elem, true, isSingleLineStaff, voice);
|
|
@@ -414,7 +400,7 @@ AbstractEngraver.prototype.createABCElement = function(isFirstStaff, isSingleLin
|
|
|
414
400
|
this.tripletmultiplier = 1;
|
|
415
401
|
}
|
|
416
402
|
}
|
|
417
|
-
|
|
403
|
+
beamelem.calcDir();
|
|
418
404
|
voice.addBeam(beamelem);
|
|
419
405
|
return abselemset;
|
|
420
406
|
};
|
|
@@ -437,20 +423,20 @@ var sortPitch = function(elem) {
|
|
|
437
423
|
var ledgerLines = function(abselem, minPitch, maxPitch, isRest, symbolWidth, additionalLedgers, dir, dx, scale) {
|
|
438
424
|
for (var i=maxPitch; i>11; i--) {
|
|
439
425
|
if (i%2===0 && !isRest) {
|
|
440
|
-
abselem.
|
|
426
|
+
abselem.addFixed(new RelativeElement(null, dx, (symbolWidth+4)*scale, i, {type:"ledger"}));
|
|
441
427
|
}
|
|
442
428
|
}
|
|
443
429
|
|
|
444
430
|
for (i=minPitch; i<1; i++) {
|
|
445
431
|
if (i%2===0 && !isRest) {
|
|
446
|
-
abselem.
|
|
432
|
+
abselem.addFixed(new RelativeElement(null, dx, (symbolWidth+4)*scale, i, {type:"ledger"}));
|
|
447
433
|
}
|
|
448
434
|
}
|
|
449
435
|
|
|
450
436
|
for (i = 0; i < additionalLedgers.length; i++) { // PER: draw additional ledgers
|
|
451
437
|
var ofs = symbolWidth;
|
|
452
438
|
if (dir === 'down') ofs = -ofs;
|
|
453
|
-
abselem.
|
|
439
|
+
abselem.addFixed(new RelativeElement(null, ofs+dx, (symbolWidth+4)*scale, additionalLedgers[i], {type:"ledger"}));
|
|
454
440
|
}
|
|
455
441
|
};
|
|
456
442
|
|
|
@@ -467,6 +453,7 @@ var ledgerLines = function(abselem, minPitch, maxPitch, isRest, symbolWidth, add
|
|
|
467
453
|
gracebeam.mainNote = abselem; // this gives us a reference back to the note this is attached to so that the stems can be attached somewhere.
|
|
468
454
|
}
|
|
469
455
|
|
|
456
|
+
var i;
|
|
470
457
|
var graceoffsets = [];
|
|
471
458
|
for (i = elem.gracenotes.length - 1; i >= 0; i--) { // figure out where to place each gracenote
|
|
472
459
|
roomtaken += 10;
|
|
@@ -476,13 +463,13 @@ var ledgerLines = function(abselem, minPitch, maxPitch, isRest, symbolWidth, add
|
|
|
476
463
|
}
|
|
477
464
|
}
|
|
478
465
|
|
|
479
|
-
var i;
|
|
480
466
|
for (i = 0; i < elem.gracenotes.length; i++) {
|
|
481
467
|
var gracepitch = elem.gracenotes[i].verticalPos;
|
|
482
468
|
|
|
483
469
|
flag = (gracebeam) ? null : chartable.uflags[(isBagpipes) ? 5 : 3];
|
|
484
470
|
var accidentalSlot = [];
|
|
485
|
-
var ret = createNoteHead(abselem, "noteheads.quarter", elem.gracenotes[i],
|
|
471
|
+
var ret = createNoteHead(abselem, "noteheads.quarter", elem.gracenotes[i],
|
|
472
|
+
{dir: "up", headx: -graceoffsets[i], extrax: -graceoffsets[i], flag: flag, scale: gracescale*this.voiceScale, accidentalSlot: accidentalSlot});
|
|
486
473
|
ret.notehead.highestVert = ret.notehead.pitch + stemHeight;
|
|
487
474
|
var grace = ret.notehead;
|
|
488
475
|
this.addSlursAndTies(abselem, elem.gracenotes[i], grace, voice, "up", true);
|
|
@@ -511,14 +498,19 @@ var ledgerLines = function(abselem, minPitch, maxPitch, isRest, symbolWidth, add
|
|
|
511
498
|
}
|
|
512
499
|
ledgerLines(abselem, gracepitch, gracepitch, false, glyphs.getSymbolWidth("noteheads.quarter"), [], true, grace.dx - 1, 0.6);
|
|
513
500
|
|
|
514
|
-
if
|
|
501
|
+
// if this is the first grace note, we might want to start a slur.
|
|
502
|
+
// there is a slur if graceSlurs is specifically set.
|
|
503
|
+
// there is no slur if it is bagpipes.
|
|
504
|
+
// there is not a slur if the element is a spacer or invisible rest.
|
|
505
|
+
var isInvisibleRest = elem.rest && (elem.rest.type === "spacer" || elem.rest.type === "invisible");
|
|
506
|
+
if (i === 0 && !isBagpipes && this.graceSlurs && !isInvisibleRest) {
|
|
515
507
|
// This is the overall slur that is under the grace notes.
|
|
516
|
-
var isTie = (elem.gracenotes.length === 1 && grace.pitch === notehead.pitch);
|
|
517
508
|
voice.addOther(new TieElem({ anchor1: grace, anchor2: notehead, isGrace: true}));
|
|
518
509
|
}
|
|
519
510
|
}
|
|
520
511
|
|
|
521
512
|
if (gracebeam) {
|
|
513
|
+
gracebeam.calcDir();
|
|
522
514
|
voice.addBeam(gracebeam);
|
|
523
515
|
}
|
|
524
516
|
return roomtaken;
|
|
@@ -563,6 +555,7 @@ var ledgerLines = function(abselem, minPitch, maxPitch, isRest, symbolWidth, add
|
|
|
563
555
|
elem.maxpitch = restpitch;
|
|
564
556
|
break;
|
|
565
557
|
case "invisible":
|
|
558
|
+
case "invisible-multimeasure":
|
|
566
559
|
case "spacer":
|
|
567
560
|
c = "";
|
|
568
561
|
elem.averagepitch = restpitch;
|
|
@@ -576,12 +569,13 @@ var ledgerLines = function(abselem, minPitch, maxPitch, isRest, symbolWidth, add
|
|
|
576
569
|
elem.maxpitch = restpitch;
|
|
577
570
|
dot = 0;
|
|
578
571
|
var mmWidth = glyphs.getSymbolWidth(c);
|
|
579
|
-
abselem.addHead(new RelativeElement(c,
|
|
580
|
-
var numMeasures = new RelativeElement("" + elem.
|
|
572
|
+
abselem.addHead(new RelativeElement(c, mmWidth, mmWidth * 2, 7));
|
|
573
|
+
var numMeasures = new RelativeElement("" + elem.rest.text, mmWidth, mmWidth, 16, {type: "multimeasure-text"});
|
|
581
574
|
abselem.addExtra(numMeasures);
|
|
582
575
|
}
|
|
583
|
-
if (elem.rest.type !== "
|
|
584
|
-
var ret = createNoteHead(abselem, c, {verticalPos: restpitch},
|
|
576
|
+
if (elem.rest.type.indexOf("multimeasure") < 0 && elem.rest.type !== "invisible") {
|
|
577
|
+
var ret = createNoteHead(abselem, c, {verticalPos: restpitch},
|
|
578
|
+
{ dot: dot, scale: voiceScale});
|
|
585
579
|
noteHead = ret.notehead;
|
|
586
580
|
if (noteHead) {
|
|
587
581
|
abselem.addHead(noteHead);
|
|
@@ -661,6 +655,13 @@ var ledgerLines = function(abselem, minPitch, maxPitch, isRest, symbolWidth, add
|
|
|
661
655
|
var c;
|
|
662
656
|
if (elem.pitches[p].style) { // There is a style for the whole group of pitches, but there could also be an override for a particular pitch.
|
|
663
657
|
c = chartable[elem.pitches[p].style][-durlog];
|
|
658
|
+
} else if (voice.isPercussion && this.percmap) {
|
|
659
|
+
c = noteSymbol;
|
|
660
|
+
var percHead = this.percmap[pitchesToPerc(elem.pitches[p])];
|
|
661
|
+
if (percHead && percHead.noteHead) {
|
|
662
|
+
if (chartable[percHead.noteHead])
|
|
663
|
+
c = chartable[percHead.noteHead][-durlog];
|
|
664
|
+
}
|
|
664
665
|
} else
|
|
665
666
|
c = noteSymbol;
|
|
666
667
|
// The highest position for the sake of placing slurs is itself if the slur is internal. It is the highest position possible if the slur is for the whole chord.
|
|
@@ -694,7 +695,8 @@ var ledgerLines = function(abselem, minPitch, maxPitch, isRest, symbolWidth, add
|
|
|
694
695
|
}
|
|
695
696
|
|
|
696
697
|
var hasStem = !nostem && durlog<=-1;
|
|
697
|
-
var ret = createNoteHead(abselem, c, elem.pitches[p],
|
|
698
|
+
var ret = createNoteHead(abselem, c, elem.pitches[p],
|
|
699
|
+
{dir: dir, extrax: -roomTaken, flag: flag, dot: dot, dotshiftx: dotshiftx, scale: this.voiceScale, accidentalSlot: accidentalSlot, shouldExtendStem: !stemdir, printAccidentals: !voice.isPercussion});
|
|
698
700
|
symbolWidth = Math.max(glyphs.getSymbolWidth(c), symbolWidth);
|
|
699
701
|
abselem.extraw -= ret.extraLeft;
|
|
700
702
|
noteHead = ret.notehead;
|
|
@@ -721,13 +723,13 @@ var ledgerLines = function(abselem, minPitch, maxPitch, isRest, symbolWidth, add
|
|
|
721
723
|
var dx = (dir==="down" || abselem.heads.length === 0)?0:abselem.heads[0].w;
|
|
722
724
|
var width = (dir==="down")?1:-1;
|
|
723
725
|
// TODO-PER-HACK: One type of note head has a different placement of the stem. This should be more generically calculated:
|
|
724
|
-
if (noteHead.c === 'noteheads.slash.quarter') {
|
|
726
|
+
if (noteHead && noteHead.c === 'noteheads.slash.quarter') {
|
|
725
727
|
if (dir === 'down')
|
|
726
728
|
p2 -= 1;
|
|
727
729
|
else
|
|
728
730
|
p1 += 1;
|
|
729
731
|
}
|
|
730
|
-
abselem.
|
|
732
|
+
abselem.addRight(new RelativeElement(null, dx, 0, p1, {"type": "stem", "pitch2":p2, linewidth: width, bottom: p1-1}));
|
|
731
733
|
//var RelativeElement = function RelativeElement(c, dx, w, pitch, opt) {
|
|
732
734
|
min = Math.min(p1, p2);
|
|
733
735
|
}
|
|
@@ -740,65 +742,9 @@ var ledgerLines = function(abselem, minPitch, maxPitch, isRest, symbolWidth, add
|
|
|
740
742
|
var div = ly.divider === ' ' ? "" : ly.divider;
|
|
741
743
|
lyricStr += ly.syllable + div + "\n";
|
|
742
744
|
});
|
|
743
|
-
var lyricDim = this.
|
|
745
|
+
var lyricDim = this.getTextSize.calc(lyricStr, 'vocalfont', "lyric");
|
|
744
746
|
var position = elem.positioning ? elem.positioning.vocalPosition : 'below';
|
|
745
|
-
abselem.addCentered(new RelativeElement(lyricStr, 0, lyricDim.width, undefined, {type:"lyric", position: position, height: lyricDim.height / spacing.STEP }));
|
|
746
|
-
};
|
|
747
|
-
|
|
748
|
-
AbstractEngraver.prototype.addChord = function(abselem, elem, roomTaken, roomTakenRight) {
|
|
749
|
-
var chordMargin = 8; // If there are chords next to each other, this is how close they can get.
|
|
750
|
-
for (var i = 0; i < elem.chord.length; i++) {
|
|
751
|
-
var chord = elem.chord[i];
|
|
752
|
-
var x = 0;
|
|
753
|
-
var y;
|
|
754
|
-
var font;
|
|
755
|
-
var klass;
|
|
756
|
-
if (chord.position === "left" || chord.position === "right" || chord.position === "below" || chord.position === "above") {
|
|
757
|
-
font = 'annotationfont';
|
|
758
|
-
klass = "annotation";
|
|
759
|
-
} else {
|
|
760
|
-
font = 'gchordfont';
|
|
761
|
-
klass = "chord";
|
|
762
|
-
}
|
|
763
|
-
var dim = this.renderer.getTextSize(chord.name, 'annotationfont', "annotation");
|
|
764
|
-
var chordWidth = dim.width;
|
|
765
|
-
var chordHeight = dim.height / spacing.STEP;
|
|
766
|
-
switch (chord.position) {
|
|
767
|
-
case "left":
|
|
768
|
-
roomTaken+=chordWidth+7;
|
|
769
|
-
x = -roomTaken; // TODO-PER: This is just a guess from trial and error
|
|
770
|
-
y = elem.averagepitch;
|
|
771
|
-
abselem.addExtra(new RelativeElement(chord.name, x, chordWidth+4, y, {type:"text", height: chordHeight}));
|
|
772
|
-
break;
|
|
773
|
-
case "right":
|
|
774
|
-
roomTakenRight+=4;
|
|
775
|
-
x = roomTakenRight;// TODO-PER: This is just a guess from trial and error
|
|
776
|
-
y = elem.averagepitch;
|
|
777
|
-
abselem.addRight(new RelativeElement(chord.name, x, chordWidth+4, y, {type:"text", height: chordHeight}));
|
|
778
|
-
break;
|
|
779
|
-
case "below":
|
|
780
|
-
// 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.
|
|
781
|
-
abselem.addRight(new RelativeElement(chord.name, 0, chordWidth+chordMargin, undefined, {type: "text", position: "below", height: chordHeight}));
|
|
782
|
-
break;
|
|
783
|
-
case "above":
|
|
784
|
-
// 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.
|
|
785
|
-
abselem.addRight(new RelativeElement(chord.name, 0, chordWidth+chordMargin, undefined, {type: "text", height: chordHeight}));
|
|
786
|
-
break;
|
|
787
|
-
default:
|
|
788
|
-
if (chord.rel_position) {
|
|
789
|
-
var relPositionY = chord.rel_position.y + 3*spacing.STEP; // TODO-PER: this is a fudge factor to make it line up with abcm2ps
|
|
790
|
-
abselem.addChild(new RelativeElement(chord.name, x + chord.rel_position.x, 0, elem.minpitch + relPositionY / spacing.STEP, {type: "text", height: chordHeight}));
|
|
791
|
-
} else {
|
|
792
|
-
// 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.
|
|
793
|
-
var pos2 = 'above';
|
|
794
|
-
if (elem.positioning && elem.positioning.chordPosition)
|
|
795
|
-
pos2 = elem.positioning.chordPosition;
|
|
796
|
-
|
|
797
|
-
abselem.addCentered(new RelativeElement(chord.name, x, chordWidth, undefined, {type: "chord", position: pos2, height: chordHeight }));
|
|
798
|
-
}
|
|
799
|
-
}
|
|
800
|
-
}
|
|
801
|
-
return { roomTaken: roomTaken, roomTakenRight: roomTakenRight };
|
|
747
|
+
abselem.addCentered(new RelativeElement(lyricStr, 0, lyricDim.width, undefined, {type:"lyric", position: position, height: lyricDim.height / spacing.STEP, dim: this.getTextSize.attr('vocalfont', "lyric") }));
|
|
802
748
|
};
|
|
803
749
|
|
|
804
750
|
AbstractEngraver.prototype.createNote = function(elem, nostem, isSingleLineStaff, voice) { //stem presence: true for drawing stemless notehead
|
|
@@ -808,7 +754,6 @@ AbstractEngraver.prototype.createNote = function(elem, nostem, isSingleLineStaff
|
|
|
808
754
|
var symbolWidth = 0;
|
|
809
755
|
var additionalLedgers = []; // PER: handle the case of [bc'], where the b doesn't have a ledger line
|
|
810
756
|
|
|
811
|
-
var i;
|
|
812
757
|
var dir;
|
|
813
758
|
|
|
814
759
|
var duration = getDuration(elem);
|
|
@@ -827,12 +772,14 @@ AbstractEngraver.prototype.createNote = function(elem, nostem, isSingleLineStaff
|
|
|
827
772
|
var durationForSpacing = duration * this.tripletmultiplier;
|
|
828
773
|
if (elem.rest && elem.rest.type === 'multimeasure')
|
|
829
774
|
durationForSpacing = 1;
|
|
775
|
+
if (elem.rest && elem.rest.type === 'invisible-multimeasure')
|
|
776
|
+
durationForSpacing = this.measureLength*elem.rest.text;
|
|
830
777
|
var absType = elem.rest ? "rest" : "note";
|
|
831
778
|
var abselem = new AbsoluteElement(elem, durationForSpacing, 1, absType, this.tuneNumber, { durationClassOveride: elem.duration * this.tripletmultiplier});
|
|
832
779
|
if (hint) abselem.setHint();
|
|
833
780
|
|
|
834
781
|
if (elem.rest) {
|
|
835
|
-
if (this.measureLength === duration && elem.rest.type !== 'invisible' && elem.rest.type !== 'spacer')
|
|
782
|
+
if (this.measureLength === duration && elem.rest.type !== 'invisible' && elem.rest.type !== 'spacer' && elem.rest.type.indexOf('multimeasure') < 0)
|
|
836
783
|
elem.rest.type = 'whole'; // If the rest is exactly a measure, always use a whole rest
|
|
837
784
|
var ret1 = addRestToAbsElement(abselem, elem, duration, dot, voice.voicetotal > 1, this.stemdir, isSingleLineStaff, durlog, this.voiceScale);
|
|
838
785
|
notehead = ret1.noteHead;
|
|
@@ -863,19 +810,18 @@ AbstractEngraver.prototype.createNote = function(elem, nostem, isSingleLineStaff
|
|
|
863
810
|
}
|
|
864
811
|
|
|
865
812
|
if (elem.barNumber) {
|
|
866
|
-
abselem.
|
|
813
|
+
abselem.addFixed(new RelativeElement(elem.barNumber, -10, 0, 0, {type:"barNumber"}));
|
|
867
814
|
}
|
|
868
815
|
|
|
869
816
|
// ledger lines
|
|
870
817
|
ledgerLines(abselem, elem.minpitch, elem.maxpitch, elem.rest, symbolWidth, additionalLedgers, dir, -2, 1);
|
|
871
818
|
|
|
872
819
|
if (elem.chord !== undefined) {
|
|
873
|
-
|
|
820
|
+
var ret3 = addChord(this.getTextSize, abselem, elem, roomtaken, roomtakenright, symbolWidth, this.jazzchords);
|
|
874
821
|
roomtaken = ret3.roomTaken;
|
|
875
822
|
roomtakenright = ret3.roomTakenRight;
|
|
876
823
|
}
|
|
877
824
|
|
|
878
|
-
|
|
879
825
|
if (elem.startTriplet) {
|
|
880
826
|
this.triplet = new TripletElem(elem.startTriplet, notehead, { flatBeams: this.flatBeams }); // above is opposite from case of slurs
|
|
881
827
|
}
|
|
@@ -884,108 +830,13 @@ AbstractEngraver.prototype.createNote = function(elem, nostem, isSingleLineStaff
|
|
|
884
830
|
this.triplet.setCloseAnchor(notehead);
|
|
885
831
|
}
|
|
886
832
|
|
|
887
|
-
if (this.triplet && !elem.startTriplet && !elem.endTriplet) {
|
|
833
|
+
if (this.triplet && !elem.startTriplet && !elem.endTriplet && !(elem.rest && elem.rest.type === "spacer")) {
|
|
888
834
|
this.triplet.middleNote(notehead);
|
|
889
835
|
}
|
|
890
836
|
|
|
891
|
-
|
|
892
837
|
return abselem;
|
|
893
838
|
};
|
|
894
839
|
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
var createNoteHead = function(abselem, c, pitchelem, dir, headx, extrax, flag, dot, dotshiftx, scale, accidentalSlot, shouldExtendStem) {
|
|
899
|
-
// TODO scale the dot as well
|
|
900
|
-
var pitch = pitchelem.verticalPos;
|
|
901
|
-
var notehead;
|
|
902
|
-
var i;
|
|
903
|
-
var accidentalshiftx = 0;
|
|
904
|
-
var newDotShiftX = 0;
|
|
905
|
-
var extraLeft = 0;
|
|
906
|
-
if (c === undefined)
|
|
907
|
-
abselem.addChild(new RelativeElement("pitch is undefined", 0, 0, 0, {type:"debug"}));
|
|
908
|
-
else if (c==="") {
|
|
909
|
-
notehead = new RelativeElement(null, 0, 0, pitch);
|
|
910
|
-
} else {
|
|
911
|
-
var shiftheadx = headx;
|
|
912
|
-
if (pitchelem.printer_shift) {
|
|
913
|
-
var adjust = (pitchelem.printer_shift==="same")?1:0;
|
|
914
|
-
shiftheadx = (dir==="down")?-glyphs.getSymbolWidth(c)*scale+adjust:glyphs.getSymbolWidth(c)*scale-adjust;
|
|
915
|
-
}
|
|
916
|
-
var opts = {scalex:scale, scaley: scale, thickness: glyphs.symbolHeightInPitches(c)*scale };
|
|
917
|
-
notehead = new RelativeElement(c, shiftheadx, glyphs.getSymbolWidth(c)*scale, pitch, opts);
|
|
918
|
-
notehead.stemDir = dir;
|
|
919
|
-
if (flag) {
|
|
920
|
-
var pos = pitch+((dir==="down")?-7:7)*scale;
|
|
921
|
-
// 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.
|
|
922
|
-
if (shouldExtendStem) {
|
|
923
|
-
if (dir==="down" && pos > 6)
|
|
924
|
-
pos = 6;
|
|
925
|
-
if (dir==="up" && pos < 6)
|
|
926
|
-
pos = 6;
|
|
927
|
-
}
|
|
928
|
-
//if (scale===1 && (dir==="down")?(pos>6):(pos<6)) pos=6;
|
|
929
|
-
var xdelta = (dir==="down")?headx:headx+notehead.w-0.6;
|
|
930
|
-
abselem.addRight(new RelativeElement(flag, xdelta, glyphs.getSymbolWidth(flag)*scale, pos, {scalex:scale, scaley: scale}));
|
|
931
|
-
}
|
|
932
|
-
newDotShiftX = notehead.w+dotshiftx-2+5*dot;
|
|
933
|
-
for (;dot>0;dot--) {
|
|
934
|
-
var dotadjusty = (1-Math.abs(pitch)%2); //PER: take abs value of the pitch. And the shift still happens on ledger lines.
|
|
935
|
-
abselem.addRight(new RelativeElement("dots.dot", notehead.w+dotshiftx-2+5*dot, glyphs.getSymbolWidth("dots.dot"), pitch+dotadjusty));
|
|
936
|
-
}
|
|
937
|
-
}
|
|
938
|
-
if (notehead)
|
|
939
|
-
notehead.highestVert = pitchelem.highestVert;
|
|
940
|
-
|
|
941
|
-
if (pitchelem.accidental) {
|
|
942
|
-
var symb;
|
|
943
|
-
switch (pitchelem.accidental) {
|
|
944
|
-
case "quartersharp":
|
|
945
|
-
symb = "accidentals.halfsharp";
|
|
946
|
-
break;
|
|
947
|
-
case "dblsharp":
|
|
948
|
-
symb = "accidentals.dblsharp";
|
|
949
|
-
break;
|
|
950
|
-
case "sharp":
|
|
951
|
-
symb = "accidentals.sharp";
|
|
952
|
-
break;
|
|
953
|
-
case "quarterflat":
|
|
954
|
-
symb = "accidentals.halfflat";
|
|
955
|
-
break;
|
|
956
|
-
case "flat":
|
|
957
|
-
symb = "accidentals.flat";
|
|
958
|
-
break;
|
|
959
|
-
case "dblflat":
|
|
960
|
-
symb = "accidentals.dblflat";
|
|
961
|
-
break;
|
|
962
|
-
case "natural":
|
|
963
|
-
symb = "accidentals.nat";
|
|
964
|
-
}
|
|
965
|
-
// if a note is at least a sixth away, it can share a slot with another accidental
|
|
966
|
-
var accSlotFound = false;
|
|
967
|
-
var accPlace = extrax;
|
|
968
|
-
for (var j = 0; j < accidentalSlot.length; j++) {
|
|
969
|
-
if (pitch - accidentalSlot[j][0] >= 6) {
|
|
970
|
-
accidentalSlot[j][0] = pitch;
|
|
971
|
-
accPlace = accidentalSlot[j][1];
|
|
972
|
-
accSlotFound = true;
|
|
973
|
-
break;
|
|
974
|
-
}
|
|
975
|
-
}
|
|
976
|
-
if (accSlotFound === false) {
|
|
977
|
-
accPlace -= (glyphs.getSymbolWidth(symb)*scale+2);
|
|
978
|
-
accidentalSlot.push([pitch,accPlace]);
|
|
979
|
-
accidentalshiftx = (glyphs.getSymbolWidth(symb)*scale+2);
|
|
980
|
-
}
|
|
981
|
-
abselem.addExtra(new RelativeElement(symb, accPlace, glyphs.getSymbolWidth(symb), pitch, {scalex:scale, scaley: scale}));
|
|
982
|
-
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.
|
|
983
|
-
}
|
|
984
|
-
|
|
985
|
-
return { notehead: notehead, accidentalshiftx: accidentalshiftx, dotshiftx: newDotShiftX, extraLeft: extraLeft };
|
|
986
|
-
|
|
987
|
-
};
|
|
988
|
-
|
|
989
840
|
AbstractEngraver.prototype.addSlursAndTies = function(abselem, pitchelem, notehead, voice, dir, isGrace) {
|
|
990
841
|
if (pitchelem.endTie) {
|
|
991
842
|
if (this.ties.length > 0) {
|
|
@@ -1008,7 +859,7 @@ var createNoteHead = function(abselem, c, pitchelem, dir, headx, extrax, flag, d
|
|
|
1008
859
|
|
|
1009
860
|
var voiceNumber = voice.voicetotal < 2 ? -1 : voice.voicenumber;
|
|
1010
861
|
if (pitchelem.startTie) {
|
|
1011
|
-
var tie = new TieElem({ anchor1: notehead, force: (this.stemdir==="down" || this.stemdir==="up"), stemDir: this.stemdir, isGrace: isGrace, voiceNumber: voiceNumber});
|
|
862
|
+
var tie = new TieElem({ anchor1: notehead, force: (this.stemdir==="down" || this.stemdir==="up"), stemDir: this.stemdir, isGrace: isGrace, voiceNumber: voiceNumber, style: pitchelem.startTie.style });
|
|
1012
863
|
if (hint) tie.setHint();
|
|
1013
864
|
|
|
1014
865
|
this.ties[this.ties.length]=tie;
|
|
@@ -1019,10 +870,11 @@ var createNoteHead = function(abselem, c, pitchelem, dir, headx, extrax, flag, d
|
|
|
1019
870
|
abselem.startTie = true;
|
|
1020
871
|
}
|
|
1021
872
|
|
|
873
|
+
var slur;
|
|
874
|
+
var slurid;
|
|
1022
875
|
if (pitchelem.endSlur) {
|
|
1023
876
|
for (var i=0; i<pitchelem.endSlur.length; i++) {
|
|
1024
|
-
|
|
1025
|
-
var slur;
|
|
877
|
+
slurid = pitchelem.endSlur[i];
|
|
1026
878
|
if (this.slurs[slurid]) {
|
|
1027
879
|
slur = this.slurs[slurid];
|
|
1028
880
|
slur.setEndAnchor(notehead);
|
|
@@ -1046,8 +898,8 @@ var createNoteHead = function(abselem, c, pitchelem, dir, headx, extrax, flag, d
|
|
|
1046
898
|
|
|
1047
899
|
if (pitchelem.startSlur) {
|
|
1048
900
|
for (i=0; i<pitchelem.startSlur.length; i++) {
|
|
1049
|
-
|
|
1050
|
-
|
|
901
|
+
slurid = pitchelem.startSlur[i].label;
|
|
902
|
+
slur = new TieElem({ anchor1: notehead, stemDir: this.stemdir, voiceNumber: voiceNumber, style: pitchelem.startSlur[i].style});
|
|
1051
903
|
if (hint) slur.setHint();
|
|
1052
904
|
this.slurs[slurid]=slur;
|
|
1053
905
|
voice.addOther(slur);
|
|
@@ -1056,9 +908,9 @@ var createNoteHead = function(abselem, c, pitchelem, dir, headx, extrax, flag, d
|
|
|
1056
908
|
};
|
|
1057
909
|
|
|
1058
910
|
AbstractEngraver.prototype.addMeasureNumber = function (number, abselem) {
|
|
1059
|
-
var measureNumDim = this.
|
|
911
|
+
var measureNumDim = this.getTextSize.calc(number, "measurefont", 'bar-number');
|
|
1060
912
|
var dx = measureNumDim.width > 18 && abselem.abcelem.type === "treble" ? -7 : 0;
|
|
1061
|
-
abselem.
|
|
913
|
+
abselem.addFixed(new RelativeElement(number, dx, measureNumDim.width, 11+measureNumDim.height / spacing.STEP, {type:"barNumber", dim: this.getTextSize.attr("measurefont", 'bar-number')}));
|
|
1062
914
|
};
|
|
1063
915
|
|
|
1064
916
|
AbstractEngraver.prototype.createBarLine = function (voice, elem, isFirstStaff) {
|
|
@@ -1140,7 +992,7 @@ AbstractEngraver.prototype.createBarLine = function (voice, elem, isFirstStaff)
|
|
|
1140
992
|
} // 2 is hardcoded
|
|
1141
993
|
|
|
1142
994
|
if (elem.startEnding && isFirstStaff) { // only put the first & second ending marks on the first staff
|
|
1143
|
-
var textWidth = this.
|
|
995
|
+
var textWidth = this.getTextSize.calc(elem.startEnding, "repeatfont", '').width;
|
|
1144
996
|
abselem.minspacing += textWidth + 10; // Give plenty of room for the ending number.
|
|
1145
997
|
this.partstartelem = new EndingElem(elem.startEnding, anchor, null);
|
|
1146
998
|
voice.addOther(this.partstartelem);
|
|
@@ -1153,7 +1005,4 @@ AbstractEngraver.prototype.createBarLine = function (voice, elem, isFirstStaff)
|
|
|
1153
1005
|
|
|
1154
1006
|
};
|
|
1155
1007
|
|
|
1156
|
-
|
|
1157
|
-
})();
|
|
1158
|
-
|
|
1159
1008
|
module.exports = AbstractEngraver;
|