abcjs-rails 2.0 → 2.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.
- 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
|
-
};
|