abcjs-rails 2.0 → 2.1
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 +0 -19
- data/app/assets/javascripts/abcjs/api/abc_tunebook.js +0 -5
- data/app/assets/javascripts/abcjs/edit/abc_editor.js +0 -10
- data/app/assets/javascripts/abcjs/parse/abc_parse.js +11 -35
- data/app/assets/javascripts/abcjs/parse/abc_parse_directive.js +2 -18
- data/app/assets/javascripts/abcjs/write/abc_absolute_element.js +9 -25
- data/app/assets/javascripts/abcjs/write/abc_abstract_engraver.js +21 -16
- data/app/assets/javascripts/abcjs/write/abc_beam_element.js +5 -94
- data/app/assets/javascripts/abcjs/write/abc_crescendo_element.js +0 -16
- data/app/assets/javascripts/abcjs/write/abc_decoration.js +3 -2
- data/app/assets/javascripts/abcjs/write/abc_dynamic_decoration.js +0 -8
- data/app/assets/javascripts/abcjs/write/abc_ending_element.js +0 -20
- data/app/assets/javascripts/abcjs/write/abc_engraver_controller.js +1 -1
- data/app/assets/javascripts/abcjs/write/abc_relative_element.js +9 -46
- data/app/assets/javascripts/abcjs/write/abc_renderer.js +1 -1
- data/app/assets/javascripts/abcjs/write/abc_staff_group_element.js +4 -67
- data/app/assets/javascripts/abcjs/write/abc_tie_element.js +0 -24
- data/app/assets/javascripts/abcjs/write/abc_triplet_element.js +0 -54
- data/app/assets/javascripts/abcjs/write/abc_voice_element.js +24 -13
- data/lib/abcjs-rails/version.rb +1 -1
- metadata +2 -4
- data/app/assets/javascripts/abcjs/write/abc_layout.js +0 -1040
- data/app/assets/javascripts/abcjs/write/abc_write.js +0 -535
@@ -1,535 +0,0 @@
|
|
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, Raphael */
|
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
|
-
// HACK-PER: Raphael doesn't support setting the class of an element, so this adds that support. This doesn't work on IE8 or less, though.
|
54
|
-
this.usingSvg = (window.SVGAngle || document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") ? true : false); // Same test Raphael uses
|
55
|
-
if (this.usingSvg && params.add_classes)
|
56
|
-
Raphael._availableAttrs['class'] = "";
|
57
|
-
Raphael._availableAttrs['text-decoration'] = "";
|
58
|
-
};
|
59
|
-
|
60
|
-
ABCJS.write.Printer.prototype.addClasses = function (c) {
|
61
|
-
var ret = [];
|
62
|
-
if (c.length > 0) ret.push(c);
|
63
|
-
if (this.lineNumber !== null) ret.push("l"+this.lineNumber);
|
64
|
-
if (this.measureNumber !== null) ret.push("m"+this.measureNumber);
|
65
|
-
return ret.join(' ');
|
66
|
-
};
|
67
|
-
|
68
|
-
// notify all listeners that a graphical element has been selected
|
69
|
-
ABCJS.write.Printer.prototype.notifySelect = function (abselem) {
|
70
|
-
this.clearSelection();
|
71
|
-
this.selected = [abselem];
|
72
|
-
abselem.highlight();
|
73
|
-
for (var i=0; i<this.listeners.length;i++) {
|
74
|
-
this.listeners[i].highlight(abselem.abcelem);
|
75
|
-
}
|
76
|
-
};
|
77
|
-
|
78
|
-
ABCJS.write.Printer.prototype.notifyChange = function (abselem) {
|
79
|
-
for (var i=0; i<this.listeners.length;i++) {
|
80
|
-
this.listeners[i].modelChanged();
|
81
|
-
}
|
82
|
-
};
|
83
|
-
|
84
|
-
ABCJS.write.Printer.prototype.clearSelection = function () {
|
85
|
-
for (var i=0;i<this.selected.length;i++) {
|
86
|
-
this.selected[i].unhighlight();
|
87
|
-
}
|
88
|
-
this.selected = [];
|
89
|
-
};
|
90
|
-
|
91
|
-
ABCJS.write.Printer.prototype.addSelectListener = function (listener) {
|
92
|
-
this.listeners[this.listeners.length] = listener;
|
93
|
-
};
|
94
|
-
|
95
|
-
ABCJS.write.Printer.prototype.rangeHighlight = function(start,end)
|
96
|
-
{
|
97
|
-
this.clearSelection();
|
98
|
-
for (var line=0;line<this.staffgroups.length; line++) {
|
99
|
-
var voices = this.staffgroups[line].voices;
|
100
|
-
for (var voice=0;voice<voices.length;voice++) {
|
101
|
-
var elems = voices[voice].children;
|
102
|
-
for (var elem=0; elem<elems.length; elem++) {
|
103
|
-
// Since the user can highlight more than an element, or part of an element, a hit is if any of the endpoints
|
104
|
-
// is inside the other range.
|
105
|
-
var elStart = elems[elem].abcelem.startChar;
|
106
|
-
var elEnd = elems[elem].abcelem.endChar;
|
107
|
-
if ((end>elStart && start<elEnd) || ((end===start) && end===elEnd)) {
|
108
|
-
// if (elems[elem].abcelem.startChar>=start && elems[elem].abcelem.endChar<=end) {
|
109
|
-
this.selected[this.selected.length]=elems[elem];
|
110
|
-
elems[elem].highlight();
|
111
|
-
}
|
112
|
-
}
|
113
|
-
}
|
114
|
-
}
|
115
|
-
};
|
116
|
-
|
117
|
-
ABCJS.write.Printer.prototype.beginGroup = function () {
|
118
|
-
this.path = [];
|
119
|
-
this.lastM = [0,0];
|
120
|
-
this.ingroup = true;
|
121
|
-
};
|
122
|
-
|
123
|
-
ABCJS.write.Printer.prototype.addPath = function (path) {
|
124
|
-
path = path || [];
|
125
|
-
if (path.length===0) return;
|
126
|
-
path[0][0]="m";
|
127
|
-
path[0][1]-=this.lastM[0];
|
128
|
-
path[0][2]-=this.lastM[1];
|
129
|
-
this.lastM[0]+=path[0][1];
|
130
|
-
this.lastM[1]+=path[0][2];
|
131
|
-
this.path.push(path[0]);
|
132
|
-
for (var i=1,ii=path.length;i<ii;i++) {
|
133
|
-
if (path[i][0]==="m") {
|
134
|
-
this.lastM[0]+=path[i][1];
|
135
|
-
this.lastM[1]+=path[i][2];
|
136
|
-
}
|
137
|
-
this.path.push(path[i]);
|
138
|
-
}
|
139
|
-
};
|
140
|
-
|
141
|
-
ABCJS.write.Printer.prototype.endGroup = function (klass) {
|
142
|
-
this.ingroup = false;
|
143
|
-
if (this.path.length===0) return null;
|
144
|
-
var ret = this.paper.path().attr({path:this.path, stroke:"none", fill:"#000000", 'class': this.addClasses(klass)});
|
145
|
-
if (this.scale!==1) {
|
146
|
-
ret.scale(this.scale, this.scale, 0, 0);
|
147
|
-
}
|
148
|
-
return ret;
|
149
|
-
};
|
150
|
-
|
151
|
-
ABCJS.write.Printer.prototype.printStaveLine = function (x1,x2, pitch) {
|
152
|
-
var isIE=/*@cc_on!@*/false;//IE detector
|
153
|
-
var dy = 0.35;
|
154
|
-
var fill = "#000000";
|
155
|
-
if (isIE) {
|
156
|
-
dy = 1;
|
157
|
-
fill = "#666666";
|
158
|
-
}
|
159
|
-
var y = this.calcY(pitch);
|
160
|
-
var pathString = ABCJS.write.sprintf("M %f %f L %f %f L %f %f L %f %f z", x1, y-dy, x2, y-dy,
|
161
|
-
x2, y+dy, x1, y+dy);
|
162
|
-
var ret = this.paper.path().attr({path:pathString, stroke:"none", fill:fill, 'class': this.addClasses('staff')}).toBack();
|
163
|
-
if (this.scale!==1) {
|
164
|
-
ret.scale(this.scale, this.scale, 0, 0);
|
165
|
-
}
|
166
|
-
return ret;
|
167
|
-
};
|
168
|
-
|
169
|
-
ABCJS.write.Printer.prototype.printStem = function (x, dx, y1, y2) {
|
170
|
-
if (dx<0) { // correct path "handedness" for intersection with other elements
|
171
|
-
var tmp = y2;
|
172
|
-
y2 = y1;
|
173
|
-
y1 = tmp;
|
174
|
-
}
|
175
|
-
var isIE=/*@cc_on!@*/false;//IE detector
|
176
|
-
var fill = "#000000";
|
177
|
-
if (isIE && dx<1) {
|
178
|
-
dx = 1;
|
179
|
-
fill = "#666666";
|
180
|
-
}
|
181
|
-
if (~~x === x) x+=0.05; // raphael does weird rounding (for VML)
|
182
|
-
var pathArray = [["M",x,y1],["L", x, y2],["L", x+dx, y2],["L",x+dx,y1],["z"]];
|
183
|
-
if (!isIE && this.ingroup) {
|
184
|
-
this.addPath(pathArray);
|
185
|
-
} else {
|
186
|
-
var ret = this.paper.path().attr({path:pathArray, stroke:"none", fill:fill, 'class': this.addClasses('stem')}).toBack();
|
187
|
-
if (this.scale!==1) {
|
188
|
-
ret.scale(this.scale, this.scale, 0, 0);
|
189
|
-
}
|
190
|
-
return ret;
|
191
|
-
}
|
192
|
-
};
|
193
|
-
|
194
|
-
// assumes this.y is set appropriately
|
195
|
-
// if symbol is a multichar string without a . (as in scripts.staccato) 1 symbol per char is assumed
|
196
|
-
// not scaled if not in printgroup
|
197
|
-
ABCJS.write.Printer.prototype.printSymbol = function(x, offset, symbol, scalex, scaley, klass) {
|
198
|
-
var el;
|
199
|
-
if (!symbol) return null;
|
200
|
-
if (symbol.length>0 && symbol.indexOf(".")<0) {
|
201
|
-
var elemset = this.paper.set();
|
202
|
-
var dx =0;
|
203
|
-
for (var i=0; i<symbol.length; i++) {
|
204
|
-
var ycorr = this.glyphs.getYCorr(symbol.charAt(i));
|
205
|
-
el = this.glyphs.printSymbol(x+dx, this.calcY(offset+ycorr), symbol.charAt(i), this.paper, klass);
|
206
|
-
if (el) {
|
207
|
-
elemset.push(el);
|
208
|
-
dx+=this.glyphs.getSymbolWidth(symbol.charAt(i));
|
209
|
-
} else {
|
210
|
-
this.renderText(x, this.y, "no symbol:" +symbol, "debugfont", 'debug-msg', 'start');
|
211
|
-
}
|
212
|
-
}
|
213
|
-
if (this.scale!==1) {
|
214
|
-
elemset.scale(this.scale, this.scale, 0, 0);
|
215
|
-
}
|
216
|
-
return elemset;
|
217
|
-
} else {
|
218
|
-
var ycorr = this.glyphs.getYCorr(symbol);
|
219
|
-
if (this.ingroup) {
|
220
|
-
this.addPath(this.glyphs.getPathForSymbol(x, this.calcY(offset+ycorr), symbol, scalex, scaley));
|
221
|
-
} else {
|
222
|
-
el = this.glyphs.printSymbol(x, this.calcY(offset+ycorr), symbol, this.paper, klass);
|
223
|
-
if (el) {
|
224
|
-
if (this.scale!==1) {
|
225
|
-
el.scale(this.scale, this.scale, 0, 0);
|
226
|
-
}
|
227
|
-
return el;
|
228
|
-
} else
|
229
|
-
this.renderText(x, this.y, "no symbol:" +symbol, "debugfont", 'debug-msg', 'start');
|
230
|
-
}
|
231
|
-
return null;
|
232
|
-
}
|
233
|
-
};
|
234
|
-
|
235
|
-
ABCJS.write.Printer.prototype.printPath = function (attrs) {
|
236
|
-
var ret = this.paper.path().attr(attrs);
|
237
|
-
if (this.scale!==1) ret.scale(this.scale, this.scale, 0, 0);
|
238
|
-
return ret;
|
239
|
-
};
|
240
|
-
|
241
|
-
ABCJS.write.Printer.prototype.drawArc = function(x1, x2, pitch1, pitch2, above) {
|
242
|
-
|
243
|
-
|
244
|
-
x1 = x1 + 6;
|
245
|
-
x2 = x2 + 4;
|
246
|
-
pitch1 = pitch1 + ((above)?1.5:-1.5);
|
247
|
-
pitch2 = pitch2 + ((above)?1.5:-1.5);
|
248
|
-
var y1 = this.calcY(pitch1);
|
249
|
-
var y2 = this.calcY(pitch2);
|
250
|
-
|
251
|
-
//unit direction vector
|
252
|
-
var dx = x2-x1;
|
253
|
-
var dy = y2-y1;
|
254
|
-
var norm= Math.sqrt(dx*dx+dy*dy);
|
255
|
-
var ux = dx/norm;
|
256
|
-
var uy = dy/norm;
|
257
|
-
|
258
|
-
var flatten = norm/3.5;
|
259
|
-
var curve = ((above)?-1:1)*Math.min(25, Math.max(4, flatten));
|
260
|
-
|
261
|
-
var controlx1 = x1+flatten*ux-curve*uy;
|
262
|
-
var controly1 = y1+flatten*uy+curve*ux;
|
263
|
-
var controlx2 = x2-flatten*ux-curve*uy;
|
264
|
-
var controly2 = y2-flatten*uy+curve*ux;
|
265
|
-
var thickness = 2;
|
266
|
-
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,
|
267
|
-
controlx1, controly1, controlx2, controly2, x2, y2,
|
268
|
-
controlx2-thickness*uy, controly2+thickness*ux, controlx1-thickness*uy, controly1+thickness*ux, x1, y1);
|
269
|
-
var ret = this.paper.path().attr({path:pathString, stroke:"none", fill:"#000000", 'class': this.addClasses('slur')});
|
270
|
-
if (this.scale!==1) {
|
271
|
-
ret.scale(this.scale, this.scale, 0, 0);
|
272
|
-
}
|
273
|
-
return ret;
|
274
|
-
};
|
275
|
-
|
276
|
-
ABCJS.write.Printer.prototype.renderText = function(x, y, text, type, klass, anchor) {
|
277
|
-
var font = this.abctune.formatting[type];
|
278
|
-
if (!font)
|
279
|
-
font = { face: "Arial", size: 12, decoration: "underline", style: "normal", weight: "normal" };
|
280
|
-
var attr = {"font-size": font.size*this.scale,
|
281
|
-
"font-family": font.face, 'font-weight': font.weight, 'text-decoration': font.decoration,
|
282
|
-
'class': this.addClasses(klass) };
|
283
|
-
if (anchor)
|
284
|
-
attr["text-anchor"] = anchor;
|
285
|
-
return this.paper.text(x, y*this.scale, text).attr(attr);
|
286
|
-
};
|
287
|
-
|
288
|
-
ABCJS.write.Printer.prototype.calcY = function(ofs) {
|
289
|
-
return this.y+((ABCJS.write.spacing.TOPNOTE-ofs)*ABCJS.write.spacing.STEP);
|
290
|
-
};
|
291
|
-
|
292
|
-
ABCJS.write.Printer.prototype.printStave = function (startx, endx, numLines) { // PER: print out requested number of lines
|
293
|
-
// If there is one line, it is the B line. Otherwise, the bottom line is the E line.
|
294
|
-
if (numLines === 1) {
|
295
|
-
this.printStaveLine(startx,endx,6);
|
296
|
-
return;
|
297
|
-
}
|
298
|
-
for (var i = 0; i < numLines; i++) {
|
299
|
-
this.printStaveLine(startx,endx,(i+1)*2);
|
300
|
-
}
|
301
|
-
// this.printStaveLine(startx,endx,2);
|
302
|
-
// this.printStaveLine(startx,endx,4);
|
303
|
-
// this.printStaveLine(startx,endx,6);
|
304
|
-
// this.printStaveLine(startx,endx,8);
|
305
|
-
// this.printStaveLine(startx,endx,10);
|
306
|
-
};
|
307
|
-
|
308
|
-
ABCJS.write.Printer.prototype.printABC = function(abctunes) {
|
309
|
-
if (abctunes[0]===undefined) {
|
310
|
-
abctunes = [abctunes];
|
311
|
-
}
|
312
|
-
this.y=0;
|
313
|
-
|
314
|
-
for (var i = 0; i < abctunes.length; i++) {
|
315
|
-
this.printTune(abctunes[i]);
|
316
|
-
}
|
317
|
-
|
318
|
-
};
|
319
|
-
|
320
|
-
ABCJS.write.Printer.prototype.printTempo = function (tempo, paper, layouter, y, printer, x) {
|
321
|
-
if (tempo.preString) {
|
322
|
-
var text = this.renderText(x, this.y+20, tempo.preString, 'tempofont', 'tempo',"start");
|
323
|
-
x += (text.getBBox().width + 20*printer.scale);
|
324
|
-
}
|
325
|
-
if (tempo.duration) {
|
326
|
-
var temposcale = 0.75*printer.scale;
|
327
|
-
var tempopitch = 14.5;
|
328
|
-
var duration = tempo.duration[0]; // TODO when multiple durations
|
329
|
-
var abselem = new ABCJS.write.AbsoluteElement(tempo, duration, 1, 'tempo');
|
330
|
-
var durlog = Math.floor(Math.log(duration) / Math.log(2));
|
331
|
-
var dot = 0;
|
332
|
-
for (var tot = Math.pow(2, durlog), inc = tot / 2; tot < duration; dot++, tot += inc, inc /= 2);
|
333
|
-
var c = layouter.chartable.note[-durlog];
|
334
|
-
var flag = layouter.chartable.uflags[-durlog];
|
335
|
-
var temponote = layouter.printNoteHead(abselem,
|
336
|
-
c,
|
337
|
-
{verticalPos:tempopitch},
|
338
|
-
"up",
|
339
|
-
0,
|
340
|
-
0,
|
341
|
-
flag,
|
342
|
-
dot,
|
343
|
-
0,
|
344
|
-
temposcale
|
345
|
-
);
|
346
|
-
abselem.addHead(temponote);
|
347
|
-
if (duration < 1) {
|
348
|
-
var p1 = tempopitch + 1 / 3 * temposcale;
|
349
|
-
var p2 = tempopitch + 7 * temposcale;
|
350
|
-
var dx = temponote.dx + temponote.w;
|
351
|
-
var width = -0.6*printer.scale;
|
352
|
-
abselem.addExtra(new ABCJS.write.RelativeElement(null, dx, 0, p1, {"type":"stem", "pitch2":p2, linewidth:width}));
|
353
|
-
}
|
354
|
-
abselem.x = x*(1/printer.scale); // TODO-PER: For some reason it scales this element twice, so just compensate.
|
355
|
-
abselem.draw(printer, null);
|
356
|
-
x += (abselem.w + 5*printer.scale);
|
357
|
-
text = this.renderText(x, this.y+20, "= " + tempo.bpm, 'tempofont', 'tempo',"start");
|
358
|
-
x += text.getBBox().width + 10*printer.scale;
|
359
|
-
}
|
360
|
-
if (tempo.postString) {
|
361
|
-
this.renderText(x, this.y+20, tempo.postString, 'tempofont', 'tempo',"start");
|
362
|
-
}
|
363
|
-
y += 15*printer.scale;
|
364
|
-
return y;
|
365
|
-
};
|
366
|
-
|
367
|
-
ABCJS.write.Printer.prototype.printTune = function (abctune) {
|
368
|
-
this.lineNumber = null;
|
369
|
-
this.abctune = abctune;
|
370
|
-
this.measureNumber = null;
|
371
|
-
this.layouter = new ABCJS.write.Layout(this.glyphs, abctune.formatting.bagpipes);
|
372
|
-
this.layouter.printer = this; // TODO-PER: this is a hack to get access, but it tightens the coupling.
|
373
|
-
if (abctune.media === 'print') {
|
374
|
-
// TODO create the page the size of
|
375
|
-
// tune.formatting.pageheight by tune.formatting.pagewidth
|
376
|
-
// create margins the size of
|
377
|
-
// TODO-PER: setting the defaults to 3/4" for now. What is the real value?
|
378
|
-
var m = abctune.formatting.topmargin === undefined ? 54 : abctune.formatting.topmargin;
|
379
|
-
this.y+=m;
|
380
|
-
// TODO tune.formatting.botmargin
|
381
|
-
// m = abctune.formatting.leftmargin === undefined ? 54 : abctune.formatting.leftmargin;
|
382
|
-
// this.paddingleft = m;
|
383
|
-
// m = abctune.formatting.rightmargin === undefined ? 54 : abctune.formatting.rightmargin;
|
384
|
-
// this.paddingright = m;
|
385
|
-
}
|
386
|
-
else
|
387
|
-
this.y+=this.paddingtop;
|
388
|
-
if (abctune.formatting.staffwidth) {
|
389
|
-
this.width=abctune.formatting.staffwidth;
|
390
|
-
} else {
|
391
|
-
this.width=this.staffwidth;
|
392
|
-
}
|
393
|
-
this.width+=this.paddingleft;
|
394
|
-
if (abctune.formatting.scale) { this.scale=abctune.formatting.scale; }
|
395
|
-
if (abctune.metaText.title)
|
396
|
-
this.renderText(this.width/2, this.y, abctune.metaText.title, 'titlefont', 'title meta-top');
|
397
|
-
this.y+=20*this.scale;
|
398
|
-
if (abctune.lines[0] && abctune.lines[0].subtitle) {
|
399
|
-
this.printSubtitleLine(abctune.lines[0]);
|
400
|
-
this.y+=20*this.scale;
|
401
|
-
}
|
402
|
-
if (abctune.metaText.rhythm) {
|
403
|
-
this.renderText(this.paddingleft, this.y, abctune.metaText.rhythm, 'infofont', 'meta-top', "start");
|
404
|
-
if (!abctune.metaText.author && !abctune.metaText.origin && !abctune.metaText.composer)
|
405
|
-
this.y+=15*this.scale;
|
406
|
-
}
|
407
|
-
var composerLine = "";
|
408
|
-
if (abctune.metaText.composer) composerLine += abctune.metaText.composer;
|
409
|
-
if (abctune.metaText.origin) composerLine += ' (' + abctune.metaText.origin + ')';
|
410
|
-
if (composerLine.length > 0) {
|
411
|
-
this.renderText(this.width, this.y, composerLine, 'composerfont', 'meta-top', "end");
|
412
|
-
this.y+=15;
|
413
|
-
}
|
414
|
-
if (abctune.metaText.author) {
|
415
|
-
this.renderText(this.width, this.y, abctune.metaText.author, 'composerfont', 'meta-top', "end");
|
416
|
-
this.y+=15;
|
417
|
-
}
|
418
|
-
if (abctune.metaText.tempo && !abctune.metaText.tempo.suppress) {
|
419
|
-
this.y = this.printTempo(abctune.metaText.tempo, this.paper, this.layouter, this.y, this, 50, -1);
|
420
|
-
this.y += 20*this.scale;
|
421
|
-
}
|
422
|
-
this.staffgroups = [];
|
423
|
-
var text2;
|
424
|
-
var maxwidth = this.width;
|
425
|
-
for(var line=0; line<abctune.lines.length; line++) {
|
426
|
-
this.lineNumber = line;
|
427
|
-
var abcline = abctune.lines[line];
|
428
|
-
if (abcline.staff) {
|
429
|
-
staffgroup = this.printStaffLine(abctune, abcline, line);
|
430
|
-
if (staffgroup.w > maxwidth) maxwidth = staffgroup.w;
|
431
|
-
} else if (abcline.subtitle && line!==0) {
|
432
|
-
this.printSubtitleLine(abcline);
|
433
|
-
this.y+=20*this.scale; //hardcoded
|
434
|
-
} else if (abcline.text) {
|
435
|
-
if (typeof abcline.text === 'string')
|
436
|
-
text2 = this.renderText(this.paddingleft, this.y, abcline.text, "textfont", 'defined-text', "start");
|
437
|
-
else {
|
438
|
-
var str = "";
|
439
|
-
for (var i = 0; i < abcline.text.length; i++) {
|
440
|
-
str += " FONT " + abcline.text[i].text;
|
441
|
-
}
|
442
|
-
text2 = this.renderText(this.paddingleft, this.y, str, "textfont", 'defined-text', "start");
|
443
|
-
}
|
444
|
-
this.y += text2.getBBox().height + 10 * this.scale;
|
445
|
-
}
|
446
|
-
}
|
447
|
-
this.lineNumber = null;
|
448
|
-
this.measureNumber = null;
|
449
|
-
if (abctune.metaText.partOrder) {
|
450
|
-
text2 = this.renderText(this.paddingleft, this.y, "Part Order: " + abctune.metaText.partOrder, 'partsfont', 'meta-bottom');
|
451
|
-
this.y += text2.getBBox().height + 10 * this.scale;
|
452
|
-
}
|
453
|
-
var extraText = "";
|
454
|
-
if (abctune.metaText.unalignedWords) {
|
455
|
-
for (var j = 0; j < abctune.metaText.unalignedWords.length; j++) {
|
456
|
-
if (typeof abctune.metaText.unalignedWords[j] === 'string')
|
457
|
-
extraText += abctune.metaText.unalignedWords[j] + "\n";
|
458
|
-
else {
|
459
|
-
for (var k = 0; k < abctune.metaText.unalignedWords[j].length; k++) {
|
460
|
-
extraText += " FONT " + abctune.metaText.unalignedWords[j][k].text;
|
461
|
-
}
|
462
|
-
extraText += "\n";
|
463
|
-
}
|
464
|
-
}
|
465
|
-
text2 = this.renderText(this.paddingleft + 50, this.y, extraText, 'wordsfont', 'meta-bottom', "start");
|
466
|
-
this.y += text2.getBBox().height + 10 * this.scale;
|
467
|
-
extraText = "";
|
468
|
-
}
|
469
|
-
if (abctune.metaText.book) extraText += "Book: " + abctune.metaText.book + "\n";
|
470
|
-
if (abctune.metaText.source) extraText += "Source: " + abctune.metaText.source + "\n";
|
471
|
-
if (abctune.metaText.discography) extraText += "Discography: " + abctune.metaText.discography + "\n";
|
472
|
-
if (abctune.metaText.notes) extraText += "Notes: " + abctune.metaText.notes + "\n";
|
473
|
-
if (abctune.metaText.transcription) extraText += "Transcription: " + abctune.metaText.transcription + "\n";
|
474
|
-
if (abctune.metaText.history) extraText += "History: " + abctune.metaText.history + "\n";
|
475
|
-
if (abctune.metaText['abc-copyright']) extraText += "Copyright: " + abctune.metaText['abc-copyright'] + "\n";
|
476
|
-
if (abctune.metaText['abc-creator']) extraText += "Creator: " + abctune.metaText['abc-creator'] + "\n";
|
477
|
-
if (abctune.metaText['abc-edited-by']) extraText += "Edited By: " + abctune.metaText['abc-edited-by'] + "\n";
|
478
|
-
text2 = this.renderText(this.paddingleft, this.y, extraText, 'historyfont', 'meta-bottom', "start");
|
479
|
-
this.y += text2.getBBox().height + 10 * this.scale;
|
480
|
-
var sizetoset = {w: (maxwidth+this.paddingright)*this.scale,h: (this.y+this.paddingbottom)*this.scale};
|
481
|
-
this.paper.setSize(sizetoset.w,sizetoset.h);
|
482
|
-
// Correct for IE problem in calculating height
|
483
|
-
var isIE=/*@cc_on!@*/false;//IE detector
|
484
|
-
if (isIE) {
|
485
|
-
this.paper.canvas.parentNode.style.width=sizetoset.w+"px";
|
486
|
-
this.paper.canvas.parentNode.style.height=""+sizetoset.h+"px";
|
487
|
-
} else
|
488
|
-
this.paper.canvas.parentNode.setAttribute("style","width:"+sizetoset.w+"px");
|
489
|
-
};
|
490
|
-
|
491
|
-
ABCJS.write.Printer.prototype.printSubtitleLine = function(abcline) {
|
492
|
-
this.renderText(this.width/2, this.y, abcline.subtitle, "subtitlefont", 'text meta-top');
|
493
|
-
};
|
494
|
-
|
495
|
-
function centerWholeRests(voices) {
|
496
|
-
// whole rests are a special case: if they are by themselves in a measure, then they should be centered.
|
497
|
-
// (If they are not by themselves, that is probably a user error, but we'll just center it between the two items to either side of it.)
|
498
|
-
for (var i = 0; i < voices.length; i++) {
|
499
|
-
var voice = voices[i];
|
500
|
-
// Look through all of the elements except for the first and last. If the whole note appears there then there isn't anything to center it between anyway.
|
501
|
-
for (var j = 1; j < voice.children.length-1; j++) {
|
502
|
-
var absElem = voice.children[j];
|
503
|
-
if (absElem.abcelem.rest && absElem.abcelem.rest.type === 'whole') {
|
504
|
-
var before = voice.children[j-1];
|
505
|
-
var after = voice.children[j+1];
|
506
|
-
var midpoint = (after.x - before.x) / 2 + before.x;
|
507
|
-
absElem.x = midpoint - absElem.w / 2;
|
508
|
-
|
509
|
-
}
|
510
|
-
}
|
511
|
-
}
|
512
|
-
}
|
513
|
-
|
514
|
-
ABCJS.write.Printer.prototype.printStaffLine = function (abctune, abcline, line) {
|
515
|
-
var staffgroup = this.layouter.printABCLine(abcline.staff);
|
516
|
-
var newspace = this.space;
|
517
|
-
for (var it = 0; it < 3; it++) { // TODO shouldn't need this triple pass any more
|
518
|
-
staffgroup.layout(newspace, this, false);
|
519
|
-
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
|
520
|
-
var relspace = staffgroup.spacingunits * newspace;
|
521
|
-
var constspace = staffgroup.w - relspace;
|
522
|
-
if (staffgroup.spacingunits > 0) {
|
523
|
-
newspace = (this.width - constspace) / staffgroup.spacingunits;
|
524
|
-
if (newspace * staffgroup.minspace > 50) {
|
525
|
-
newspace = 50 / staffgroup.minspace;
|
526
|
-
}
|
527
|
-
}
|
528
|
-
}
|
529
|
-
centerWholeRests(staffgroup.voices);
|
530
|
-
staffgroup.draw(this, this.y);
|
531
|
-
this.staffgroups[this.staffgroups.length] = staffgroup;
|
532
|
-
this.y = staffgroup.y + staffgroup.height;
|
533
|
-
this.y += ABCJS.write.spacing.STAVEHEIGHT * 0.2;
|
534
|
-
return staffgroup;
|
535
|
-
};
|