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,27 +1,7 @@
|
|
|
1
1
|
// abc_triplet_element.js: Definition of the TripletElem class.
|
|
2
|
-
// Copyright (C) 2010-2020 Gregory Dyke (gregdyke at gmail dot com) and Paul Rosen
|
|
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
|
-
var
|
|
18
|
-
|
|
19
|
-
var TripletElem;
|
|
20
|
-
|
|
21
|
-
(function() {
|
|
22
|
-
"use strict";
|
|
23
|
-
|
|
24
|
-
TripletElem = function TripletElem(number, anchor1, options) {
|
|
3
|
+
var TripletElem = function TripletElem(number, anchor1, options) {
|
|
4
|
+
this.type = "TripletElem";
|
|
25
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)
|
|
26
6
|
this.number = number;
|
|
27
7
|
this.durationClass = ('d'+(Math.round(anchor1.parent.durationClass*1000)/1000)).replace(/\./, '-');
|
|
@@ -30,7 +10,7 @@ var TripletElem;
|
|
|
30
10
|
};
|
|
31
11
|
|
|
32
12
|
TripletElem.prototype.isClosed = function() {
|
|
33
|
-
return this.anchor2;
|
|
13
|
+
return !!this.anchor2;
|
|
34
14
|
};
|
|
35
15
|
|
|
36
16
|
TripletElem.prototype.middleNote = function(elem) {
|
|
@@ -39,108 +19,10 @@ var TripletElem;
|
|
|
39
19
|
|
|
40
20
|
TripletElem.prototype.setCloseAnchor = function(anchor2) {
|
|
41
21
|
this.anchor2 = anchor2;
|
|
42
|
-
// TODO-PER:
|
|
43
|
-
//
|
|
44
|
-
if (this.anchor1.parent.beam)
|
|
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')
|
|
45
25
|
this.endingHeightAbove = 4;
|
|
46
26
|
};
|
|
47
27
|
|
|
48
|
-
TripletElem.prototype.setUpperAndLowerElements = function(/*positionY*/) {
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
TripletElem.prototype.layout = function() {
|
|
52
|
-
// TODO end and beginning of line (PER: P.S. I'm not sure this can happen: I think the parser will always specify both the start and end points.)
|
|
53
|
-
if (this.anchor1 && this.anchor2) {
|
|
54
|
-
this.hasBeam = !!this.anchor1.parent.beam && this.anchor1.parent.beam === this.anchor2.parent.beam;
|
|
55
|
-
|
|
56
|
-
if (this.hasBeam) {
|
|
57
|
-
// If there is a beam then we don't need to draw anything except the text. The beam could either be above or below.
|
|
58
|
-
var beam = this.anchor1.parent.beam;
|
|
59
|
-
var left = beam.isAbove() ? this.anchor1.x + this.anchor1.w : this.anchor1.x;
|
|
60
|
-
this.yTextPos = beam.heightAtMidpoint(left, this.anchor2.x);
|
|
61
|
-
this.yTextPos += beam.isAbove() ? 3 : -2; // This creates some space between the beam and the number.
|
|
62
|
-
this.top = this.yTextPos + 1;
|
|
63
|
-
this.bottom = this.yTextPos - 2;
|
|
64
|
-
if (beam.isAbove())
|
|
65
|
-
this.endingHeightAbove = 4;
|
|
66
|
-
} else {
|
|
67
|
-
// If there isn't a beam, then we need to draw the bracket and the text. The bracket is always above.
|
|
68
|
-
// The bracket is never lower than the 'a' line, but is 4 pitches above the first and last notes. If there is
|
|
69
|
-
// a tall note in the middle, the bracket is horizontal and above the highest note.
|
|
70
|
-
this.startNote = Math.max(this.anchor1.parent.top, 9) + 4;
|
|
71
|
-
this.endNote = Math.max(this.anchor2.parent.top, 9) + 4;
|
|
72
|
-
// If it starts or ends on a rest, make the beam horizontal
|
|
73
|
-
if (this.anchor1.parent.type === "rest" && this.anchor2.parent.type !== "rest")
|
|
74
|
-
this.startNote = this.endNote;
|
|
75
|
-
else if (this.anchor2.parent.type === "rest" && this.anchor1.parent.type !== "rest")
|
|
76
|
-
this.endNote = this.startNote;
|
|
77
|
-
// See if the middle note is really high.
|
|
78
|
-
var max = 0;
|
|
79
|
-
for (var i = 0; i < this.middleElems.length; i++) {
|
|
80
|
-
max = Math.max(max, this.middleElems[i].top);
|
|
81
|
-
}
|
|
82
|
-
max += 4;
|
|
83
|
-
if (max > this.startNote || max > this.endNote) {
|
|
84
|
-
this.startNote = max;
|
|
85
|
-
this.endNote = max;
|
|
86
|
-
}
|
|
87
|
-
if (this.flatBeams) {
|
|
88
|
-
this.startNote = Math.max(this.startNote, this.endNote);
|
|
89
|
-
this.endNote = Math.max(this.startNote, this.endNote);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
this.yTextPos = this.startNote + (this.endNote - this.startNote) / 2;
|
|
93
|
-
this.top = this.yTextPos + 1;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
delete this.middleElems;
|
|
97
|
-
delete this.flatBeams;
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
TripletElem.prototype.draw = function(renderer) {
|
|
101
|
-
var xTextPos;
|
|
102
|
-
renderer.controller.currentAbsEl = { tuneNumber: renderer.controller.engraver.tuneNumber, elemset: [], abcelem: { el_type: "triplet", startChar: -1, endChar: -1 }};
|
|
103
|
-
renderer.createElemSet({ klass: renderer.addClasses('triplet '+this.durationClass)});
|
|
104
|
-
if (this.hasBeam) {
|
|
105
|
-
var left = this.anchor1.parent.beam.isAbove() ? this.anchor1.x + this.anchor1.w : this.anchor1.x;
|
|
106
|
-
xTextPos = this.anchor1.parent.beam.xAtMidpoint(left, this.anchor2.x);
|
|
107
|
-
} else {
|
|
108
|
-
xTextPos = this.anchor1.x + (this.anchor2.x + this.anchor2.w - this.anchor1.x) / 2;
|
|
109
|
-
drawBracket(renderer, this.anchor1.x, this.startNote, this.anchor2.x + this.anchor2.w, this.endNote);
|
|
110
|
-
}
|
|
111
|
-
renderer.renderText({x: xTextPos, y: renderer.calcY(this.yTextPos), text: "" + this.number, type: 'tripletfont', anchor: "middle", centerVertically: true, history: 'ignore', noClass: true});
|
|
112
|
-
var g = renderer.closeElemSet();
|
|
113
|
-
renderer.controller.currentAbsEl.elemset.push(g);
|
|
114
|
-
renderer.controller.recordHistory(g, true);
|
|
115
|
-
};
|
|
116
|
-
|
|
117
|
-
function drawLine(renderer, l, t, r, b) {
|
|
118
|
-
return sprintf("M %f %f L %f %f", l, t, r, b);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
function drawBracket(renderer, x1, y1, x2, y2) {
|
|
122
|
-
y1 = renderer.calcY(y1);
|
|
123
|
-
y2 = renderer.calcY(y2);
|
|
124
|
-
var bracketHeight = 5;
|
|
125
|
-
|
|
126
|
-
// Draw vertical lines at the beginning and end
|
|
127
|
-
var pathString = "";
|
|
128
|
-
pathString += drawLine(renderer, x1, y1, x1, y1 + bracketHeight);
|
|
129
|
-
pathString += drawLine(renderer, x2, y2, x2, y2 + bracketHeight);
|
|
130
|
-
|
|
131
|
-
// figure out midpoints to draw the broken line.
|
|
132
|
-
var midX = x1 + (x2-x1)/2;
|
|
133
|
-
//var midY = y1 + (y2-y1)/2;
|
|
134
|
-
var gapWidth = 8;
|
|
135
|
-
var slope = (y2 - y1) / (x2 - x1);
|
|
136
|
-
var leftEndX = midX - gapWidth;
|
|
137
|
-
var leftEndY = y1 + (leftEndX - x1) * slope;
|
|
138
|
-
pathString += drawLine(renderer, x1, y1, leftEndX, leftEndY);
|
|
139
|
-
var rightStartX = midX + gapWidth;
|
|
140
|
-
var rightStartY = y1 + (rightStartX - x1) * slope;
|
|
141
|
-
pathString += drawLine(renderer, rightStartX, rightStartY, x2, y2);
|
|
142
|
-
renderer.printPath({path: pathString, stroke: "#000000"});
|
|
143
|
-
}
|
|
144
|
-
})();
|
|
145
|
-
|
|
146
28
|
module.exports = TripletElem;
|
|
@@ -1,20 +1,4 @@
|
|
|
1
1
|
// abc_voice_element.js: Definition of the VoiceElement class.
|
|
2
|
-
// Copyright (C) 2010-2020 Gregory Dyke (gregdyke at gmail dot com) and Paul Rosen
|
|
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
|
-
|
|
17
|
-
var parseCommon = require('../parse/abc_common');
|
|
18
2
|
|
|
19
3
|
var VoiceElement = function VoiceElement(voicenumber, voicetotal) {
|
|
20
4
|
this.children = [];
|
|
@@ -42,8 +26,9 @@ var VoiceElement = function VoiceElement(voicenumber, voicetotal) {
|
|
|
42
26
|
};
|
|
43
27
|
};
|
|
44
28
|
|
|
45
|
-
VoiceElement.prototype.addChild = function (
|
|
46
|
-
|
|
29
|
+
VoiceElement.prototype.addChild = function (absElem) {
|
|
30
|
+
// This is always passed an AbsoluteElement
|
|
31
|
+
if (absElem.type === 'bar') {
|
|
47
32
|
var firstItem = true;
|
|
48
33
|
for (var i = 0; firstItem && i < this.children.length; i++) {
|
|
49
34
|
if (this.children[i].type.indexOf("staff-extra") < 0 && this.children[i].type !== "tempo")
|
|
@@ -54,8 +39,8 @@ VoiceElement.prototype.addChild = function (child) {
|
|
|
54
39
|
this.otherchildren.push("bar");
|
|
55
40
|
}
|
|
56
41
|
}
|
|
57
|
-
this.children[this.children.length] =
|
|
58
|
-
this.setRange(
|
|
42
|
+
this.children[this.children.length] = absElem;
|
|
43
|
+
this.setRange(absElem);
|
|
59
44
|
};
|
|
60
45
|
|
|
61
46
|
VoiceElement.prototype.setLimit = function(member, child) {
|
|
@@ -71,29 +56,6 @@ VoiceElement.prototype.setLimit = function(member, child) {
|
|
|
71
56
|
this.specialY[member] = Math.max(this.specialY[member], specialY[member]);
|
|
72
57
|
};
|
|
73
58
|
|
|
74
|
-
VoiceElement.prototype.moveDecorations = function(beam) {
|
|
75
|
-
var padding = 1.5; // This is the vertical padding between elements, in pitches.
|
|
76
|
-
for (var ch = 0; ch < beam.elems.length; ch++) {
|
|
77
|
-
var child = beam.elems[ch];
|
|
78
|
-
if (child.top) {
|
|
79
|
-
// We now know where the ornaments should have been placed, so move them if they would overlap.
|
|
80
|
-
var top = beam.yAtNote(child);
|
|
81
|
-
for (var i = 0; i < child.children.length; i++) {
|
|
82
|
-
var el = child.children[i];
|
|
83
|
-
if (el.klass === 'ornament') {
|
|
84
|
-
if (el.bottom - padding < top) {
|
|
85
|
-
var distance = top - el.bottom + padding; // Find the distance that it needs to move and add a little margin so the element doesn't touch the beam.
|
|
86
|
-
el.bottom += distance;
|
|
87
|
-
el.top += distance;
|
|
88
|
-
el.pitch += distance;
|
|
89
|
-
top = child.top = el.top;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
};
|
|
96
|
-
|
|
97
59
|
VoiceElement.prototype.adjustRange = function(child) {
|
|
98
60
|
if (child.bottom !== undefined)
|
|
99
61
|
this.bottom = Math.min(this.bottom, child.bottom);
|
|
@@ -116,19 +78,6 @@ VoiceElement.prototype.setRange = function(child) {
|
|
|
116
78
|
this.setLimit('dynamicHeightBelow', child);
|
|
117
79
|
};
|
|
118
80
|
|
|
119
|
-
VoiceElement.prototype.setUpperAndLowerElements = function(positionY) {
|
|
120
|
-
var i;
|
|
121
|
-
for (i = 0; i < this.children.length; i++) {
|
|
122
|
-
var abselem = this.children[i];
|
|
123
|
-
abselem.setUpperAndLowerElements(positionY);
|
|
124
|
-
}
|
|
125
|
-
for (i = 0; i < this.otherchildren.length; i++) {
|
|
126
|
-
var abselem = this.otherchildren[i];
|
|
127
|
-
if (typeof abselem !== 'string')
|
|
128
|
-
abselem.setUpperAndLowerElements(positionY);
|
|
129
|
-
}
|
|
130
|
-
};
|
|
131
|
-
|
|
132
81
|
VoiceElement.prototype.addOther = function (child) {
|
|
133
82
|
this.otherchildren.push(child);
|
|
134
83
|
this.setRange(child);
|
|
@@ -138,172 +87,8 @@ VoiceElement.prototype.addBeam = function (child) {
|
|
|
138
87
|
this.beams.push(child);
|
|
139
88
|
};
|
|
140
89
|
|
|
141
|
-
VoiceElement.prototype.
|
|
142
|
-
|
|
143
|
-
this.durationindex += this.children[this.i].duration;
|
|
144
|
-
if (this.children[this.i].type === 'bar') this.durationindex = Math.round(this.durationindex*64)/64; // everytime we meet a barline, do rounding to nearest 64th
|
|
145
|
-
this.i++;
|
|
146
|
-
}
|
|
147
|
-
};
|
|
148
|
-
|
|
149
|
-
VoiceElement.prototype.layoutEnded = function () {
|
|
150
|
-
return (this.i>=this.children.length);
|
|
151
|
-
};
|
|
152
|
-
|
|
153
|
-
VoiceElement.prototype.getDurationIndex = function () {
|
|
154
|
-
return this.durationindex - (this.children[this.i] && (this.children[this.i].duration>0)?0:0.0000005); // if the ith element doesn't have a duration (is not a note), its duration index is fractionally before. This enables CLEF KEYSIG TIMESIG PART, etc. to be laid out before we get to the first note of other voices
|
|
155
|
-
};
|
|
156
|
-
|
|
157
|
-
// number of spacing units expected for next positioning
|
|
158
|
-
VoiceElement.prototype.getSpacingUnits = function () {
|
|
159
|
-
return Math.sqrt(this.spacingduration*8);
|
|
160
|
-
// TODO-PER: On short lines, this would never trigger, so the spacing was wrong. I just changed this line empirically, though, so I don't know if there are other ramifications.
|
|
161
|
-
//return (this.minx<this.nextx) ? Math.sqrt(this.spacingduration*8) : 0; // we haven't used any spacing units if we end up using minx
|
|
162
|
-
};
|
|
163
|
-
|
|
164
|
-
//
|
|
165
|
-
VoiceElement.prototype.getNextX = function () {
|
|
166
|
-
return Math.max(this.minx, this.nextx);
|
|
167
|
-
};
|
|
168
|
-
|
|
169
|
-
VoiceElement.prototype.beginLayout = function (startx) {
|
|
170
|
-
this.i=0;
|
|
171
|
-
this.durationindex=0;
|
|
172
|
-
//this.ii=this.children.length;
|
|
173
|
-
this.startx=startx;
|
|
174
|
-
this.minx=startx; // furthest left to where negatively positioned elements are allowed to go
|
|
175
|
-
this.nextx=startx; // x position where the next element of this voice should be placed assuming no other voices and no fixed width constraints
|
|
176
|
-
this.spacingduration=0; // duration left to be laid out in current iteration (omitting additional spacing due to other aspects, such as bars, dots, sharps and flats)
|
|
177
|
-
};
|
|
178
|
-
|
|
179
|
-
// Try to layout the element at index this.i
|
|
180
|
-
// x - position to try to layout the element at
|
|
181
|
-
// spacing - base spacing
|
|
182
|
-
// can't call this function more than once per iteration
|
|
183
|
-
VoiceElement.prototype.layoutOneItem = function (x, spacing) {
|
|
184
|
-
var child = this.children[this.i];
|
|
185
|
-
if (!child) return 0;
|
|
186
|
-
var er = x - this.minx; // available extrawidth to the left
|
|
187
|
-
var extraWidth = child.getExtraWidth();
|
|
188
|
-
if (er<extraWidth) { // shift right by needed amount
|
|
189
|
-
// There's an exception if a bar element is after a Part element, there is no shift.
|
|
190
|
-
if (this.i === 0 || child.type !== 'bar' || (this.children[this.i-1].type !== 'part' && this.children[this.i-1].type !== 'tempo') )
|
|
191
|
-
x+=extraWidth-er;
|
|
192
|
-
}
|
|
193
|
-
child.setX(x);
|
|
194
|
-
|
|
195
|
-
this.spacingduration = child.duration;
|
|
196
|
-
//update minx
|
|
197
|
-
this.minx = x+child.getMinWidth(); // add necessary layout space
|
|
198
|
-
if (this.i!==this.children.length-1) this.minx+=child.minspacing; // add minimumspacing except on last elem
|
|
199
|
-
|
|
200
|
-
this.updateNextX(x, spacing);
|
|
201
|
-
|
|
202
|
-
// contribute to staff y position
|
|
203
|
-
//this.staff.top = Math.max(child.top,this.staff.top);
|
|
204
|
-
//this.staff.bottom = Math.min(child.bottom,this.staff.bottom);
|
|
205
|
-
|
|
206
|
-
return x; // where we end up having placed the child
|
|
207
|
-
};
|
|
208
|
-
|
|
209
|
-
// call when spacingduration has been updated
|
|
210
|
-
VoiceElement.prototype.updateNextX = function (x, spacing) {
|
|
211
|
-
this.nextx= x + (spacing*Math.sqrt(this.spacingduration*8));
|
|
212
|
-
};
|
|
213
|
-
|
|
214
|
-
VoiceElement.prototype.shiftRight = function (dx) {
|
|
215
|
-
var child = this.children[this.i];
|
|
216
|
-
if (!child) return;
|
|
217
|
-
child.setX(child.x+dx);
|
|
218
|
-
this.minx+=dx;
|
|
219
|
-
this.nextx+=dx;
|
|
220
|
-
};
|
|
221
|
-
|
|
222
|
-
function isNonSpacerRest(elem) {
|
|
223
|
-
if (elem.type !== 'rest')
|
|
224
|
-
return false;
|
|
225
|
-
if (elem.abcelem && elem.abcelem.rest && elem.abcelem.rest.type !== 'spacer')
|
|
226
|
-
return true;
|
|
227
|
-
return false;
|
|
228
|
-
}
|
|
229
|
-
VoiceElement.prototype.draw = function (renderer, bartop) {
|
|
230
|
-
var width = this.w-1;
|
|
231
|
-
renderer.staffbottom = this.staff.bottom;
|
|
232
|
-
//this.barbottom = renderer.calcY(2);
|
|
233
|
-
|
|
234
|
-
renderer.measureNumber = null;
|
|
235
|
-
renderer.noteNumber = null;
|
|
236
|
-
if (this.header) { // print voice name
|
|
237
|
-
var textpitch = 14 - (this.voicenumber+1)*(12/(this.voicetotal+1));
|
|
238
|
-
var self = this;
|
|
239
|
-
renderer.wrapInAbsElem({ el_type: "voice-name", startChar: -1, endChar: -1, text: this.header }, 'meta-bottom extra-text', function() {
|
|
240
|
-
var textEl = renderer.renderText({x: renderer.padding.left, y: renderer.calcY(textpitch), text: self.header, type: 'voicefont', klass: 'staff-extra voice-name', anchor: 'start'});
|
|
241
|
-
return textEl;
|
|
242
|
-
});
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
for (var i=0, ii=this.children.length; i<ii; i++) {
|
|
246
|
-
var child = this.children[i];
|
|
247
|
-
var justInitializedMeasureNumber = false;
|
|
248
|
-
if (child.type !== 'staff-extra' && renderer.measureNumber === null) {
|
|
249
|
-
renderer.measureNumber = 0;
|
|
250
|
-
renderer.noteNumber = 0;
|
|
251
|
-
justInitializedMeasureNumber = true;
|
|
252
|
-
}
|
|
253
|
-
renderer.controller.currentAbsEl = child;
|
|
254
|
-
child.draw(renderer, (this.barto || i===ii-1)?bartop:0);
|
|
255
|
-
if (child.type === 'note' || isNonSpacerRest(child))
|
|
256
|
-
renderer.noteNumber++;
|
|
257
|
-
if (child.type === 'bar' && !justInitializedMeasureNumber) {
|
|
258
|
-
renderer.measureNumber++;
|
|
259
|
-
renderer.noteNumber = 0;
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
renderer.measureNumber = 0;
|
|
264
|
-
renderer.noteNumber = 0;
|
|
265
|
-
parseCommon.each(this.beams, function(beam) {
|
|
266
|
-
if (beam === 'bar') {
|
|
267
|
-
renderer.measureNumber++;
|
|
268
|
-
renderer.noteNumber = 0;
|
|
269
|
-
} else
|
|
270
|
-
beam.draw(renderer); // beams must be drawn first for proper printing of triplets, slurs and ties.
|
|
271
|
-
});
|
|
272
|
-
|
|
273
|
-
renderer.measureNumber = 0;
|
|
274
|
-
renderer.noteNumber = 0;
|
|
275
|
-
var self = this;
|
|
276
|
-
parseCommon.each(this.otherchildren, function(child) {
|
|
277
|
-
if (child === 'bar') {
|
|
278
|
-
renderer.measureNumber++;
|
|
279
|
-
renderer.noteNumber = 0;
|
|
280
|
-
} else
|
|
281
|
-
child.draw(renderer,self.startx+10,width);
|
|
282
|
-
});
|
|
283
|
-
|
|
284
|
-
};
|
|
285
|
-
|
|
286
|
-
VoiceElement.prototype.layoutBeams = function() {
|
|
287
|
-
for (var i = 0; i < this.beams.length; i++) {
|
|
288
|
-
if (this.beams[i].layout) {
|
|
289
|
-
this.beams[i].layout();
|
|
290
|
-
this.moveDecorations(this.beams[i]);
|
|
291
|
-
// The above will change the top and bottom of the abselem children, so see if we need to expand our range.
|
|
292
|
-
for (var j = 0; j < this.beams[i].elems.length; j++) {
|
|
293
|
-
this.adjustRange(this.beams[i].elems[j]);
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
// Now we can layout the triplets
|
|
298
|
-
for (i = 0; i < this.otherchildren.length; i++) {
|
|
299
|
-
var child = this.otherchildren[i];
|
|
300
|
-
if (child.layout) {
|
|
301
|
-
child.layout();
|
|
302
|
-
this.adjustRange(child);
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
this.staff.top = Math.max(this.staff.top, this.top);
|
|
306
|
-
this.staff.bottom = Math.min(this.staff.bottom, this.bottom);
|
|
90
|
+
VoiceElement.prototype.setWidth = function (width) {
|
|
91
|
+
this.w = width;
|
|
307
92
|
};
|
|
308
93
|
|
|
309
94
|
module.exports = VoiceElement;
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
var RelativeElement = require('./abc_relative_element');
|
|
2
|
+
var spacing = require('./abc_spacing');
|
|
3
|
+
const formatJazzChord = require("./format-jazz-chord");
|
|
4
|
+
|
|
5
|
+
var addChord = function (getTextSize, abselem, elem, roomTaken, roomTakenRight, noteheadWidth, jazzchords) {
|
|
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
|
+
if (jazzchords)
|
|
23
|
+
chord = formatJazzChord(chord);
|
|
24
|
+
}
|
|
25
|
+
var attr = getTextSize.attr(font, klass);
|
|
26
|
+
var dim = getTextSize.calc(chord, font, klass);
|
|
27
|
+
var chordWidth = dim.width;
|
|
28
|
+
var chordHeight = dim.height / spacing.STEP;
|
|
29
|
+
switch (pos) {
|
|
30
|
+
case "left":
|
|
31
|
+
roomTaken += chordWidth + 7;
|
|
32
|
+
x = -roomTaken; // TODO-PER: This is just a guess from trial and error
|
|
33
|
+
y = elem.averagepitch;
|
|
34
|
+
abselem.addExtra(new RelativeElement(chord, x, chordWidth + 4, y, {
|
|
35
|
+
type: "text",
|
|
36
|
+
height: chordHeight,
|
|
37
|
+
dim: attr,
|
|
38
|
+
position: "left"
|
|
39
|
+
}));
|
|
40
|
+
break;
|
|
41
|
+
case "right":
|
|
42
|
+
roomTakenRight += 4;
|
|
43
|
+
x = roomTakenRight;// TODO-PER: This is just a guess from trial and error
|
|
44
|
+
y = elem.averagepitch;
|
|
45
|
+
abselem.addRight(new RelativeElement(chord, x, chordWidth + 4, y, {
|
|
46
|
+
type: "text",
|
|
47
|
+
height: chordHeight,
|
|
48
|
+
dim: attr,
|
|
49
|
+
position: "right"
|
|
50
|
+
}));
|
|
51
|
+
break;
|
|
52
|
+
case "below":
|
|
53
|
+
// 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.
|
|
54
|
+
abselem.addRight(new RelativeElement(chord, 0, 0, undefined, {
|
|
55
|
+
type: "text",
|
|
56
|
+
position: "below",
|
|
57
|
+
height: chordHeight,
|
|
58
|
+
dim: attr,
|
|
59
|
+
realWidth: chordWidth
|
|
60
|
+
}));
|
|
61
|
+
break;
|
|
62
|
+
case "above":
|
|
63
|
+
// 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.
|
|
64
|
+
abselem.addRight(new RelativeElement(chord, 0, 0, undefined, {
|
|
65
|
+
type: "text",
|
|
66
|
+
position: "above",
|
|
67
|
+
height: chordHeight,
|
|
68
|
+
dim: attr,
|
|
69
|
+
realWidth: chordWidth
|
|
70
|
+
}));
|
|
71
|
+
break;
|
|
72
|
+
default:
|
|
73
|
+
if (rel_position) {
|
|
74
|
+
var relPositionY = rel_position.y + 3 * spacing.STEP; // TODO-PER: this is a fudge factor to make it line up with abcm2ps
|
|
75
|
+
abselem.addRight(new RelativeElement(chord, x + rel_position.x, 0, elem.minpitch + relPositionY / spacing.STEP, {
|
|
76
|
+
position: "relative",
|
|
77
|
+
type: "text",
|
|
78
|
+
height: chordHeight,
|
|
79
|
+
dim: attr
|
|
80
|
+
}));
|
|
81
|
+
} else {
|
|
82
|
+
// 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.
|
|
83
|
+
var pos2 = 'above';
|
|
84
|
+
if (elem.positioning && elem.positioning.chordPosition)
|
|
85
|
+
pos2 = elem.positioning.chordPosition;
|
|
86
|
+
|
|
87
|
+
if (pos2 !== 'hidden') {
|
|
88
|
+
abselem.addCentered(new RelativeElement(chord, noteheadWidth/2, chordWidth, undefined, {
|
|
89
|
+
type: "chord",
|
|
90
|
+
position: pos2,
|
|
91
|
+
height: chordHeight,
|
|
92
|
+
dim: attr,
|
|
93
|
+
realWidth: chordWidth
|
|
94
|
+
}));
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return {roomTaken: roomTaken, roomTakenRight: roomTakenRight};
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
module.exports = addChord;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
function addTextIf(rows, params, getTextSize) {
|
|
2
|
+
if (!params.text)
|
|
3
|
+
return;
|
|
4
|
+
if (!params.marginLeft) params.marginLeft = 0;
|
|
5
|
+
if (!params.klass) params.klass = '';
|
|
6
|
+
if (!params.anchor) params.anchor = 'start';
|
|
7
|
+
if (!params.info) params.info = { startChar: -2, endChar: -2}
|
|
8
|
+
|
|
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};
|
|
12
|
+
if (params.absElemType)
|
|
13
|
+
attr.absElemType = params.absElemType;
|
|
14
|
+
if (!params.inGroup)
|
|
15
|
+
attr.klass = params.klass;
|
|
16
|
+
if (params.name)
|
|
17
|
+
attr.name = params.name;
|
|
18
|
+
|
|
19
|
+
rows.push(attr);
|
|
20
|
+
// If there are blank lines they won't be counted by getTextSize, so just get the height of one line and multiply
|
|
21
|
+
var size = getTextSize.calc("A", params.font, params.klass);
|
|
22
|
+
var numLines = params.text.split("\n").length;
|
|
23
|
+
if (params.text[params.text.length-1] === '\n')
|
|
24
|
+
numLines--; // If there is a new line at the end of the string, then an extra line will be counted.
|
|
25
|
+
if (!params.noMove) {
|
|
26
|
+
var h = (size.height * 1.1) * numLines;
|
|
27
|
+
rows.push({move: Math.round(h)});
|
|
28
|
+
if (params.marginBottom)
|
|
29
|
+
rows.push({move: params.marginBottom});
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
module.exports = addTextIf;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
const addTextIf = require("./add-text-if");
|
|
2
|
+
|
|
3
|
+
function BottomText(metaText, width, isPrint, paddingLeft, spacing, getTextSize) {
|
|
4
|
+
this.rows = [];
|
|
5
|
+
if (metaText.unalignedWords && metaText.unalignedWords.length > 0)
|
|
6
|
+
this.unalignedWords(metaText.unalignedWords, paddingLeft, spacing, getTextSize);
|
|
7
|
+
this.extraText(metaText, paddingLeft, spacing, getTextSize);
|
|
8
|
+
if (metaText.footer && isPrint)
|
|
9
|
+
this.footer(metaText.footer, width, paddingLeft, getTextSize);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
BottomText.prototype.unalignedWords = function (unalignedWords, paddingLeft, spacing, getTextSize) {
|
|
13
|
+
var indent = 50;
|
|
14
|
+
var klass = 'meta-bottom unaligned-words';
|
|
15
|
+
var defFont = 'wordsfont';
|
|
16
|
+
this.rows.push({startGroup: "unalignedWords", klass: 'abcjs-meta-bottom abcjs-unaligned-words', name: "words"});
|
|
17
|
+
var space = getTextSize.calc("i", defFont, klass);
|
|
18
|
+
|
|
19
|
+
this.rows.push({move: spacing.words});
|
|
20
|
+
|
|
21
|
+
for (var j = 0; j < unalignedWords.length; j++) {
|
|
22
|
+
if (unalignedWords[j] === '')
|
|
23
|
+
this.rows.push({move: space.height});
|
|
24
|
+
else if (typeof unalignedWords[j] === 'string') {
|
|
25
|
+
addTextIf(this.rows, { marginLeft: paddingLeft + indent, text: unalignedWords[j], font: defFont, klass: klass, inGroup: true, name: "words"}, getTextSize);
|
|
26
|
+
} else {
|
|
27
|
+
var largestY = 0;
|
|
28
|
+
var offsetX = 0;
|
|
29
|
+
for (var k = 0; k < unalignedWords[j].length; k++) {
|
|
30
|
+
var thisWord = unalignedWords[j][k];
|
|
31
|
+
var font = (thisWord.font) ? thisWord.font : defFont;
|
|
32
|
+
this.rows.push({
|
|
33
|
+
left: paddingLeft + indent + offsetX,
|
|
34
|
+
text: thisWord.text,
|
|
35
|
+
font: font,
|
|
36
|
+
anchor: 'start'
|
|
37
|
+
});
|
|
38
|
+
var size = getTextSize.calc(thisWord.text, defFont, klass);
|
|
39
|
+
largestY = Math.max(largestY, size.height);
|
|
40
|
+
offsetX += size.width;
|
|
41
|
+
// If the phrase ends in a space, then that is not counted in the width, so we need to add that in ourselves.
|
|
42
|
+
if (thisWord.text[thisWord.text.length - 1] === ' ') {
|
|
43
|
+
offsetX += space.width;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
this.rows.push({move: largestY});
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
this.rows.push({move: space.height * 2});
|
|
50
|
+
this.rows.push({endGroup: "unalignedWords", absElemType: "unalignedWords", startChar: -1, endChar: -1, name: "unalignedWords"});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
BottomText.prototype.extraText = function (metaText, marginLeft, spacing, getTextSize) {
|
|
54
|
+
var extraText = "";
|
|
55
|
+
if (metaText.book) extraText += "Book: " + metaText.book + "\n";
|
|
56
|
+
if (metaText.source) extraText += "Source: " + metaText.source + "\n";
|
|
57
|
+
if (metaText.discography) extraText += "Discography: " + metaText.discography + "\n";
|
|
58
|
+
if (metaText.notes) extraText += "Notes: " + metaText.notes + "\n";
|
|
59
|
+
if (metaText.transcription) extraText += "Transcription: " + metaText.transcription + "\n";
|
|
60
|
+
if (metaText.history) extraText += "History: " + metaText.history + "\n";
|
|
61
|
+
if (metaText['abc-copyright']) extraText += "Copyright: " + metaText['abc-copyright'] + "\n";
|
|
62
|
+
if (metaText['abc-creator']) extraText += "Creator: " + metaText['abc-creator'] + "\n";
|
|
63
|
+
if (metaText['abc-edited-by']) extraText += "Edited By: " + metaText['abc-edited-by'] + "\n";
|
|
64
|
+
if (extraText.length > 0) {
|
|
65
|
+
addTextIf(this.rows, { marginLeft: marginLeft, text: extraText, font: 'historyfont', klass: 'meta-bottom extra-text', marginTop: spacing.info, absElemType: "extraText", name: "description"}, getTextSize);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
BottomText.prototype.footer = function (footer, width, paddingLeft, getTextSize) {
|
|
70
|
+
var klass = 'header meta-bottom';
|
|
71
|
+
var font = "footerfont";
|
|
72
|
+
this.rows.push({startGroup: "footer", klass: klass});
|
|
73
|
+
// Note: whether there is a footer or not doesn't change any other positioning, so this doesn't change the Y-coordinate.
|
|
74
|
+
addTextIf(this.rows, { marginLeft: paddingLeft, text: footer.left, font: font, klass: klass, name: "footer"}, getTextSize);
|
|
75
|
+
addTextIf(this.rows, { marginLeft: paddingLeft + width / 2, text: footer.center, font: font, klass: klass, anchor: 'middle', name: "footer"} , getTextSize);
|
|
76
|
+
addTextIf(this.rows, { marginLeft: paddingLeft + width, text: footer.right, font: font, klass: klass, anchor: 'end', name: "footer"}, getTextSize);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
module.exports = BottomText;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
var calcHeight = function (staffGroup) {
|
|
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
|
+
// TODO-PER: also add the space between staves. (That's systemStaffSeparation, which is the minimum distance between the staff LINES.)
|
|
4
|
+
var height = 0;
|
|
5
|
+
for (var i=0;i<staffGroup.voices.length;i++) {
|
|
6
|
+
var staff = staffGroup.voices[i].staff;
|
|
7
|
+
if (!staffGroup.voices[i].duplicate) {
|
|
8
|
+
height += staff.top;
|
|
9
|
+
//if (staff.bottom < 0)
|
|
10
|
+
height += -staff.bottom;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
return height;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
module.exports = calcHeight;
|
|
17
|
+
|