abcjs-rails 1.11 → 2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
})();
|