abcjs-rails 1.1.0 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/app/assets/javascripts/abcjs-rails.js +1 -0
- data/app/assets/javascripts/abcjs/api/abc_tunebook.js +158 -0
- data/app/assets/javascripts/abcjs/data/abc_tune.js +686 -0
- data/app/assets/javascripts/abcjs/edit/abc_editor.js +414 -0
- data/app/assets/javascripts/abcjs/midi/abc_midiwriter.js +698 -0
- data/app/assets/javascripts/abcjs/parse/abc_common.js +76 -0
- data/app/assets/javascripts/abcjs/parse/abc_parse.js +1385 -0
- data/app/assets/javascripts/abcjs/parse/abc_parse_directive.js +546 -0
- data/app/assets/javascripts/abcjs/parse/abc_parse_header.js +521 -0
- data/app/assets/javascripts/abcjs/parse/abc_parse_key_voice.js +781 -0
- data/app/assets/javascripts/abcjs/parse/abc_tokenizer.js +751 -0
- data/app/assets/javascripts/abcjs/write/abc_glyphs.js +105 -0
- data/app/assets/javascripts/abcjs/write/abc_graphelements.js +781 -0
- data/app/assets/javascripts/abcjs/write/abc_layout.js +959 -0
- data/app/assets/javascripts/abcjs/write/abc_write.js +487 -0
- data/app/assets/javascripts/abcjs/write/raphael.js +3395 -0
- data/app/assets/javascripts/abcjs/write/sprintf.js +61 -0
- data/lib/abcjs-rails/version.rb +1 -1
- metadata +18 -1
@@ -0,0 +1,487 @@
|
|
1
|
+
// abc_write.js: Prints an abc file parsed by abc_parse.js
|
2
|
+
// Copyright (C) 2010 Gregory Dyke (gregdyke at gmail dot com)
|
3
|
+
//
|
4
|
+
// This program is free software: you can redistribute it and/or modify
|
5
|
+
// it under the terms of the GNU General Public License as published by
|
6
|
+
// the Free Software Foundation, either version 3 of the License, or
|
7
|
+
// (at your option) any later version.
|
8
|
+
//
|
9
|
+
// This program is distributed in the hope that it will be useful,
|
10
|
+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
+
// GNU General Public License for more details.
|
13
|
+
//
|
14
|
+
// You should have received a copy of the GNU General Public License
|
15
|
+
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
16
|
+
|
17
|
+
|
18
|
+
/*global window, ABCJS, Math */
|
19
|
+
|
20
|
+
if (!window.ABCJS)
|
21
|
+
window.ABCJS = {};
|
22
|
+
|
23
|
+
if (!window.ABCJS.write)
|
24
|
+
window.ABCJS.write = {};
|
25
|
+
|
26
|
+
ABCJS.write.spacing = function() {};
|
27
|
+
ABCJS.write.spacing.FONTEM = 360;
|
28
|
+
ABCJS.write.spacing.FONTSIZE = 30;
|
29
|
+
ABCJS.write.spacing.STEP = ABCJS.write.spacing.FONTSIZE*93/720;
|
30
|
+
ABCJS.write.spacing.SPACE = 10;
|
31
|
+
ABCJS.write.spacing.TOPNOTE = 20;
|
32
|
+
ABCJS.write.spacing.STAVEHEIGHT = 100;
|
33
|
+
|
34
|
+
|
35
|
+
//--------------------------------------------------------------------PRINTER
|
36
|
+
|
37
|
+
ABCJS.write.Printer = function(paper, params) {
|
38
|
+
params = params || {};
|
39
|
+
this.y = 0;
|
40
|
+
this.paper = paper;
|
41
|
+
this.space = 3*ABCJS.write.spacing.SPACE;
|
42
|
+
this.glyphs = new ABCJS.write.Glyphs();
|
43
|
+
this.listeners = [];
|
44
|
+
this.selected = [];
|
45
|
+
this.ingroup = false;
|
46
|
+
this.scale = params.scale || 1;
|
47
|
+
this.staffwidth = params.staffwidth || 740;
|
48
|
+
this.paddingtop = params.paddingtop || 15;
|
49
|
+
this.paddingbottom = params.paddingbottom || 30;
|
50
|
+
this.paddingright = params.paddingright || 50;
|
51
|
+
this.paddingleft = params.paddingleft || 15;
|
52
|
+
this.editable = params.editable || false;
|
53
|
+
};
|
54
|
+
|
55
|
+
// notify all listeners that a graphical element has been selected
|
56
|
+
ABCJS.write.Printer.prototype.notifySelect = function (abselem) {
|
57
|
+
this.clearSelection();
|
58
|
+
this.selected = [abselem];
|
59
|
+
abselem.highlight();
|
60
|
+
for (var i=0; i<this.listeners.length;i++) {
|
61
|
+
this.listeners[i].highlight(abselem.abcelem);
|
62
|
+
}
|
63
|
+
};
|
64
|
+
|
65
|
+
ABCJS.write.Printer.prototype.notifyChange = function (abselem) {
|
66
|
+
for (var i=0; i<this.listeners.length;i++) {
|
67
|
+
this.listeners[i].modelChanged();
|
68
|
+
}
|
69
|
+
};
|
70
|
+
|
71
|
+
ABCJS.write.Printer.prototype.clearSelection = function () {
|
72
|
+
for (var i=0;i<this.selected.length;i++) {
|
73
|
+
this.selected[i].unhighlight();
|
74
|
+
}
|
75
|
+
this.selected = [];
|
76
|
+
};
|
77
|
+
|
78
|
+
ABCJS.write.Printer.prototype.addSelectListener = function (listener) {
|
79
|
+
this.listeners[this.listeners.length] = listener;
|
80
|
+
};
|
81
|
+
|
82
|
+
ABCJS.write.Printer.prototype.rangeHighlight = function(start,end)
|
83
|
+
{
|
84
|
+
this.clearSelection();
|
85
|
+
for (var line=0;line<this.staffgroups.length; line++) {
|
86
|
+
var voices = this.staffgroups[line].voices;
|
87
|
+
for (var voice=0;voice<voices.length;voice++) {
|
88
|
+
var elems = voices[voice].children;
|
89
|
+
for (var elem=0; elem<elems.length; elem++) {
|
90
|
+
// Since the user can highlight more than an element, or part of an element, a hit is if any of the endpoints
|
91
|
+
// is inside the other range.
|
92
|
+
var elStart = elems[elem].abcelem.startChar;
|
93
|
+
var elEnd = elems[elem].abcelem.endChar;
|
94
|
+
if ((end>elStart && start<elEnd) || ((end===start) && end===elEnd)) {
|
95
|
+
// if (elems[elem].abcelem.startChar>=start && elems[elem].abcelem.endChar<=end) {
|
96
|
+
this.selected[this.selected.length]=elems[elem];
|
97
|
+
elems[elem].highlight();
|
98
|
+
}
|
99
|
+
}
|
100
|
+
}
|
101
|
+
}
|
102
|
+
};
|
103
|
+
|
104
|
+
ABCJS.write.Printer.prototype.beginGroup = function () {
|
105
|
+
this.path = [];
|
106
|
+
this.lastM = [0,0];
|
107
|
+
this.ingroup = true;
|
108
|
+
};
|
109
|
+
|
110
|
+
ABCJS.write.Printer.prototype.addPath = function (path) {
|
111
|
+
path = path || [];
|
112
|
+
if (path.length===0) return;
|
113
|
+
path[0][0]="m";
|
114
|
+
path[0][1]-=this.lastM[0];
|
115
|
+
path[0][2]-=this.lastM[1];
|
116
|
+
this.lastM[0]+=path[0][1];
|
117
|
+
this.lastM[1]+=path[0][2];
|
118
|
+
this.path.push(path[0]);
|
119
|
+
for (var i=1,ii=path.length;i<ii;i++) {
|
120
|
+
if (path[i][0]==="m") {
|
121
|
+
this.lastM[0]+=path[i][1];
|
122
|
+
this.lastM[1]+=path[i][2];
|
123
|
+
}
|
124
|
+
this.path.push(path[i]);
|
125
|
+
}
|
126
|
+
};
|
127
|
+
|
128
|
+
ABCJS.write.Printer.prototype.endGroup = function () {
|
129
|
+
this.ingroup = false;
|
130
|
+
if (this.path.length===0) return null;
|
131
|
+
var ret = this.paper.path().attr({path:this.path, stroke:"none", fill:"#000000"});
|
132
|
+
if (this.scale!==1) {
|
133
|
+
ret.scale(this.scale, this.scale, 0, 0);
|
134
|
+
}
|
135
|
+
return ret;
|
136
|
+
};
|
137
|
+
|
138
|
+
ABCJS.write.Printer.prototype.printStaveLine = function (x1,x2, pitch) {
|
139
|
+
var isIE=/*@cc_on!@*/false;//IE detector
|
140
|
+
var dy = 0.35;
|
141
|
+
var fill = "#000000";
|
142
|
+
if (isIE) {
|
143
|
+
dy = 1;
|
144
|
+
fill = "#666666";
|
145
|
+
}
|
146
|
+
var y = this.calcY(pitch);
|
147
|
+
var pathString = ABCJS.write.sprintf("M %f %f L %f %f L %f %f L %f %f z", x1, y-dy, x2, y-dy,
|
148
|
+
x2, y+dy, x1, y+dy);
|
149
|
+
var ret = this.paper.path().attr({path:pathString, stroke:"none", fill:fill}).toBack();
|
150
|
+
if (this.scale!==1) {
|
151
|
+
ret.scale(this.scale, this.scale, 0, 0);
|
152
|
+
}
|
153
|
+
return ret;
|
154
|
+
};
|
155
|
+
|
156
|
+
ABCJS.write.Printer.prototype.printStem = function (x, dx, y1, y2) {
|
157
|
+
if (dx<0) { // correct path "handedness" for intersection with other elements
|
158
|
+
var tmp = y2;
|
159
|
+
y2 = y1;
|
160
|
+
y1 = tmp;
|
161
|
+
}
|
162
|
+
var isIE=/*@cc_on!@*/false;//IE detector
|
163
|
+
var fill = "#000000";
|
164
|
+
if (isIE && dx<1) {
|
165
|
+
dx = 1;
|
166
|
+
fill = "#666666";
|
167
|
+
}
|
168
|
+
if (~~x === x) x+=0.05; // raphael does weird rounding (for VML)
|
169
|
+
var pathArray = [["M",x,y1],["L", x, y2],["L", x+dx, y2],["L",x+dx,y1],["z"]];
|
170
|
+
if (!isIE && this.ingroup) {
|
171
|
+
this.addPath(pathArray);
|
172
|
+
} else {
|
173
|
+
var ret = this.paper.path().attr({path:pathArray, stroke:"none", fill:fill}).toBack();
|
174
|
+
if (this.scale!==1) {
|
175
|
+
ret.scale(this.scale, this.scale, 0, 0);
|
176
|
+
}
|
177
|
+
return ret;
|
178
|
+
}
|
179
|
+
};
|
180
|
+
|
181
|
+
ABCJS.write.Printer.prototype.printText = function (x, offset, text, anchor) {
|
182
|
+
anchor = anchor || "start";
|
183
|
+
var ret = this.paper.text(x, this.calcY(offset), text).attr({"text-anchor":anchor, "font-size":12});
|
184
|
+
if (this.scale!==1) {
|
185
|
+
ret.scale(this.scale, this.scale, 0, 0);
|
186
|
+
}
|
187
|
+
return ret;
|
188
|
+
};
|
189
|
+
|
190
|
+
// assumes this.y is set appropriately
|
191
|
+
// if symbol is a multichar string without a . (as in scripts.staccato) 1 symbol per char is assumed
|
192
|
+
// not scaled if not in printgroup
|
193
|
+
ABCJS.write.Printer.prototype.printSymbol = function(x, offset, symbol, scalex, scaley) {
|
194
|
+
var el;
|
195
|
+
if (!symbol) return null;
|
196
|
+
if (symbol.length>0 && symbol.indexOf(".")<0) {
|
197
|
+
var elemset = this.paper.set();
|
198
|
+
var dx =0;
|
199
|
+
for (var i=0; i<symbol.length; i++) {
|
200
|
+
var ycorr = this.glyphs.getYCorr(symbol.charAt(i));
|
201
|
+
el = this.glyphs.printSymbol(x+dx, this.calcY(offset+ycorr), symbol.charAt(i), this.paper);
|
202
|
+
if (el) {
|
203
|
+
elemset.push(el);
|
204
|
+
dx+=this.glyphs.getSymbolWidth(symbol.charAt(i));
|
205
|
+
} else {
|
206
|
+
this.debugMsg(x,"no symbol:" +symbol);
|
207
|
+
}
|
208
|
+
}
|
209
|
+
if (this.scale!==1) {
|
210
|
+
elemset.scale(this.scale, this.scale, 0, 0);
|
211
|
+
}
|
212
|
+
return elemset;
|
213
|
+
} else {
|
214
|
+
var ycorr = this.glyphs.getYCorr(symbol);
|
215
|
+
if (this.ingroup) {
|
216
|
+
this.addPath(this.glyphs.getPathForSymbol(x, this.calcY(offset+ycorr), symbol, scalex, scaley));
|
217
|
+
} else {
|
218
|
+
el = this.glyphs.printSymbol(x, this.calcY(offset+ycorr), symbol, this.paper);
|
219
|
+
if (el) {
|
220
|
+
if (this.scale!==1) {
|
221
|
+
el.scale(this.scale, this.scale, 0, 0);
|
222
|
+
}
|
223
|
+
return el;
|
224
|
+
} else
|
225
|
+
this.debugMsg(x,"no symbol:" +symbol);
|
226
|
+
}
|
227
|
+
return null;
|
228
|
+
}
|
229
|
+
};
|
230
|
+
|
231
|
+
ABCJS.write.Printer.prototype.printPath = function (attrs) {
|
232
|
+
var ret = this.paper.path().attr(attrs);
|
233
|
+
if (this.scale!==1) ret.scale(this.scale, this.scale, 0, 0);
|
234
|
+
return ret;
|
235
|
+
};
|
236
|
+
|
237
|
+
ABCJS.write.Printer.prototype.drawArc = function(x1, x2, pitch1, pitch2, above) {
|
238
|
+
|
239
|
+
|
240
|
+
x1 = x1 + 6;
|
241
|
+
x2 = x2 + 4;
|
242
|
+
pitch1 = pitch1 + ((above)?1.5:-1.5);
|
243
|
+
pitch2 = pitch2 + ((above)?1.5:-1.5);
|
244
|
+
var y1 = this.calcY(pitch1);
|
245
|
+
var y2 = this.calcY(pitch2);
|
246
|
+
|
247
|
+
//unit direction vector
|
248
|
+
var dx = x2-x1;
|
249
|
+
var dy = y2-y1;
|
250
|
+
var norm= Math.sqrt(dx*dx+dy*dy);
|
251
|
+
var ux = dx/norm;
|
252
|
+
var uy = dy/norm;
|
253
|
+
|
254
|
+
var flatten = norm/3.5;
|
255
|
+
var curve = ((above)?-1:1)*Math.min(25, Math.max(4, flatten));
|
256
|
+
|
257
|
+
var controlx1 = x1+flatten*ux-curve*uy;
|
258
|
+
var controly1 = y1+flatten*uy+curve*ux;
|
259
|
+
var controlx2 = x2-flatten*ux-curve*uy;
|
260
|
+
var controly2 = y2-flatten*uy+curve*ux;
|
261
|
+
var thickness = 2;
|
262
|
+
var pathString = ABCJS.write.sprintf("M %f %f C %f %f %f %f %f %f C %f %f %f %f %f %f z", x1, y1,
|
263
|
+
controlx1, controly1, controlx2, controly2, x2, y2,
|
264
|
+
controlx2-thickness*uy, controly2+thickness*ux, controlx1-thickness*uy, controly1+thickness*ux, x1, y1);
|
265
|
+
var ret = this.paper.path().attr({path:pathString, stroke:"none", fill:"#000000"});
|
266
|
+
if (this.scale!==1) {
|
267
|
+
ret.scale(this.scale, this.scale, 0, 0);
|
268
|
+
}
|
269
|
+
return ret;
|
270
|
+
};
|
271
|
+
|
272
|
+
ABCJS.write.Printer.prototype.debugMsg = function(x, msg) {
|
273
|
+
return this.paper.text(x, this.y, msg).scale(this.scale, this.scale, 0, 0);
|
274
|
+
};
|
275
|
+
|
276
|
+
ABCJS.write.Printer.prototype.debugMsgLow = function(x, msg) {
|
277
|
+
return this.paper.text(x, this.calcY(this.layouter.minY-7), msg).attr({"font-family":"serif", "font-size":12, "text-anchor":"begin"}).scale(this.scale, this.scale, 0, 0);
|
278
|
+
};
|
279
|
+
|
280
|
+
ABCJS.write.Printer.prototype.printLyrics = function(x, msg) {
|
281
|
+
var el = this.paper.text(x, this.calcY(this.layouter.minY-7), msg).attr({"font-family":"Times New Roman", "font-weight":'bold', "font-size":14, "text-anchor":"begin"}).scale(this.scale, this.scale, 0, 0);
|
282
|
+
el[0].setAttribute("class", "abc-lyric");
|
283
|
+
return el;
|
284
|
+
};
|
285
|
+
|
286
|
+
ABCJS.write.Printer.prototype.calcY = function(ofs) {
|
287
|
+
return this.y+((ABCJS.write.spacing.TOPNOTE-ofs)*ABCJS.write.spacing.STEP);
|
288
|
+
};
|
289
|
+
|
290
|
+
ABCJS.write.Printer.prototype.printStave = function (startx, endx, numLines) { // PER: print out requested number of lines
|
291
|
+
// If there is one line, it is the B line. Otherwise, the bottom line is the E line.
|
292
|
+
if (numLines === 1) {
|
293
|
+
this.printStaveLine(startx,endx,6);
|
294
|
+
return;
|
295
|
+
}
|
296
|
+
for (var i = 0; i < numLines; i++) {
|
297
|
+
this.printStaveLine(startx,endx,(i+1)*2);
|
298
|
+
}
|
299
|
+
// this.printStaveLine(startx,endx,2);
|
300
|
+
// this.printStaveLine(startx,endx,4);
|
301
|
+
// this.printStaveLine(startx,endx,6);
|
302
|
+
// this.printStaveLine(startx,endx,8);
|
303
|
+
// this.printStaveLine(startx,endx,10);
|
304
|
+
};
|
305
|
+
|
306
|
+
ABCJS.write.Printer.prototype.printABC = function(abctunes) {
|
307
|
+
if (abctunes[0]===undefined) {
|
308
|
+
abctunes = [abctunes];
|
309
|
+
}
|
310
|
+
this.y=0;
|
311
|
+
|
312
|
+
for (var i = 0; i < abctunes.length; i++) {
|
313
|
+
this.printTune(abctunes[i]);
|
314
|
+
}
|
315
|
+
|
316
|
+
};
|
317
|
+
|
318
|
+
ABCJS.write.Printer.prototype.printTempo = function (tempo, paper, layouter, y, printer, x) {
|
319
|
+
if (tempo.preString) {
|
320
|
+
var text = paper.text(x, y + 20, tempo.preString).attr({"text-anchor":"start"});
|
321
|
+
x += (text.getBBox().width + 10);
|
322
|
+
}
|
323
|
+
if (tempo.duration) {
|
324
|
+
var temposcale = 0.75;
|
325
|
+
var tempopitch = 14.5;
|
326
|
+
var duration = tempo.duration[0]; // TODO when multiple durations
|
327
|
+
var abselem = new ABCJS.write.AbsoluteElement(tempo, duration, 1);
|
328
|
+
var durlog = Math.floor(Math.log(duration) / Math.log(2));
|
329
|
+
var dot = 0;
|
330
|
+
for (var tot = Math.pow(2, durlog), inc = tot / 2; tot < duration; dot++, tot += inc, inc /= 2);
|
331
|
+
var c = layouter.chartable.note[-durlog];
|
332
|
+
var flag = layouter.chartable.uflags[-durlog];
|
333
|
+
var temponote = layouter.printNoteHead(abselem,
|
334
|
+
c,
|
335
|
+
{verticalPos:tempopitch},
|
336
|
+
"up",
|
337
|
+
0,
|
338
|
+
0,
|
339
|
+
flag,
|
340
|
+
dot,
|
341
|
+
0,
|
342
|
+
temposcale
|
343
|
+
);
|
344
|
+
abselem.addHead(temponote);
|
345
|
+
if (duration < 1) {
|
346
|
+
var p1 = tempopitch + 1 / 3 * temposcale;
|
347
|
+
var p2 = tempopitch + 7 * temposcale;
|
348
|
+
var dx = temponote.dx + temponote.w;
|
349
|
+
var width = -0.6;
|
350
|
+
abselem.addExtra(new ABCJS.write.RelativeElement(null, dx, 0, p1, {"type":"stem", "pitch2":p2, linewidth:width}));
|
351
|
+
}
|
352
|
+
abselem.x = x;
|
353
|
+
abselem.draw(printer, null);
|
354
|
+
x += (abselem.w + 5);
|
355
|
+
text = paper.text(x, y + 20, "= " + tempo.bpm).attr({"text-anchor":"start"});
|
356
|
+
x += text.getBBox().width + 10;
|
357
|
+
}
|
358
|
+
if (tempo.postString) {
|
359
|
+
paper.text(x, y + 20, tempo.postString).attr({"text-anchor":"start"});
|
360
|
+
}
|
361
|
+
y += 15;
|
362
|
+
return y;
|
363
|
+
};
|
364
|
+
|
365
|
+
ABCJS.write.Printer.prototype.printTune = function (abctune) {
|
366
|
+
this.layouter = new ABCJS.write.Layout(this.glyphs, abctune.formatting.bagpipes);
|
367
|
+
this.layouter.printer = this; // TODO-PER: this is a hack to get access, but it tightens the coupling.
|
368
|
+
if (abctune.media === 'print') {
|
369
|
+
// TODO create the page the size of
|
370
|
+
// tune.formatting.pageheight by tune.formatting.pagewidth
|
371
|
+
// create margins the size of
|
372
|
+
// TODO-PER: setting the defaults to 3/4" for now. What is the real value?
|
373
|
+
var m = abctune.formatting.topmargin === undefined ? 54 : abctune.formatting.topmargin;
|
374
|
+
this.y+=m;
|
375
|
+
// TODO tune.formatting.botmargin
|
376
|
+
// m = abctune.formatting.leftmargin === undefined ? 54 : abctune.formatting.leftmargin;
|
377
|
+
// this.paddingleft = m;
|
378
|
+
// m = abctune.formatting.rightmargin === undefined ? 54 : abctune.formatting.rightmargin;
|
379
|
+
// this.paddingright = m;
|
380
|
+
}
|
381
|
+
else
|
382
|
+
this.y+=this.paddingtop;
|
383
|
+
// FIXED BELOW, NEEDS CHECKING if (abctune.formatting.stretchlast) { this.paper.text(200, this.y, "Format: stretchlast"); this.y += 20; }
|
384
|
+
if (abctune.formatting.staffwidth) {
|
385
|
+
this.width=abctune.formatting.staffwidth;
|
386
|
+
} else {
|
387
|
+
this.width=this.staffwidth;
|
388
|
+
}
|
389
|
+
this.width+=this.paddingleft;
|
390
|
+
if (abctune.formatting.scale) { this.scale=abctune.formatting.scale; }
|
391
|
+
this.paper.text(this.width/2, this.y, abctune.metaText.title).attr({"font-size":20, "font-family":"serif"});
|
392
|
+
this.y+=20;
|
393
|
+
if (abctune.lines[0] && abctune.lines[0].subtitle) {
|
394
|
+
this.printSubtitleLine(abctune.lines[0]);
|
395
|
+
this.y+=20;
|
396
|
+
}
|
397
|
+
if (abctune.metaText.rhythm) {
|
398
|
+
this.paper.text(this.paddingleft, this.y, abctune.metaText.rhythm).attr({"text-anchor":"start","font-style":"italic","font-family":"serif", "font-size":12});
|
399
|
+
!(abctune.metaText.author || abctune.metaText.origin || abctune.metaText.composer) && (this.y+=15);
|
400
|
+
}
|
401
|
+
if (abctune.metaText.author) {this.paper.text(this.width, this.y, abctune.metaText.author).attr({"text-anchor":"end","font-style":"italic","font-family":"serif", "font-size":12}); this.y+=15;}
|
402
|
+
if (abctune.metaText.origin) {this.paper.text(this.width, this.y, "(" + abctune.metaText.origin + ")").attr({"text-anchor":"end","font-style":"italic","font-family":"serif", "font-size":12});this.y+=15;}
|
403
|
+
if (abctune.metaText.composer) {this.paper.text(this.width, this.y, abctune.metaText.composer).attr({"text-anchor":"end","font-style":"italic","font-family":"serif", "font-size":12});this.y+=15;}
|
404
|
+
if (abctune.metaText.tempo && !abctune.metaText.tempo.suppress) {
|
405
|
+
this.y = this.printTempo(abctune.metaText.tempo, this.paper, this.layouter, this.y, this, 50);
|
406
|
+
}
|
407
|
+
this.staffgroups = [];
|
408
|
+
var maxwidth = this.width;
|
409
|
+
for(var line=0; line<abctune.lines.length; line++) {
|
410
|
+
var abcline = abctune.lines[line];
|
411
|
+
if (abcline.staff) {
|
412
|
+
var staffgroup = this.layouter.printABCLine(abcline.staff);
|
413
|
+
var newspace = this.space;
|
414
|
+
for (var it=0;it<3;it++) {
|
415
|
+
staffgroup.layout(newspace,this);
|
416
|
+
if (line && line===abctune.lines.length-1 && staffgroup.w/this.width<0.66 && !abctune.formatting.stretchlast) break; // don't stretch last line too much unless it is 1st
|
417
|
+
var relspace = staffgroup.spacingunits*newspace;
|
418
|
+
var constspace = staffgroup.w-relspace;
|
419
|
+
if (staffgroup.spacingunits>0) {
|
420
|
+
newspace = (this.width-constspace)/staffgroup.spacingunits;
|
421
|
+
if (newspace*staffgroup.minspace>50) {
|
422
|
+
newspace = 50/staffgroup.minspace;
|
423
|
+
}
|
424
|
+
}
|
425
|
+
}
|
426
|
+
staffgroup.draw(this,this.y);
|
427
|
+
if (staffgroup.w>maxwidth) maxwidth = staffgroup.w;
|
428
|
+
this.staffgroups[this.staffgroups.length] = staffgroup;
|
429
|
+
this.y = staffgroup.y+staffgroup.height;
|
430
|
+
this.y+=ABCJS.write.spacing.STAVEHEIGHT*0.2;
|
431
|
+
} else if (abcline.subtitle && line!==0) {
|
432
|
+
this.printSubtitleLine(abcline);
|
433
|
+
this.y+=20; //hardcoded
|
434
|
+
} else if (abcline.text) {
|
435
|
+
if (typeof abcline.text === 'string')
|
436
|
+
this.paper.text(100, this.y, "TEXT: " + abcline.text);
|
437
|
+
else {
|
438
|
+
var str = "";
|
439
|
+
for (var i = 0; i < abcline.text.length; i++) {
|
440
|
+
str += " FONT " + abcline.text[i].text;
|
441
|
+
}
|
442
|
+
this.paper.text(100, this.y, "TEXT: " + str);
|
443
|
+
}
|
444
|
+
this.y+=20; //hardcoded
|
445
|
+
}
|
446
|
+
}
|
447
|
+
var extraText = ""; // TODO-PER: This is just an easy way to display this info for now.
|
448
|
+
if (abctune.metaText.partOrder) extraText += "Part Order: " + abctune.metaText.partOrder + "\n";
|
449
|
+
if (abctune.metaText.notes) extraText += "Notes:\n" + abctune.metaText.notes + "\n";
|
450
|
+
if (abctune.metaText.book) extraText += "Book: " + abctune.metaText.book + "\n";
|
451
|
+
if (abctune.metaText.source) extraText += "Source: " + abctune.metaText.source + "\n";
|
452
|
+
if (abctune.metaText.transcription) extraText += "Transcription: " + abctune.metaText.transcription + "\n";
|
453
|
+
if (abctune.metaText.discography) extraText += "Discography: " + abctune.metaText.discography + "\n";
|
454
|
+
if (abctune.metaText.history) extraText += "History: " + abctune.metaText.history + "\n";
|
455
|
+
if (abctune.metaText.unalignedWords) {
|
456
|
+
extraText += "Words:\n";
|
457
|
+
for (var j = 0; j < abctune.metaText.unalignedWords.length; j++) {
|
458
|
+
if (typeof abctune.metaText.unalignedWords[j] === 'string')
|
459
|
+
extraText += abctune.metaText.unalignedWords[j] + "\n";
|
460
|
+
else {
|
461
|
+
for (var k = 0; k < abctune.metaText.unalignedWords[j].length; k++) {
|
462
|
+
extraText += " FONT " + abctune.metaText.unalignedWords[j][k].text;
|
463
|
+
}
|
464
|
+
extraText += "\n";
|
465
|
+
}
|
466
|
+
}
|
467
|
+
}
|
468
|
+
var text2 = this.paper.text(this.paddingleft, this.y+25, extraText).attr({"text-anchor":"start", "font-family":"serif", "font-size":13});
|
469
|
+
var height = text2.getBBox().height;
|
470
|
+
text2.translate(0,height/2);
|
471
|
+
this.y+=25+height;
|
472
|
+
var sizetoset = {w: maxwidth*this.scale+this.paddingright,h: this.y*this.scale+this.paddingbottom};
|
473
|
+
this.paper.setSize(sizetoset.w,sizetoset.h);
|
474
|
+
// Correct for IE problem in calculating height
|
475
|
+
var isIE=/*@cc_on!@*/false;//IE detector
|
476
|
+
if (isIE) {
|
477
|
+
this.paper.canvas.parentNode.style.width=sizetoset.w+"px";
|
478
|
+
this.paper.canvas.parentNode.style.height=""+sizetoset.h+"px";
|
479
|
+
} else
|
480
|
+
this.paper.canvas.parentNode.setAttribute("style","width:"+sizetoset.w+"px");
|
481
|
+
};
|
482
|
+
|
483
|
+
ABCJS.write.Printer.prototype.printSubtitleLine = function(abcline) {
|
484
|
+
this.paper.text(this.width/2, this.y, abcline.subtitle).attr({"font-size":16}).scale(this.scale, this.scale, 0,0);
|
485
|
+
};
|
486
|
+
|
487
|
+
|