abcjs-rails 1.11 → 2.0
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.
- checksums.yaml +4 -4
- data/app/assets/javascripts/abcjs/api/abc_animation.js +41 -1
- data/app/assets/javascripts/abcjs/api/abc_tunebook.js +5 -0
- data/app/assets/javascripts/abcjs/data/abc_tune.js +4 -3
- data/app/assets/javascripts/abcjs/edit/abc_editor.js +10 -0
- data/app/assets/javascripts/abcjs/parse/abc_parse.js +120 -19
- data/app/assets/javascripts/abcjs/parse/abc_parse_directive.js +456 -115
- data/app/assets/javascripts/abcjs/raphael.js +2 -2
- data/app/assets/javascripts/abcjs/write/abc_absolute_element.js +111 -4
- data/app/assets/javascripts/abcjs/write/abc_abstract_engraver.js +899 -0
- data/app/assets/javascripts/abcjs/write/abc_beam_element.js +263 -37
- data/app/assets/javascripts/abcjs/write/abc_create_clef.js +76 -0
- data/app/assets/javascripts/abcjs/write/abc_create_key_signature.js +41 -0
- data/app/assets/javascripts/abcjs/write/abc_create_time_signature.js +51 -0
- data/app/assets/javascripts/abcjs/write/{abc_cresendo_element.js → abc_crescendo_element.js} +32 -1
- data/app/assets/javascripts/abcjs/write/abc_decoration.js +321 -0
- data/app/assets/javascripts/abcjs/write/abc_dynamic_decoration.js +22 -1
- data/app/assets/javascripts/abcjs/write/abc_ending_element.js +31 -1
- data/app/assets/javascripts/abcjs/write/abc_engraver_controller.js +359 -0
- data/app/assets/javascripts/abcjs/write/abc_glyphs.js +119 -9
- data/app/assets/javascripts/abcjs/write/abc_layout.js +2 -2
- data/app/assets/javascripts/abcjs/write/abc_relative_element.js +106 -8
- data/app/assets/javascripts/abcjs/write/abc_renderer.js +754 -0
- data/app/assets/javascripts/abcjs/write/abc_staff_group_element.js +249 -9
- data/app/assets/javascripts/abcjs/write/abc_tempo_element.js +104 -0
- data/app/assets/javascripts/abcjs/write/abc_tie_element.js +69 -22
- data/app/assets/javascripts/abcjs/write/abc_triplet_element.js +77 -10
- data/app/assets/javascripts/abcjs/write/abc_voice_element.js +100 -8
- data/app/assets/javascripts/abcjs/write/abc_write.js +64 -68
- data/lib/abcjs-rails/version.rb +1 -1
- metadata +12 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fa42e9ce9d4ae382cdf01127928c52e1baaa8741
|
4
|
+
data.tar.gz: 146f81c567ee9aee005ceb00f5d29800a40fcb19
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 97b5c92b0832f98646268224d823fe88f7021dfbd90a1b8a5af0e2356ce39c63e58f2abfff49c363e6ef1cccdd44b555e9251e0e5263b603464f175434d89888
|
7
|
+
data.tar.gz: 4c060e9e01c5490e2b481636873881a0189c7748db272375e80e8c48e5066dc122223613b4ed39c4247c9572a91864f32cdc617992a0418a06dc1029485d4575
|
@@ -20,6 +20,10 @@ if (!window.ABCJS)
|
|
20
20
|
window.ABCJS = {};
|
21
21
|
|
22
22
|
(function() {
|
23
|
+
<<<<<<< HEAD
|
24
|
+
"use strict";
|
25
|
+
=======
|
26
|
+
>>>>>>> origin/master
|
23
27
|
|
24
28
|
function hasClass(element, cls) {
|
25
29
|
var elClass = element.getAttribute("class");
|
@@ -79,6 +83,10 @@ if (!window.ABCJS)
|
|
79
83
|
if (options.showCursor) {
|
80
84
|
cursor = $('<div class="cursor" style="position: absolute;"></div>');
|
81
85
|
$(paper).append(cursor);
|
86
|
+
<<<<<<< HEAD
|
87
|
+
$(paper).css({ position: "relative" });
|
88
|
+
=======
|
89
|
+
>>>>>>> origin/master
|
82
90
|
}
|
83
91
|
|
84
92
|
stopNextTime = false;
|
@@ -107,7 +115,14 @@ if (!window.ABCJS)
|
|
107
115
|
arr.push(hash[k]);
|
108
116
|
}
|
109
117
|
arr = arr.sort(function(a,b) {
|
110
|
-
|
118
|
+
var diff = a.time - b.time;
|
119
|
+
// if the events have the same time, make sure a bar comes before a note
|
120
|
+
if (diff !== 0) {
|
121
|
+
return diff;
|
122
|
+
}
|
123
|
+
else {
|
124
|
+
return a.type === "bar" ? -1 : 1;
|
125
|
+
}
|
111
126
|
});
|
112
127
|
return arr;
|
113
128
|
}
|
@@ -121,8 +136,18 @@ if (!window.ABCJS)
|
|
121
136
|
for (var line=0;line<engraver.staffgroups.length; line++) {
|
122
137
|
var group = engraver.staffgroups[line];
|
123
138
|
var voices = group.voices;
|
139
|
+
<<<<<<< HEAD
|
140
|
+
var firstStaff = group.staffs[0];
|
141
|
+
var middleC = firstStaff.absoluteY;
|
142
|
+
var top = middleC - firstStaff.top*ABCJS.write.spacing.STEP;
|
143
|
+
var lastStaff = group.staffs[group.staffs.length-1];
|
144
|
+
middleC = lastStaff.absoluteY;
|
145
|
+
var bottom = middleC - lastStaff.bottom*ABCJS.write.spacing.STEP;
|
146
|
+
var height = bottom - top;
|
147
|
+
=======
|
124
148
|
var top = group.y;
|
125
149
|
var height = group.height;
|
150
|
+
>>>>>>> origin/master
|
126
151
|
var maxVoiceTime = 0;
|
127
152
|
// Put in the notes for all voices, then sort them, then remove duplicates
|
128
153
|
for (var v = 0; v < voices.length; v++) {
|
@@ -140,7 +165,16 @@ if (!window.ABCJS)
|
|
140
165
|
// If the note is tied on both sides it can just be ignored.
|
141
166
|
} else {
|
142
167
|
// the last note wasn't tied.
|
168
|
+
<<<<<<< HEAD
|
169
|
+
if (!eventHash["event"+voiceTime])
|
170
|
+
eventHash["event"+voiceTime] = { type: "event", time: voiceTime, top: top, height: height, left: element.x, width: element.w };
|
171
|
+
else {
|
172
|
+
// If there is more than one voice then two notes can fall at the same time. Usually they would be lined up in the same place, but if it is a whole rest, then it is placed funny. In any case, the left most element wins.
|
173
|
+
eventHash["event"+voiceTime].left = Math.min(eventHash["event"+voiceTime].left, element.x);
|
174
|
+
}
|
175
|
+
=======
|
143
176
|
eventHash["event"+voiceTime] = { type: "event", time: voiceTime, top: top, height: height, left: element.x, width: element.w };
|
177
|
+
>>>>>>> origin/master
|
144
178
|
if (isTiedToNext)
|
145
179
|
isTiedState = true;
|
146
180
|
}
|
@@ -184,7 +218,13 @@ if (!window.ABCJS)
|
|
184
218
|
if (currentNote.type === "bar") {
|
185
219
|
if (options.hideFinishedMeasures)
|
186
220
|
processMeasureHider(currentNote.lineNum, currentNote.measureNum);
|
221
|
+
<<<<<<< HEAD
|
222
|
+
if (timingEvents.length > 0)
|
223
|
+
return timingEvents[0].time / beatLength;
|
224
|
+
return 0;
|
225
|
+
=======
|
187
226
|
return processShowCursor();
|
227
|
+
>>>>>>> origin/master
|
188
228
|
}
|
189
229
|
if (options.showCursor)
|
190
230
|
cursor.css({ left: currentNote.left + "px", top: currentNote.top + "px", width: currentNote.width + "px", height: currentNote.height + "px" });
|
@@ -156,8 +156,13 @@ if (!window.ABCJS)
|
|
156
156
|
/* jshint -W064 */ var paper = Raphael(div, width, 400); /* jshint +W064 */
|
157
157
|
if (engraverParams === undefined)
|
158
158
|
engraverParams = {};
|
159
|
+
<<<<<<< HEAD
|
160
|
+
var engraver_controller = new ABCJS.write.EngraverController(paper, engraverParams);
|
161
|
+
engraver_controller.engraveABC(tune);
|
162
|
+
=======
|
159
163
|
var engraver_controller = new ABCJS.write.Printer(paper, engraverParams);
|
160
164
|
engraver_controller.printABC(tune);
|
165
|
+
>>>>>>> origin/master
|
161
166
|
tune.engraver = engraver_controller;
|
162
167
|
}
|
163
168
|
|
@@ -101,7 +101,7 @@ window.ABCJS.data.Tune = function() {
|
|
101
101
|
this.lineNum = 0;
|
102
102
|
};
|
103
103
|
|
104
|
-
this.cleanUp = function(defWidth, defLength, barsperstaff, staffnonote) {
|
104
|
+
this.cleanUp = function(defWidth, defLength, barsperstaff, staffnonote, currSlur) {
|
105
105
|
this.closeLine(); // Close the last line.
|
106
106
|
|
107
107
|
// Remove any blank lines
|
@@ -211,7 +211,6 @@ window.ABCJS.data.Tune = function() {
|
|
211
211
|
}
|
212
212
|
|
213
213
|
function cleanUpSlursInLine(line) {
|
214
|
-
var currSlur = [];
|
215
214
|
var x;
|
216
215
|
// var lyr = null; // TODO-PER: debugging.
|
217
216
|
|
@@ -225,7 +224,7 @@ window.ABCJS.data.Tune = function() {
|
|
225
224
|
}
|
226
225
|
}
|
227
226
|
if (currSlur[chordPos] === undefined) {
|
228
|
-
var offNum = chordPos*100;
|
227
|
+
var offNum = chordPos*100+1;
|
229
228
|
window.ABCJS.parse.each(obj.endSlur, function(x) { if (offNum === x) --offNum; });
|
230
229
|
currSlur[chordPos] = [offNum];
|
231
230
|
}
|
@@ -399,6 +398,8 @@ window.ABCJS.data.Tune = function() {
|
|
399
398
|
delete this.potentialStartBeam;
|
400
399
|
delete this.potentialEndBeam;
|
401
400
|
delete this.vskipPending;
|
401
|
+
|
402
|
+
return currSlur;
|
402
403
|
};
|
403
404
|
|
404
405
|
this.reset();
|
@@ -241,8 +241,13 @@ window.ABCJS.Editor.prototype.renderTune = function(abc, params, div) {
|
|
241
241
|
abcParser.parse(tunebook.tunes[0].abc, params); //TODO handle multiple tunes
|
242
242
|
var tune = abcParser.getTune();
|
243
243
|
var paper = Raphael(div, 800, 400);
|
244
|
+
<<<<<<< HEAD
|
245
|
+
var engraver_controller = new ABCJS.write.EngraverController(paper, this.engraverparams);
|
246
|
+
engraver_controller.engraveABC(tune);
|
247
|
+
=======
|
244
248
|
var engraver_controller = new ABCJS.write.Printer(paper, this.engraverparams);
|
245
249
|
engraver_controller.printABC(tune);
|
250
|
+
>>>>>>> origin/master
|
246
251
|
};
|
247
252
|
|
248
253
|
window.ABCJS.Editor.prototype.modelChanged = function() {
|
@@ -259,8 +264,13 @@ window.ABCJS.Editor.prototype.modelChanged = function() {
|
|
259
264
|
this.timerId = null;
|
260
265
|
this.div.innerHTML = "";
|
261
266
|
var paper = Raphael(this.div, 800, 400);
|
267
|
+
<<<<<<< HEAD
|
268
|
+
this.engraver_controller = new ABCJS.write.EngraverController(paper, this.engraverparams);
|
269
|
+
this.engraver_controller.engraveABC(this.tunes);
|
270
|
+
=======
|
262
271
|
this.engraver_controller = new ABCJS.write.Printer(paper, this.engraverparams);
|
263
272
|
this.engraver_controller.printABC(this.tunes);
|
273
|
+
>>>>>>> origin/master
|
264
274
|
this.tunes[0].engraver = this.engraver_controller; // TODO-PER: We actually want an output object for each tune, not the entire controller. When refactoring, don't save data in the controller.
|
265
275
|
if (ABCJS.midi.MidiWriter && this.mididiv) {
|
266
276
|
if (this.mididiv !== this.div)
|
@@ -23,6 +23,7 @@ if (!window.ABCJS.parse)
|
|
23
23
|
window.ABCJS.parse = {};
|
24
24
|
|
25
25
|
window.ABCJS.parse.Parse = function() {
|
26
|
+
"use strict";
|
26
27
|
var tune = new window.ABCJS.data.Tune();
|
27
28
|
var tokenizer = new window.ABCJS.parse.tokenizer();
|
28
29
|
|
@@ -30,6 +31,16 @@ window.ABCJS.parse.Parse = function() {
|
|
30
31
|
return tune;
|
31
32
|
};
|
32
33
|
|
34
|
+
function addPositioning(el, type, value) {
|
35
|
+
if (!el.positioning) el.positioning = {};
|
36
|
+
el.positioning[type] = value;
|
37
|
+
}
|
38
|
+
|
39
|
+
function addFont(el, type, value) {
|
40
|
+
if (!el.fonts) el.fonts = {};
|
41
|
+
el.fonts[type] = value;
|
42
|
+
}
|
43
|
+
|
33
44
|
var multilineVars = {
|
34
45
|
reset: function() {
|
35
46
|
for (var property in this) {
|
@@ -62,6 +73,39 @@ window.ABCJS.parse.Parse = function() {
|
|
62
73
|
this.inEnding = false;
|
63
74
|
this.inTie = false;
|
64
75
|
this.inTieChord = {};
|
76
|
+
this.vocalPosition = "auto";
|
77
|
+
this.dynamicPosition = "auto";
|
78
|
+
this.chordPosition = "auto";
|
79
|
+
this.ornamentPosition = "auto";
|
80
|
+
this.volumePosition = "auto";
|
81
|
+
this.openSlurs = [];
|
82
|
+
},
|
83
|
+
differentFont: function(type, defaultFonts) {
|
84
|
+
if (this[type].decoration !== defaultFonts[type].decoration) return true;
|
85
|
+
if (this[type].face !== defaultFonts[type].face) return true;
|
86
|
+
if (this[type].size !== defaultFonts[type].size) return true;
|
87
|
+
if (this[type].style !== defaultFonts[type].style) return true;
|
88
|
+
if (this[type].weight !== defaultFonts[type].weight) return true;
|
89
|
+
return false;
|
90
|
+
},
|
91
|
+
addFormattingOptions: function(el, defaultFonts, elType) {
|
92
|
+
if (elType === 'note') {
|
93
|
+
if (this.vocalPosition !== 'auto') addPositioning(el, 'vocalPosition', this.vocalPosition);
|
94
|
+
if (this.dynamicPosition !== 'auto') addPositioning(el, 'dynamicPosition', this.dynamicPosition);
|
95
|
+
if (this.chordPosition !== 'auto') addPositioning(el, 'chordPosition', this.chordPosition);
|
96
|
+
if (this.ornamentPosition !== 'auto') addPositioning(el, 'ornamentPosition', this.ornamentPosition);
|
97
|
+
if (this.volumePosition !== 'auto') addPositioning(el, 'volumePosition', this.volumePosition);
|
98
|
+
if (this.differentFont("annotationfont", defaultFonts)) addFont(el, 'annotationfont', this.annotationfont);
|
99
|
+
if (this.differentFont("gchordfont", defaultFonts)) addFont(el, 'gchordfont', this.gchordfont);
|
100
|
+
if (this.differentFont("vocalfont", defaultFonts)) addFont(el, 'vocalfont', this.vocalfont);
|
101
|
+
} else if (elType === 'bar') {
|
102
|
+
if (this.dynamicPosition !== 'auto') addPositioning(el, 'dynamicPosition', this.dynamicPosition);
|
103
|
+
if (this.chordPosition !== 'auto') addPositioning(el, 'chordPosition', this.chordPosition);
|
104
|
+
if (this.ornamentPosition !== 'auto') addPositioning(el, 'ornamentPosition', this.ornamentPosition);
|
105
|
+
if (this.volumePosition !== 'auto') addPositioning(el, 'volumePosition', this.volumePosition);
|
106
|
+
if (this.differentFont("measurefont", defaultFonts)) addFont(el, 'measurefont', this.measurefont);
|
107
|
+
if (this.differentFont("repeatfont", defaultFonts)) addFont(el, 'repeatfont', this.repeatfont);
|
108
|
+
}
|
65
109
|
}
|
66
110
|
};
|
67
111
|
|
@@ -79,6 +123,7 @@ window.ABCJS.parse.Parse = function() {
|
|
79
123
|
};
|
80
124
|
|
81
125
|
var warn = function(str, line, col_num) {
|
126
|
+
if (!line) line = " ";
|
82
127
|
var bad_char = line.charAt(col_num);
|
83
128
|
if (bad_char === ' ')
|
84
129
|
bad_char = "SPACE";
|
@@ -146,14 +191,20 @@ window.ABCJS.parse.Parse = function() {
|
|
146
191
|
var legalAccents = [ "trill", "lowermordent", "uppermordent", "mordent", "pralltriller", "accent",
|
147
192
|
"fermata", "invertedfermata", "tenuto", "0", "1", "2", "3", "4", "5", "+", "wedge",
|
148
193
|
"open", "thumb", "snap", "turn", "roll", "breath", "shortphrase", "mediumphrase", "longphrase",
|
149
|
-
"segno", "coda", "D.S.", "D.C.", "fine",
|
150
|
-
"
|
194
|
+
"segno", "coda", "D.S.", "D.C.", "fine",
|
195
|
+
"slide", "^", "marcato",
|
151
196
|
"upbow", "downbow", "/", "//", "///", "////", "trem1", "trem2", "trem3", "trem4",
|
152
197
|
"turnx", "invertedturn", "invertedturnx", "trill(", "trill)", "arpeggio", "xstem", "mark", "umarcato",
|
153
198
|
"style=normal", "style=harmonic", "style=rhythm", "style=x"
|
154
199
|
];
|
155
|
-
var
|
156
|
-
|
200
|
+
var volumeDecorations = [ "p", "pp", "f", "ff", "mf", "mp", "ppp", "pppp", "fff", "ffff", "sfz" ];
|
201
|
+
var dynamicDecorations = ["crescendo(", "crescendo)", "diminuendo(", "diminuendo)"];
|
202
|
+
|
203
|
+
var accentPseudonyms = [ ["<", "accent"], [">", "accent"], ["tr", "trill"],
|
204
|
+
["plus", "+"], [ "emphasis", "accent"],
|
205
|
+
[ "^", "umarcato" ], [ "marcato", "umarcato" ] ];
|
206
|
+
var accentDynamicPseudonyms = [ ["<(", "crescendo("], ["<)", "crescendo)"],
|
207
|
+
[">(", "diminuendo("], [">)", "diminuendo)"] ];
|
157
208
|
var letter_to_accent = function(line, i)
|
158
209
|
{
|
159
210
|
var macro = multilineVars.macros[line.charAt(i)];
|
@@ -167,7 +218,19 @@ window.ABCJS.parse.Parse = function() {
|
|
167
218
|
return (macro === acc);
|
168
219
|
}))
|
169
220
|
return [ 1, macro ];
|
170
|
-
else {
|
221
|
+
else if (window.ABCJS.parse.detect(volumeDecorations, function(acc) {
|
222
|
+
return (macro === acc);
|
223
|
+
})) {
|
224
|
+
if (multilineVars.volumePosition === 'hidden')
|
225
|
+
macro = "";
|
226
|
+
return [1, macro];
|
227
|
+
} else if (window.ABCJS.parse.detect(dynamicDecorations, function(acc) {
|
228
|
+
if (multilineVars.dynamicPosition === 'hidden')
|
229
|
+
macro = "";
|
230
|
+
return (macro === acc);
|
231
|
+
})) {
|
232
|
+
return [1, macro];
|
233
|
+
} else {
|
171
234
|
if (!window.ABCJS.parse.detect(multilineVars.ignoredDecorations, function(dec) {
|
172
235
|
return (macro === dec);
|
173
236
|
}))
|
@@ -191,8 +254,22 @@ window.ABCJS.parse.Parse = function() {
|
|
191
254
|
return (ret[1] === acc);
|
192
255
|
}))
|
193
256
|
return ret;
|
257
|
+
if (window.ABCJS.parse.detect(volumeDecorations, function(acc) {
|
258
|
+
return (ret[1] === acc);
|
259
|
+
})) {
|
260
|
+
if (multilineVars.volumePosition === 'hidden' )
|
261
|
+
ret[1] = '';
|
262
|
+
return ret;
|
263
|
+
}
|
264
|
+
if (window.ABCJS.parse.detect(dynamicDecorations, function(acc) {
|
265
|
+
return (ret[1] === acc);
|
266
|
+
})) {
|
267
|
+
if (multilineVars.dynamicPosition === 'hidden' )
|
268
|
+
ret[1] = '';
|
269
|
+
return ret;
|
270
|
+
}
|
194
271
|
|
195
|
-
if (window.ABCJS.parse.detect(
|
272
|
+
if (window.ABCJS.parse.detect(accentPseudonyms, function(acc) {
|
196
273
|
if (ret[1] === acc[0]) {
|
197
274
|
ret[1] = acc[1];
|
198
275
|
return true;
|
@@ -201,6 +278,17 @@ window.ABCJS.parse.Parse = function() {
|
|
201
278
|
}))
|
202
279
|
return ret;
|
203
280
|
|
281
|
+
if (window.ABCJS.parse.detect(accentDynamicPseudonyms, function(acc) {
|
282
|
+
if (ret[1] === acc[0]) {
|
283
|
+
ret[1] = acc[1];
|
284
|
+
return true;
|
285
|
+
} else
|
286
|
+
return false;
|
287
|
+
})) {
|
288
|
+
if (multilineVars.dynamicPosition === 'hidden' )
|
289
|
+
ret[1] = '';
|
290
|
+
return ret;
|
291
|
+
}
|
204
292
|
// We didn't find the accent in the list, so consume the space, but don't return an accent.
|
205
293
|
// Although it is possible that ! was used as a line break, so accept that.
|
206
294
|
if (line.charAt(i) === '!' && (ret[0] === 1 || line.charAt(i+ret[0]-1) !== '!'))
|
@@ -319,7 +407,7 @@ window.ABCJS.parse.Parse = function() {
|
|
319
407
|
};
|
320
408
|
|
321
409
|
var addWords = function(line, words) {
|
322
|
-
if (!line) { warn("Can't add words before the first line of
|
410
|
+
if (!line) { warn("Can't add words before the first line of music", line, 0); return; }
|
323
411
|
words = window.ABCJS.parse.strip(words);
|
324
412
|
if (words.charAt(words.length-1) !== '-')
|
325
413
|
words = words + ' '; // Just makes it easier to parse below, since every word has a divider after it.
|
@@ -396,7 +484,7 @@ window.ABCJS.parse.Parse = function() {
|
|
396
484
|
|
397
485
|
var addSymbols = function(line, words) {
|
398
486
|
// TODO-PER: Currently copied from w: line. This needs to be read as symbols instead.
|
399
|
-
if (!line) { warn("Can't add symbols before the first line of
|
487
|
+
if (!line) { warn("Can't add symbols before the first line of music", line, 0); return; }
|
400
488
|
words = window.ABCJS.parse.strip(words);
|
401
489
|
if (words.charAt(words.length-1) !== '-')
|
402
490
|
words = words + ' '; // Just makes it easier to parse below, since every word has a divider after it.
|
@@ -786,6 +874,8 @@ window.ABCJS.parse.Parse = function() {
|
|
786
874
|
}
|
787
875
|
var note = getCoreNote(gra[1], ii, {}, false);
|
788
876
|
if (note !== null) {
|
877
|
+
// The grace note durations should not be affected by the default length: they should be based on 1/16, so if that isn't the default, then multiply here.
|
878
|
+
note.duration = note.duration / (multilineVars.default_length * 8);
|
789
879
|
if (acciaccatura)
|
790
880
|
note.acciaccatura = true;
|
791
881
|
gracenotes.push(note);
|
@@ -1011,9 +1101,13 @@ window.ABCJS.parse.Parse = function() {
|
|
1011
1101
|
if (i + 1 < line.length)
|
1012
1102
|
startNewLine(); // There was a ! in the middle of the line. Start a new line if there is anything after it.
|
1013
1103
|
} else if (ret[1].length > 0) {
|
1014
|
-
if (
|
1015
|
-
el.
|
1016
|
-
|
1104
|
+
if (ret[1].indexOf("style=") === 0) {
|
1105
|
+
el.style = ret[1].substr(6);
|
1106
|
+
} else {
|
1107
|
+
if (el.decoration === undefined)
|
1108
|
+
el.decoration = [];
|
1109
|
+
el.decoration.push(ret[1]);
|
1110
|
+
}
|
1017
1111
|
}
|
1018
1112
|
i += ret[0];
|
1019
1113
|
} else {
|
@@ -1035,6 +1129,7 @@ window.ABCJS.parse.Parse = function() {
|
|
1035
1129
|
// Attach the grace note to an invisible note
|
1036
1130
|
el.rest = { type: 'spacer' };
|
1037
1131
|
el.duration = 0.125; // TODO-PER: I don't think the duration of this matters much, but figure out if it does.
|
1132
|
+
multilineVars.addFormattingOptions(el, tune.formatting, 'note');
|
1038
1133
|
tune.appendElement('note', startOfLine+i, startOfLine+i+ret[0], el);
|
1039
1134
|
multilineVars.measureNotEmpty = true;
|
1040
1135
|
el = {};
|
@@ -1068,6 +1163,7 @@ window.ABCJS.parse.Parse = function() {
|
|
1068
1163
|
if (multilineVars.barNumbers && multilineVars.currBarNumber % multilineVars.barNumbers === 0)
|
1069
1164
|
multilineVars.barNumOnNextNote = multilineVars.currBarNumber;
|
1070
1165
|
}
|
1166
|
+
multilineVars.addFormattingOptions(el, tune.formatting, 'bar');
|
1071
1167
|
tune.appendElement('bar', startOfLine+i, startOfLine+i+ret[0], bar);
|
1072
1168
|
multilineVars.measureNotEmpty = false;
|
1073
1169
|
el = {};
|
@@ -1221,6 +1317,7 @@ window.ABCJS.parse.Parse = function() {
|
|
1221
1317
|
el.barNumber = multilineVars.barNumOnNextNote;
|
1222
1318
|
multilineVars.barNumOnNextNote = null;
|
1223
1319
|
}
|
1320
|
+
multilineVars.addFormattingOptions(el, tune.formatting, 'note');
|
1224
1321
|
tune.appendElement('note', startOfLine+i, startOfLine+i, el);
|
1225
1322
|
multilineVars.measureNotEmpty = true;
|
1226
1323
|
el = {};
|
@@ -1293,6 +1390,7 @@ window.ABCJS.parse.Parse = function() {
|
|
1293
1390
|
el.barNumber = multilineVars.barNumOnNextNote;
|
1294
1391
|
multilineVars.barNumOnNextNote = null;
|
1295
1392
|
}
|
1393
|
+
multilineVars.addFormattingOptions(el, tune.formatting, 'note');
|
1296
1394
|
tune.appendElement('note', startOfLine+startI, startOfLine+i, el);
|
1297
1395
|
multilineVars.measureNotEmpty = true;
|
1298
1396
|
el = {};
|
@@ -1329,8 +1427,10 @@ window.ABCJS.parse.Parse = function() {
|
|
1329
1427
|
// switches.header_only : stop parsing when the header is finished
|
1330
1428
|
// switches.stop_on_warning : stop at the first warning encountered.
|
1331
1429
|
// switches.print: format for the page instead of the browser.
|
1430
|
+
// switches.format: a hash of the desired formatting commands.
|
1431
|
+
if (!switches) switches = {};
|
1332
1432
|
tune.reset();
|
1333
|
-
if (switches
|
1433
|
+
if (switches.print)
|
1334
1434
|
tune.media = 'print';
|
1335
1435
|
multilineVars.reset();
|
1336
1436
|
header.reset(tokenizer, warn, multilineVars, tune);
|
@@ -1350,13 +1450,14 @@ window.ABCJS.parse.Parse = function() {
|
|
1350
1450
|
if (window.ABCJS.parse.last(lines).length === 0) // remove the blank line we added above.
|
1351
1451
|
lines.pop();
|
1352
1452
|
try {
|
1453
|
+
if (switches.format) {
|
1454
|
+
window.ABCJS.parse.parseDirective.globalFormatting(switches.format);
|
1455
|
+
}
|
1353
1456
|
window.ABCJS.parse.each(lines, function(line) {
|
1354
|
-
if (switches)
|
1355
|
-
|
1356
|
-
|
1357
|
-
|
1358
|
-
throw "normal_abort";
|
1359
|
-
}
|
1457
|
+
if (switches.header_only && multilineVars.is_in_header === false)
|
1458
|
+
throw "normal_abort";
|
1459
|
+
if (switches.stop_on_warning && multilineVars.warnings)
|
1460
|
+
throw "normal_abort";
|
1360
1461
|
if (multilineVars.is_in_history) {
|
1361
1462
|
if (line.charAt(1) === ':') {
|
1362
1463
|
multilineVars.is_in_history = false;
|
@@ -1398,7 +1499,7 @@ window.ABCJS.parse.Parse = function() {
|
|
1398
1499
|
ph = pl;
|
1399
1500
|
pl = x;
|
1400
1501
|
}
|
1401
|
-
tune.cleanUp(pl, ph, multilineVars.barsperstaff, multilineVars.staffnonote);
|
1502
|
+
multilineVars.openSlurs = tune.cleanUp(pl, ph, multilineVars.barsperstaff, multilineVars.staffnonote, multilineVars.openSlurs);
|
1402
1503
|
} catch (err) {
|
1403
1504
|
if (err !== "normal_abort")
|
1404
1505
|
throw err;
|
@@ -9,6 +9,7 @@ if (!window.ABCJS.parse)
|
|
9
9
|
window.ABCJS.parse.parseDirective = {};
|
10
10
|
|
11
11
|
(function() {
|
12
|
+
"use strict";
|
12
13
|
var tokenizer;
|
13
14
|
var warn;
|
14
15
|
var multilineVars;
|
@@ -18,6 +19,377 @@ window.ABCJS.parse.parseDirective = {};
|
|
18
19
|
warn = warn_;
|
19
20
|
multilineVars = multilineVars_;
|
20
21
|
tune = tune_;
|
22
|
+
initializeFonts();
|
23
|
+
};
|
24
|
+
|
25
|
+
function initializeFonts() {
|
26
|
+
multilineVars.annotationfont = { face: "Helvetica", size: 12, weight: "normal", style: "normal", decoration: "none" };
|
27
|
+
multilineVars.gchordfont = { face: "Helvetica", size: 12, weight: "normal", style: "normal", decoration: "none" };
|
28
|
+
multilineVars.historyfont = { face: "\"Times New Roman\"", size: 16, weight: "normal", style: "normal", decoration: "none" };
|
29
|
+
multilineVars.infofont = { face: "\"Times New Roman\"", size: 14, weight: "normal", style: "italic", decoration: "none" };
|
30
|
+
multilineVars.measurefont = { face: "\"Times New Roman\"", size: 14, weight: "normal", style: "italic", decoration: "none" };
|
31
|
+
multilineVars.partsfont = { face: "\"Times New Roman\"", size: 15, weight: "normal", style: "normal", decoration: "none" };
|
32
|
+
multilineVars.repeatfont = { face: "\"Times New Roman\"", size: 13, weight: "normal", style: "normal", decoration: "none" };
|
33
|
+
multilineVars.textfont = { face: "\"Times New Roman\"", size: 16, weight: "normal", style: "normal", decoration: "none" };
|
34
|
+
multilineVars.vocalfont = { face: "\"Times New Roman\"", size: 13, weight: "bold", style: "normal", decoration: "none" };
|
35
|
+
multilineVars.wordsfont = { face: "\"Times New Roman\"", size: 16, weight: "normal", style: "normal", decoration: "none" };
|
36
|
+
|
37
|
+
<<<<<<< HEAD
|
38
|
+
// These fonts are global for the entire tune.
|
39
|
+
=======
|
40
|
+
>>>>>>> origin/master
|
41
|
+
tune.formatting.composerfont = { face: "\"Times New Roman\"", size: 14, weight: "normal", style: "italic", decoration: "none" };
|
42
|
+
tune.formatting.subtitlefont = { face: "\"Times New Roman\"", size: 16, weight: "normal", style: "normal", decoration: "none" };
|
43
|
+
tune.formatting.tempofont = { face: "\"Times New Roman\"", size: 15, weight: "bold", style: "normal", decoration: "none" };
|
44
|
+
tune.formatting.titlefont = { face: "\"Times New Roman\"", size: 20, weight: "normal", style: "normal", decoration: "none" };
|
45
|
+
tune.formatting.footerfont = { face: "\"Times New Roman\"", size: 12, weight: "normal", style: "normal", decoration: "none" };
|
46
|
+
tune.formatting.headerfont = { face: "\"Times New Roman\"", size: 12, weight: "normal", style: "normal", decoration: "none" };
|
47
|
+
tune.formatting.voicefont = { face: "\"Times New Roman\"", size: 13, weight: "bold", style: "normal", decoration: "none" };
|
48
|
+
<<<<<<< HEAD
|
49
|
+
|
50
|
+
// these are the default fonts for these element types. In the printer, these fonts might change as the tune progresses.
|
51
|
+
tune.formatting.annotationfont = multilineVars.annotationfont;
|
52
|
+
tune.formatting.gchordfont = multilineVars.gchordfont;
|
53
|
+
tune.formatting.historyfont = multilineVars.historyfont;
|
54
|
+
tune.formatting.infofont = multilineVars.infofont;
|
55
|
+
tune.formatting.measurefont = multilineVars.measurefont;
|
56
|
+
tune.formatting.partsfont = multilineVars.partsfont;
|
57
|
+
tune.formatting.repeatfont = multilineVars.repeatfont;
|
58
|
+
tune.formatting.textfont = multilineVars.textfont;
|
59
|
+
tune.formatting.vocalfont = multilineVars.vocalfont;
|
60
|
+
tune.formatting.wordsfont = multilineVars.wordsfont;
|
61
|
+
=======
|
62
|
+
>>>>>>> origin/master
|
63
|
+
}
|
64
|
+
|
65
|
+
var fontTypeCanHaveBox = { gchordfont: true, measurefont: true, partsfont: true };
|
66
|
+
|
67
|
+
var fontTranslation = function(fontFace) {
|
68
|
+
// This translates Postscript fonts for a web alternative.
|
69
|
+
// Note that the postscript fonts contain italic and bold info in them, so what is returned is a hash.
|
70
|
+
|
71
|
+
switch (fontFace) {
|
72
|
+
case "Arial-Italic":
|
73
|
+
return { face: "Arial", weight: "normal", style: "italic", decoration: "none" };
|
74
|
+
case "Arial-Bold":
|
75
|
+
return { face: "Arial", weight: "bold", style: "normal", decoration: "none" };
|
76
|
+
case "Bookman-Demi":
|
77
|
+
return { face: "Bookman,serif", weight: "bold", style: "normal", decoration: "none" };
|
78
|
+
case "Bookman-DemiItalic":
|
79
|
+
return { face: "Bookman,serif", weight: "bold", style: "italic", decoration: "none" };
|
80
|
+
case "Bookman-Light":
|
81
|
+
return { face: "Bookman,serif", weight: "normal", style: "normal", decoration: "none" };
|
82
|
+
case "Bookman-LightItalic":
|
83
|
+
return { face: "Bookman,serif", weight: "normal", style: "italic", decoration: "none" };
|
84
|
+
case "Courier":
|
85
|
+
return { face: "\"Courier New\"", weight: "normal", style: "normal", decoration: "none" };
|
86
|
+
case "Courier-Oblique":
|
87
|
+
return { face: "\"Courier New\"", weight: "normal", style: "italic", decoration: "none" };
|
88
|
+
case "Courier-Bold":
|
89
|
+
return { face: "\"Courier New\"", weight: "bold", style: "normal", decoration: "none" };
|
90
|
+
case "Courier-BoldOblique":
|
91
|
+
return { face: "\"Courier New\"", weight: "bold", style: "italic", decoration: "none" };
|
92
|
+
case "AvantGarde-Book":
|
93
|
+
return { face: "AvantGarde,Arial", weight: "normal", style: "normal", decoration: "none" };
|
94
|
+
case "AvantGarde-BookOblique":
|
95
|
+
return { face: "AvantGarde,Arial", weight: "normal", style: "italic", decoration: "none" };
|
96
|
+
case "AvantGarde-Demi":
|
97
|
+
case "Avant-Garde-Demi":
|
98
|
+
return { face: "AvantGarde,Arial", weight: "bold", style: "normal", decoration: "none" };
|
99
|
+
case "AvantGarde-DemiOblique":
|
100
|
+
return { face: "AvantGarde,Arial", weight: "bold", style: "italic", decoration: "none" };
|
101
|
+
case "Helvetica-Oblique":
|
102
|
+
return { face: "Helvetica", weight: "normal", style: "italic", decoration: "none" };
|
103
|
+
case "Helvetica-Bold":
|
104
|
+
return { face: "Helvetica", weight: "bold", style: "normal", decoration: "none" };
|
105
|
+
case "Helvetica-BoldOblique":
|
106
|
+
return { face: "Helvetica", weight: "bold", style: "italic", decoration: "none" };
|
107
|
+
case "Helvetica-Narrow":
|
108
|
+
return { face: "\"Helvetica Narrow\",Helvetica", weight: "normal", style: "normal", decoration: "none" };
|
109
|
+
case "Helvetica-Narrow-Oblique":
|
110
|
+
return { face: "\"Helvetica Narrow\",Helvetica", weight: "normal", style: "italic", decoration: "none" };
|
111
|
+
case "Helvetica-Narrow-Bold":
|
112
|
+
return { face: "\"Helvetica Narrow\",Helvetica", weight: "bold", style: "normal", decoration: "none" };
|
113
|
+
case "Helvetica-Narrow-BoldOblique":
|
114
|
+
return { face: "\"Helvetica Narrow\",Helvetica", weight: "bold", style: "italic", decoration: "none" };
|
115
|
+
case "Palatino-Roman":
|
116
|
+
return { face: "Palatino", weight: "normal", style: "normal", decoration: "none" };
|
117
|
+
case "Palatino-Italic":
|
118
|
+
return { face: "Palatino", weight: "normal", style: "italic", decoration: "none" };
|
119
|
+
case "Palatino-Bold":
|
120
|
+
return { face: "Palatino", weight: "bold", style: "normal", decoration: "none" };
|
121
|
+
case "Palatino-BoldItalic":
|
122
|
+
return { face: "Palatino", weight: "bold", style: "italic", decoration: "none" };
|
123
|
+
case "NewCenturySchlbk-Roman":
|
124
|
+
return { face: "\"New Century\",serif", weight: "normal", style: "normal", decoration: "none" };
|
125
|
+
case "NewCenturySchlbk-Italic":
|
126
|
+
return { face: "\"New Century\",serif", weight: "normal", style: "italic", decoration: "none" };
|
127
|
+
case "NewCenturySchlbk-Bold":
|
128
|
+
return { face: "\"New Century\",serif", weight: "bold", style: "normal", decoration: "none" };
|
129
|
+
case "NewCenturySchlbk-BoldItalic":
|
130
|
+
return { face: "\"New Century\",serif", weight: "bold", style: "italic", decoration: "none" };
|
131
|
+
case "Times":
|
132
|
+
case "Times-Roman":
|
133
|
+
case "Times-Narrow":
|
134
|
+
case "Times-Courier":
|
135
|
+
case "Times-New-Roman":
|
136
|
+
return { face: "\"Times New Roman\"", weight: "normal", style: "normal", decoration: "none" };
|
137
|
+
case "Times-Italic":
|
138
|
+
case "Times-Italics":
|
139
|
+
return { face: "\"Times New Roman\"", weight: "normal", style: "italic", decoration: "none" };
|
140
|
+
case "Times-Bold":
|
141
|
+
return { face: "\"Times New Roman\"", weight: "bold", style: "normal", decoration: "none" };
|
142
|
+
case "Times-BoldItalic":
|
143
|
+
return { face: "\"Times New Roman\"", weight: "bold", style: "italic", decoration: "none" };
|
144
|
+
case "ZapfChancery-MediumItalic":
|
145
|
+
return { face: "\"Zapf Chancery\",cursive,serif", weight: "normal", style: "normal", decoration: "none" };
|
146
|
+
default:
|
147
|
+
return null;
|
148
|
+
}
|
149
|
+
};
|
150
|
+
|
151
|
+
var getFontParameter = function(tokens, currentSetting, str, position, cmd) {
|
152
|
+
// Every font parameter has the following format:
|
153
|
+
// <face> <utf8> <size> <modifiers> <box>
|
154
|
+
// Where:
|
155
|
+
// face: either a standard web font name, or a postscript font, enumerated in fontTranslation. This could also be an * or be missing if the face shouldn't change.
|
156
|
+
// utf8: This is optional, and specifies utf8. That's all that is supported so the field is just silently ignored.
|
157
|
+
// size: The size, in pixels. This may be omitted if the size is not changing.
|
158
|
+
// modifiers: zero or more of "bold", "italic", "underline"
|
159
|
+
// box: Only applies to the measure numbers, gchords, and the parts. If present, then a box is drawn around the characters.
|
160
|
+
// If face is present, then all the modifiers are cleared. If face is absent, then the modifiers are illegal.
|
161
|
+
// The face can be a single word, a set of words separated by hyphens, or a quoted string.
|
162
|
+
//
|
163
|
+
// So, in practicality, there are three types of font definitions: a number only, an asterisk and a number only, or the full definition (with an optional size).
|
164
|
+
function processNumberOnly() {
|
165
|
+
var size = parseInt(tokens[0].token);
|
166
|
+
tokens.shift();
|
167
|
+
if (!currentSetting) {
|
168
|
+
warn("Can't set just the size of the font since there is no default value.", str, position);
|
169
|
+
return { face: "\"Times New Roman\"", weight: "normal", style: "normal", decoration: "none", size: size};
|
170
|
+
}
|
171
|
+
if (tokens.length === 0) {
|
172
|
+
return { face: currentSetting.face, weight: currentSetting.weight, style: currentSetting.style, decoration: currentSetting.decoration, size: size};
|
173
|
+
}
|
174
|
+
if (tokens.length === 1 && tokens[0].token === "box" && fontTypeCanHaveBox[cmd])
|
175
|
+
return { face: currentSetting.face, weight: currentSetting.weight, style: currentSetting.style, decoration: currentSetting.decoration, size: size, box: true};
|
176
|
+
warn("Extra parameters in font definition.", str, position);
|
177
|
+
return { face: currentSetting.face, weight: currentSetting.weight, style: currentSetting.style, decoration: currentSetting.decoration, size: size};
|
178
|
+
}
|
179
|
+
|
180
|
+
// format 1: asterisk and number only
|
181
|
+
if (tokens[0].token === '*') {
|
182
|
+
tokens.shift();
|
183
|
+
if (tokens[0].type === 'number')
|
184
|
+
return processNumberOnly();
|
185
|
+
else {
|
186
|
+
warn("Expected font size number after *.", str, position);
|
187
|
+
}
|
188
|
+
}
|
189
|
+
|
190
|
+
// format 2: number only
|
191
|
+
if (tokens[0].type === 'number') {
|
192
|
+
return processNumberOnly();
|
193
|
+
}
|
194
|
+
|
195
|
+
// format 3: whole definition
|
196
|
+
var face = [];
|
197
|
+
var size;
|
198
|
+
var weight = "normal";
|
199
|
+
var style = "normal";
|
200
|
+
var decoration = "none";
|
201
|
+
var box = false;
|
202
|
+
var state = 'face';
|
203
|
+
var hyphenLast = false;
|
204
|
+
while (tokens.length) {
|
205
|
+
var currToken = tokens.shift();
|
206
|
+
var word = currToken.token.toLowerCase();
|
207
|
+
switch (state) {
|
208
|
+
case 'face':
|
209
|
+
if (hyphenLast || (word !== 'utf' && currToken.type !== 'number' && word !== "bold" && word !== "italic" && word !== "underline" && word !== "box")) {
|
210
|
+
if (face.length > 0 && currToken.token === '-') {
|
211
|
+
hyphenLast = true;
|
212
|
+
face[face.length-1] = face[face.length-1] + currToken.token;
|
213
|
+
}
|
214
|
+
else {
|
215
|
+
if (hyphenLast) {
|
216
|
+
hyphenLast = false;
|
217
|
+
face[face.length-1] = face[face.length-1] + currToken.token;
|
218
|
+
} else
|
219
|
+
face.push(currToken.token);
|
220
|
+
}
|
221
|
+
} else {
|
222
|
+
if (currToken.type === 'number') {
|
223
|
+
if (size) {
|
224
|
+
warn("Font size specified twice in font definition.", str, position);
|
225
|
+
} else {
|
226
|
+
size = currToken.token;
|
227
|
+
}
|
228
|
+
state = 'modifier';
|
229
|
+
} else if (word === "bold")
|
230
|
+
weight = "bold";
|
231
|
+
else if (word === "italic")
|
232
|
+
style = "italic";
|
233
|
+
else if (word === "underline")
|
234
|
+
decoration = "underline";
|
235
|
+
else if (word === "box") {
|
236
|
+
if (fontTypeCanHaveBox[cmd])
|
237
|
+
box = true;
|
238
|
+
else
|
239
|
+
warn("This font style doesn't support \"box\"", str, position);
|
240
|
+
state = "finished";
|
241
|
+
} else if (word === "utf") {
|
242
|
+
currToken = tokens.shift(); // this gets rid of the "8" after "utf"
|
243
|
+
state = "size";
|
244
|
+
} else
|
245
|
+
warn("Unknown parameter " + currToken.token + " in font definition.", str, position);
|
246
|
+
}
|
247
|
+
break;
|
248
|
+
case "size":
|
249
|
+
if (currToken.type === 'number') {
|
250
|
+
if (size) {
|
251
|
+
warn("Font size specified twice in font definition.", str, position);
|
252
|
+
} else {
|
253
|
+
size = currToken.token;
|
254
|
+
}
|
255
|
+
} else {
|
256
|
+
warn("Expected font size in font definition.", str, position);
|
257
|
+
}
|
258
|
+
state = 'modifier';
|
259
|
+
break;
|
260
|
+
case "modifier":
|
261
|
+
if (word === "bold")
|
262
|
+
weight = "bold";
|
263
|
+
else if (word === "italic")
|
264
|
+
style = "italic";
|
265
|
+
else if (word === "underline")
|
266
|
+
decoration = "underline";
|
267
|
+
else if (word === "box") {
|
268
|
+
if (fontTypeCanHaveBox[cmd])
|
269
|
+
box = true;
|
270
|
+
else
|
271
|
+
warn("This font style doesn't support \"box\"", str, position);
|
272
|
+
state = "finished";
|
273
|
+
} else
|
274
|
+
warn("Unknown parameter " + currToken.token + " in font definition.", str, position);
|
275
|
+
break;
|
276
|
+
case "finished":
|
277
|
+
warn("Extra characters found after \"box\" in font definition.", str, position);
|
278
|
+
break;
|
279
|
+
}
|
280
|
+
}
|
281
|
+
|
282
|
+
if (size === undefined) {
|
283
|
+
if (!currentSetting) {
|
284
|
+
warn("Must specify the size of the font since there is no default value.", str, position);
|
285
|
+
size = 12;
|
286
|
+
<<<<<<< HEAD
|
287
|
+
} else
|
288
|
+
size = currentSetting.size;
|
289
|
+
=======
|
290
|
+
}
|
291
|
+
size = currentSetting.size;
|
292
|
+
>>>>>>> origin/master
|
293
|
+
} else
|
294
|
+
size = parseFloat(size);
|
295
|
+
|
296
|
+
face = face.join(' ');
|
297
|
+
var psFont = fontTranslation(face);
|
298
|
+
var font = {};
|
299
|
+
if (psFont) {
|
300
|
+
font.face = psFont.face;
|
301
|
+
font.weight = psFont.weight;
|
302
|
+
font.style = psFont.style;
|
303
|
+
font.decoration = psFont.decoration;
|
304
|
+
font.size = size;
|
305
|
+
if (box)
|
306
|
+
font.box = true;
|
307
|
+
return font;
|
308
|
+
}
|
309
|
+
font.face = face;
|
310
|
+
font.weight = weight;
|
311
|
+
font.style = style;
|
312
|
+
font.decoration = decoration;
|
313
|
+
font.size = size;
|
314
|
+
if (box)
|
315
|
+
font.box = true;
|
316
|
+
return font;
|
317
|
+
};
|
318
|
+
|
319
|
+
var getChangingFont = function(cmd, tokens, str) {
|
320
|
+
if (tokens.length === 0)
|
321
|
+
return "Directive \"" + cmd + "\" requires a font as a parameter.";
|
322
|
+
multilineVars[cmd] = getFontParameter(tokens, multilineVars[cmd], str, 0, cmd);
|
323
|
+
return null;
|
324
|
+
};
|
325
|
+
var getGlobalFont = function(cmd, tokens, str) {
|
326
|
+
if (tokens.length === 0)
|
327
|
+
return "Directive \"" + cmd + "\" requires a font as a parameter.";
|
328
|
+
tune.formatting[cmd] = getFontParameter(tokens, tune.formatting[cmd], str, 0, cmd);
|
329
|
+
return null;
|
330
|
+
};
|
331
|
+
|
332
|
+
var setScale = function(cmd, tokens) {
|
333
|
+
var scratch = "";
|
334
|
+
window.ABCJS.parse.each(tokens, function(tok) {
|
335
|
+
scratch += tok.token;
|
336
|
+
});
|
337
|
+
var num = parseFloat(scratch);
|
338
|
+
if (isNaN(num) || num === 0)
|
339
|
+
return "Directive \"" + cmd + "\" requires a number as a parameter.";
|
340
|
+
tune.formatting.scale = num;
|
341
|
+
|
342
|
+
};
|
343
|
+
|
344
|
+
var getRequiredMeasurement = function(cmd, tokens) {
|
345
|
+
var points = tokenizer.getMeasurement(tokens);
|
346
|
+
if (points.used === 0 || tokens.length !== 0)
|
347
|
+
return { error: "Directive \"" + cmd + "\" requires a measurement as a parameter."};
|
348
|
+
return points.value;
|
349
|
+
};
|
350
|
+
var oneParameterMeasurement = function(cmd, tokens) {
|
351
|
+
var points = tokenizer.getMeasurement(tokens);
|
352
|
+
if (points.used === 0 || tokens.length !== 0)
|
353
|
+
return "Directive \"" + cmd + "\" requires a measurement as a parameter.";
|
354
|
+
tune.formatting[cmd] = points.value;
|
355
|
+
return null;
|
356
|
+
};
|
357
|
+
|
358
|
+
var addMultilineVar = function(key, cmd, tokens, min, max) {
|
359
|
+
if (tokens.length !== 1 || tokens[0].type !== 'number')
|
360
|
+
return "Directive \"" + cmd + "\" requires a number as a parameter.";
|
361
|
+
var i = tokens[0].intt;
|
362
|
+
if (min !== undefined && i < min)
|
363
|
+
return "Directive \"" + cmd + "\" requires a number greater than or equal to " + min + " as a parameter.";
|
364
|
+
if (max !== undefined && i > max)
|
365
|
+
return "Directive \"" + cmd + "\" requires a number less than or equal to " + max + " as a parameter.";
|
366
|
+
multilineVars[key] = i;
|
367
|
+
return null;
|
368
|
+
};
|
369
|
+
|
370
|
+
var addMultilineVarBool = function(key, cmd, tokens) {
|
371
|
+
var str = addMultilineVar(key, cmd, tokens, 0, 1);
|
372
|
+
if (str !== null) return str;
|
373
|
+
multilineVars[key] = (multilineVars[key] === 1);
|
374
|
+
return null;
|
375
|
+
<<<<<<< HEAD
|
376
|
+
};
|
377
|
+
|
378
|
+
var addMultilineVarOneParamChoice = function(key, cmd, tokens, choices) {
|
379
|
+
if (tokens.length !== 1)
|
380
|
+
return "Directive \"" + cmd + "\" requires one of [ " + choices.join(", ") + " ] as a parameter.";
|
381
|
+
var choice = tokens[0].token;
|
382
|
+
var found = false;
|
383
|
+
for (var i = 0; !found && i < choices.length; i++) {
|
384
|
+
if (choices[i] === choice)
|
385
|
+
found = true;
|
386
|
+
}
|
387
|
+
if (!found)
|
388
|
+
return "Directive \"" + cmd + "\" requires one of [ " + choices.join(", ") + " ] as a parameter.";
|
389
|
+
multilineVars[key] = choice;
|
390
|
+
return null;
|
391
|
+
=======
|
392
|
+
>>>>>>> origin/master
|
21
393
|
};
|
22
394
|
|
23
395
|
window.ABCJS.parse.parseDirective.parseFontChangeLine = function(textstr) {
|
@@ -44,77 +416,13 @@ window.ABCJS.parse.parseDirective = {};
|
|
44
416
|
return textstr;
|
45
417
|
};
|
46
418
|
|
419
|
+
var positionChoices = [ 'auto', 'above', 'below', 'hidden' ];
|
47
420
|
window.ABCJS.parse.parseDirective.addDirective = function(str) {
|
48
|
-
var getRequiredMeasurement = function(cmd, tokens) {
|
49
|
-
var points = tokenizer.getMeasurement(tokens);
|
50
|
-
if (points.used === 0 || tokens.length !== 0)
|
51
|
-
return { error: "Directive \"" + cmd + "\" requires a measurement as a parameter."};
|
52
|
-
return points.value;
|
53
|
-
};
|
54
|
-
var oneParameterMeasurement = function(cmd, tokens) {
|
55
|
-
var points = tokenizer.getMeasurement(tokens);
|
56
|
-
if (points.used === 0 || tokens.length !== 0)
|
57
|
-
return "Directive \"" + cmd + "\" requires a measurement as a parameter.";
|
58
|
-
tune.formatting[cmd] = points.value;
|
59
|
-
return null;
|
60
|
-
};
|
61
|
-
var getFontParameter = function(tokens) {
|
62
|
-
var font = {};
|
63
|
-
var token = window.ABCJS.parse.last(tokens);
|
64
|
-
if (token.type === 'number') {
|
65
|
-
font.size = parseInt(token.token);
|
66
|
-
tokens.pop();
|
67
|
-
}
|
68
|
-
if (tokens.length > 0) {
|
69
|
-
var scratch = "";
|
70
|
-
window.ABCJS.parse.each(tokens, function(tok) {
|
71
|
-
if (tok.token !== '-') {
|
72
|
-
if (scratch.length > 0) scratch += ' ';
|
73
|
-
scratch += tok.token;
|
74
|
-
}
|
75
|
-
});
|
76
|
-
font.font = scratch;
|
77
|
-
}
|
78
|
-
return font;
|
79
|
-
};
|
80
|
-
var getChangingFont = function(cmd, tokens) {
|
81
|
-
if (tokens.length === 0)
|
82
|
-
return "Directive \"" + cmd + "\" requires a font as a parameter.";
|
83
|
-
multilineVars[cmd] = getFontParameter(tokens);
|
84
|
-
return null;
|
85
|
-
};
|
86
|
-
var getGlobalFont = function(cmd, tokens) {
|
87
|
-
if (tokens.length === 0)
|
88
|
-
return "Directive \"" + cmd + "\" requires a font as a parameter.";
|
89
|
-
tune.formatting[cmd] = getFontParameter(tokens);
|
90
|
-
return null;
|
91
|
-
};
|
92
|
-
|
93
|
-
var addMultilineVar = function(key, cmd, tokens, min, max) {
|
94
|
-
if (tokens.length !== 1 || tokens[0].type !== 'number')
|
95
|
-
return "Directive \"" + cmd + "\" requires a number as a parameter.";
|
96
|
-
var i = tokens[0].intt;
|
97
|
-
if (min !== undefined && i < min)
|
98
|
-
return "Directive \"" + cmd + "\" requires a number greater than or equal to " + min + " as a parameter.";
|
99
|
-
if (max !== undefined && i > max)
|
100
|
-
return "Directive \"" + cmd + "\" requires a number less than or equal to " + max + " as a parameter.";
|
101
|
-
multilineVars[key] = i;
|
102
|
-
return null;
|
103
|
-
};
|
104
|
-
|
105
|
-
var addMultilineVarBool = function(key, cmd, tokens) {
|
106
|
-
var str = addMultilineVar(key, cmd, tokens, 0, 1);
|
107
|
-
if (str !== null) return str;
|
108
|
-
multilineVars[key] = (multilineVars[key] === 1);
|
109
|
-
return null;
|
110
|
-
};
|
111
|
-
|
112
421
|
var tokens = tokenizer.tokenize(str, 0, str.length); // 3 or more % in a row, or just spaces after %% is just a comment
|
113
422
|
if (tokens.length === 0 || tokens[0].type !== 'alpha') return null;
|
114
423
|
var restOfString = str.substring(str.indexOf(tokens[0].token)+tokens[0].token.length);
|
115
424
|
restOfString = tokenizer.stripComment(restOfString);
|
116
425
|
var cmd = tokens.shift().token.toLowerCase();
|
117
|
-
var num;
|
118
426
|
var scratch = "";
|
119
427
|
switch (cmd)
|
120
428
|
{
|
@@ -122,47 +430,35 @@ window.ABCJS.parse.parseDirective = {};
|
|
122
430
|
// Most of them are direct translations from the directives that will be parsed in. See abcm2ps's format.txt for info on each of these.
|
123
431
|
// alignbars: { type: "number", optional: true },
|
124
432
|
// aligncomposer: { type: "string", Enum: [ 'left', 'center','right' ], optional: true },
|
125
|
-
// annotationfont: fontType,
|
126
433
|
// bstemdown: { type: "boolean", optional: true },
|
127
434
|
// continueall: { type: "boolean", optional: true },
|
128
435
|
// dynalign: { type: "boolean", optional: true },
|
129
436
|
// exprabove: { type: "boolean", optional: true },
|
130
437
|
// exprbelow: { type: "boolean", optional: true },
|
131
438
|
// flatbeams: { type: "boolean", optional: true },
|
132
|
-
// footer: { type: "string", optional: true },
|
133
|
-
// footerfont: fontType,
|
134
439
|
// gchordbox: { type: "boolean", optional: true },
|
135
440
|
// graceslurs: { type: "boolean", optional: true },
|
136
441
|
// gracespacebefore: { type: "number", optional: true },
|
137
442
|
// gracespaceinside: { type: "number", optional: true },
|
138
443
|
// gracespaceafter: { type: "number", optional: true },
|
139
|
-
// header: { type: "string", optional: true },
|
140
|
-
// headerfont: fontType,
|
141
|
-
// historyfont: fontType,
|
142
|
-
// infofont: fontType,
|
143
444
|
// infospace: { type: "number", optional: true },
|
144
445
|
// lineskipfac: { type: "number", optional: true },
|
145
446
|
// maxshrink: { type: "number", optional: true },
|
146
447
|
// maxstaffsep: { type: "number", optional: true },
|
147
448
|
// maxsysstaffsep: { type: "number", optional: true },
|
148
|
-
// measurebox: { type: "boolean", optional: true },
|
149
|
-
// measurefont: fontType,
|
150
449
|
// notespacingfactor: { type: "number", optional: true },
|
151
450
|
// parskipfac: { type: "number", optional: true },
|
152
|
-
// partsbox: { type: "boolean", optional: true },
|
153
|
-
// repeatfont: fontType,
|
154
|
-
// rightmargin: { type: "number", optional: true },
|
155
451
|
// slurheight: { type: "number", optional: true },
|
156
452
|
// splittune: { type: "boolean", optional: true },
|
157
453
|
// squarebreve: { type: "boolean", optional: true },
|
158
454
|
// stemheight: { type: "number", optional: true },
|
159
455
|
// straightflags: { type: "boolean", optional: true },
|
160
456
|
// stretchstaff: { type: "boolean", optional: true },
|
161
|
-
// textfont: fontType,
|
162
457
|
// titleformat: { type: "string", optional: true },
|
458
|
+
<<<<<<< HEAD
|
459
|
+
=======
|
163
460
|
// vocalabove: { type: "boolean", optional: true },
|
164
|
-
|
165
|
-
// wordsfont: fontType,
|
461
|
+
>>>>>>> origin/master
|
166
462
|
case "bagpipes":tune.formatting.bagpipes = true;break;
|
167
463
|
case "landscape":multilineVars.landscape = true;break;
|
168
464
|
case "papersize":multilineVars.papersize = restOfString;break;
|
@@ -172,6 +468,12 @@ window.ABCJS.parse.parseDirective = {};
|
|
172
468
|
case "titleleft":tune.formatting.titleleft = true;break;
|
173
469
|
case "measurebox":tune.formatting.measurebox = true;break;
|
174
470
|
|
471
|
+
case "vocal": return addMultilineVarOneParamChoice("vocalPosition", cmd, tokens, positionChoices);
|
472
|
+
case "dynamic": return addMultilineVarOneParamChoice("dynamicPosition", cmd, tokens, positionChoices);
|
473
|
+
case "gchord": return addMultilineVarOneParamChoice("chordPosition", cmd, tokens, positionChoices);
|
474
|
+
case "ornament": return addMultilineVarOneParamChoice("ornamentPosition", cmd, tokens, positionChoices);
|
475
|
+
case "volume": return addMultilineVarOneParamChoice("volumePosition", cmd, tokens, positionChoices);
|
476
|
+
|
175
477
|
case "botmargin":
|
176
478
|
case "botspace":
|
177
479
|
case "composerspace":
|
@@ -202,14 +504,7 @@ window.ABCJS.parse.parseDirective = {};
|
|
202
504
|
tune.addSpacing(vskip);
|
203
505
|
return null;
|
204
506
|
case "scale":
|
205
|
-
|
206
|
-
window.ABCJS.parse.each(tokens, function(tok) {
|
207
|
-
scratch += tok.token;
|
208
|
-
});
|
209
|
-
num = parseFloat(scratch);
|
210
|
-
if (isNaN(num) || num === 0)
|
211
|
-
return "Directive \"" + cmd + "\" requires a number as a parameter.";
|
212
|
-
tune.formatting.scale = num;
|
507
|
+
setScale(cmd, tokens);
|
213
508
|
break;
|
214
509
|
case "sep":
|
215
510
|
if (tokens.length === 0)
|
@@ -244,6 +539,10 @@ window.ABCJS.parse.parseDirective = {};
|
|
244
539
|
scratch = addMultilineVarBool('printTempo', cmd, tokens);
|
245
540
|
if (scratch !== null) return scratch;
|
246
541
|
break;
|
542
|
+
case "partsbox":
|
543
|
+
scratch = addMultilineVarBool('partsBox', cmd, tokens);
|
544
|
+
if (scratch !== null) return scratch;
|
545
|
+
break;
|
247
546
|
case "measurenb":
|
248
547
|
case "barnumbers":
|
249
548
|
scratch = addMultilineVar('barNumbers', cmd, tokens);
|
@@ -277,43 +576,54 @@ window.ABCJS.parse.parseDirective = {};
|
|
277
576
|
break;
|
278
577
|
case "setfont":
|
279
578
|
var sfTokens = tokenizer.tokenize(restOfString, 0, restOfString.length);
|
280
|
-
var sfDone = false;
|
579
|
+
// var sfDone = false;
|
281
580
|
if (sfTokens.length >= 4) {
|
282
581
|
if (sfTokens[0].token === '-' && sfTokens[1].type === 'number') {
|
283
582
|
var sfNum = parseInt(sfTokens[1].token);
|
284
583
|
if (sfNum >= 1 && sfNum <= 4) {
|
285
584
|
if (!multilineVars.setfont)
|
286
585
|
multilineVars.setfont = [];
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
586
|
+
sfTokens.shift();
|
587
|
+
sfTokens.shift();
|
588
|
+
multilineVars.setfont[sfNum] = getFontParameter(sfTokens, multilineVars.setfont[sfNum], str, 0, 'setfont');
|
589
|
+
// var sfSize = sfTokens.pop();
|
590
|
+
// if (sfSize.type === 'number') {
|
591
|
+
// sfSize = parseInt(sfSize.token);
|
592
|
+
// var sfFontName = '';
|
593
|
+
// for (var sfi = 2; sfi < sfTokens.length; sfi++)
|
594
|
+
// sfFontName += sfTokens[sfi].token;
|
595
|
+
// multilineVars.setfont[sfNum] = { face: sfFontName, size: sfSize };
|
596
|
+
// sfDone = true;
|
597
|
+
// }
|
296
598
|
}
|
297
599
|
}
|
298
600
|
}
|
299
|
-
if (!sfDone)
|
300
|
-
return "Bad parameters: " + cmd;
|
601
|
+
// if (!sfDone)
|
602
|
+
// return "Bad parameters: " + cmd;
|
301
603
|
break;
|
302
604
|
case "gchordfont":
|
303
605
|
case "partsfont":
|
304
606
|
case "vocalfont":
|
305
607
|
case "textfont":
|
306
|
-
|
307
|
-
case "
|
308
|
-
case "
|
608
|
+
case "annotationfont":
|
609
|
+
case "historyfont":
|
610
|
+
case "infofont":
|
611
|
+
case "measurefont":
|
612
|
+
case "repeatfont":
|
613
|
+
case "wordsfont":
|
614
|
+
return getChangingFont(cmd, tokens, str);
|
309
615
|
case "composerfont":
|
310
616
|
case "subtitlefont":
|
311
617
|
case "tempofont":
|
312
618
|
case "titlefont":
|
313
619
|
case "voicefont":
|
314
|
-
|
620
|
+
case "footerfont":
|
621
|
+
case "headerfont":
|
622
|
+
return getGlobalFont(cmd, tokens, str);
|
623
|
+
case "barlabelfont":
|
624
|
+
case "barnumberfont":
|
315
625
|
case "barnumfont":
|
316
|
-
return
|
626
|
+
return getChangingFont("measurefont", tokens, str);
|
317
627
|
case "staves":
|
318
628
|
case "score":
|
319
629
|
multilineVars.score_is_present = true;
|
@@ -411,19 +721,27 @@ window.ABCJS.parse.parseDirective = {};
|
|
411
721
|
tune.addNewPage(pgNum.digits === 0 ? -1 : pgNum.value);
|
412
722
|
break;
|
413
723
|
|
414
|
-
case "abc
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
724
|
+
case "abc":
|
725
|
+
var arr = restOfString.split(' ');
|
726
|
+
switch (arr[0]) {
|
727
|
+
case "-copyright":
|
728
|
+
case "-creator":
|
729
|
+
case "-edited-by":
|
730
|
+
case "-version":
|
731
|
+
case "-charset":
|
732
|
+
var subCmd = arr.shift();
|
733
|
+
tune.addMetaText(cmd+subCmd, arr.join(' '));
|
734
|
+
break;
|
735
|
+
default:
|
736
|
+
return "Unknown directive: " + cmd+arr[0];
|
737
|
+
}
|
420
738
|
break;
|
421
739
|
case "header":
|
422
740
|
case "footer":
|
423
741
|
var footerStr = tokenizer.getMeat(restOfString, 0, restOfString.length);
|
424
742
|
footerStr = restOfString.substring(footerStr.start, footerStr.end);
|
425
743
|
if (footerStr.charAt(0) === '"' && footerStr.charAt(footerStr.length-1) === '"' )
|
426
|
-
footerStr = footerStr.substring(1, footerStr.length-
|
744
|
+
footerStr = footerStr.substring(1, footerStr.length-1);
|
427
745
|
var footerArr = footerStr.split('\t');
|
428
746
|
var footer = {};
|
429
747
|
if (footerArr.length === 1)
|
@@ -432,8 +750,8 @@ window.ABCJS.parse.parseDirective = {};
|
|
432
750
|
footer = { left: footerArr[0], center: footerArr[1], right: "" };
|
433
751
|
else
|
434
752
|
footer = { left: footerArr[0], center: footerArr[1], right: footerArr[2] };
|
435
|
-
|
436
|
-
|
753
|
+
if (footerArr.length > 3)
|
754
|
+
warn("Too many tabs in " + cmd + ": " + footerArr.length + " found.", restOfString, 0);
|
437
755
|
|
438
756
|
tune.addMetaTextObj(cmd, footer);
|
439
757
|
break;
|
@@ -542,5 +860,28 @@ window.ABCJS.parse.parseDirective = {};
|
|
542
860
|
}
|
543
861
|
return null;
|
544
862
|
};
|
545
|
-
|
863
|
+
window.ABCJS.parse.parseDirective.globalFormatting = function(formatHash) {
|
864
|
+
for (var cmd in formatHash) {
|
865
|
+
if (formatHash.hasOwnProperty(cmd)) {
|
866
|
+
var value = ''+formatHash[cmd];
|
867
|
+
var tokens = tokenizer.tokenize(value, 0, value.length);
|
868
|
+
var scratch;
|
869
|
+
switch (cmd) {
|
870
|
+
case "titlefont":
|
871
|
+
case "gchordfont":
|
872
|
+
getChangingFont(cmd, tokens, value);
|
873
|
+
break;
|
874
|
+
case "scale":
|
875
|
+
setScale(cmd, tokens);
|
876
|
+
break;
|
877
|
+
case "partsbox":
|
878
|
+
scratch = addMultilineVarBool('partsBox', cmd, tokens);
|
879
|
+
if (scratch !== null) warn(scratch);
|
880
|
+
break;
|
881
|
+
default:
|
882
|
+
warn("Formatting directive unrecognized: ", cmd, 0);
|
883
|
+
}
|
884
|
+
}
|
885
|
+
}
|
886
|
+
};
|
546
887
|
})();
|