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.
Files changed (24) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/abcjs/api/abc_animation.js +0 -19
  3. data/app/assets/javascripts/abcjs/api/abc_tunebook.js +0 -5
  4. data/app/assets/javascripts/abcjs/edit/abc_editor.js +0 -10
  5. data/app/assets/javascripts/abcjs/parse/abc_parse.js +11 -35
  6. data/app/assets/javascripts/abcjs/parse/abc_parse_directive.js +2 -18
  7. data/app/assets/javascripts/abcjs/write/abc_absolute_element.js +9 -25
  8. data/app/assets/javascripts/abcjs/write/abc_abstract_engraver.js +21 -16
  9. data/app/assets/javascripts/abcjs/write/abc_beam_element.js +5 -94
  10. data/app/assets/javascripts/abcjs/write/abc_crescendo_element.js +0 -16
  11. data/app/assets/javascripts/abcjs/write/abc_decoration.js +3 -2
  12. data/app/assets/javascripts/abcjs/write/abc_dynamic_decoration.js +0 -8
  13. data/app/assets/javascripts/abcjs/write/abc_ending_element.js +0 -20
  14. data/app/assets/javascripts/abcjs/write/abc_engraver_controller.js +1 -1
  15. data/app/assets/javascripts/abcjs/write/abc_relative_element.js +9 -46
  16. data/app/assets/javascripts/abcjs/write/abc_renderer.js +1 -1
  17. data/app/assets/javascripts/abcjs/write/abc_staff_group_element.js +4 -67
  18. data/app/assets/javascripts/abcjs/write/abc_tie_element.js +0 -24
  19. data/app/assets/javascripts/abcjs/write/abc_triplet_element.js +0 -54
  20. data/app/assets/javascripts/abcjs/write/abc_voice_element.js +24 -13
  21. data/lib/abcjs-rails/version.rb +1 -1
  22. metadata +2 -4
  23. data/app/assets/javascripts/abcjs/write/abc_layout.js +0 -1040
  24. 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
- };