abcjs-rails 1.11 → 2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/javascripts/abcjs/api/abc_animation.js +41 -1
- data/app/assets/javascripts/abcjs/api/abc_tunebook.js +5 -0
- data/app/assets/javascripts/abcjs/data/abc_tune.js +4 -3
- data/app/assets/javascripts/abcjs/edit/abc_editor.js +10 -0
- data/app/assets/javascripts/abcjs/parse/abc_parse.js +120 -19
- data/app/assets/javascripts/abcjs/parse/abc_parse_directive.js +456 -115
- data/app/assets/javascripts/abcjs/raphael.js +2 -2
- data/app/assets/javascripts/abcjs/write/abc_absolute_element.js +111 -4
- data/app/assets/javascripts/abcjs/write/abc_abstract_engraver.js +899 -0
- data/app/assets/javascripts/abcjs/write/abc_beam_element.js +263 -37
- data/app/assets/javascripts/abcjs/write/abc_create_clef.js +76 -0
- data/app/assets/javascripts/abcjs/write/abc_create_key_signature.js +41 -0
- data/app/assets/javascripts/abcjs/write/abc_create_time_signature.js +51 -0
- data/app/assets/javascripts/abcjs/write/{abc_cresendo_element.js → abc_crescendo_element.js} +32 -1
- data/app/assets/javascripts/abcjs/write/abc_decoration.js +321 -0
- data/app/assets/javascripts/abcjs/write/abc_dynamic_decoration.js +22 -1
- data/app/assets/javascripts/abcjs/write/abc_ending_element.js +31 -1
- data/app/assets/javascripts/abcjs/write/abc_engraver_controller.js +359 -0
- data/app/assets/javascripts/abcjs/write/abc_glyphs.js +119 -9
- data/app/assets/javascripts/abcjs/write/abc_layout.js +2 -2
- data/app/assets/javascripts/abcjs/write/abc_relative_element.js +106 -8
- data/app/assets/javascripts/abcjs/write/abc_renderer.js +754 -0
- data/app/assets/javascripts/abcjs/write/abc_staff_group_element.js +249 -9
- data/app/assets/javascripts/abcjs/write/abc_tempo_element.js +104 -0
- data/app/assets/javascripts/abcjs/write/abc_tie_element.js +69 -22
- data/app/assets/javascripts/abcjs/write/abc_triplet_element.js +77 -10
- data/app/assets/javascripts/abcjs/write/abc_voice_element.js +100 -8
- data/app/assets/javascripts/abcjs/write/abc_write.js +64 -68
- data/lib/abcjs-rails/version.rb +1 -1
- metadata +12 -4
@@ -35,8 +35,6 @@ if (!window.ABCJS.write)
|
|
35
35
|
// Members:
|
36
36
|
// staffs: an array of all the staves in this group. Each staff contains the following elements:
|
37
37
|
// { top, bottom, highest, lowest, y }
|
38
|
-
// stafflines: an array of the same length as staffs. It contains an integer with the number of lines.
|
39
|
-
// TODO-PER: stafflines should actually be an element of staffs, I think.
|
40
38
|
// voices: array of VoiceElement objects. This is mostly passed in, but the VoiceElement objects are modified here.
|
41
39
|
//
|
42
40
|
// spacingunits: number of relative x-units in the line. Used by the calling function to pass back in as the "spacing" input parameter.
|
@@ -54,18 +52,148 @@ if (!window.ABCJS.write)
|
|
54
52
|
ABCJS.write.StaffGroupElement = function() {
|
55
53
|
this.voices = [];
|
56
54
|
this.staffs = [];
|
57
|
-
|
55
|
+
};
|
56
|
+
|
57
|
+
ABCJS.write.StaffGroupElement.prototype.setLimit = function(member, voice) {
|
58
|
+
if (!voice.specialY[member]) return;
|
59
|
+
if (!voice.staff.specialY[member])
|
60
|
+
voice.staff.specialY[member] = voice.specialY[member];
|
61
|
+
else
|
62
|
+
voice.staff.specialY[member] = Math.max(voice.staff.specialY[member], voice.specialY[member]);
|
58
63
|
};
|
59
64
|
|
60
65
|
ABCJS.write.StaffGroupElement.prototype.addVoice = function (voice, staffnumber, stafflines) {
|
61
|
-
this.voices
|
62
|
-
|
63
|
-
|
64
|
-
this.
|
66
|
+
var voiceNum = this.voices.length;
|
67
|
+
this.voices[voiceNum] = voice;
|
68
|
+
if (this.staffs[staffnumber])
|
69
|
+
this.staffs[staffnumber].voices.push(voiceNum);
|
70
|
+
else {
|
71
|
+
// TODO-PER: how does the min/max change when stafflines is not 5?
|
72
|
+
this.staffs[this.staffs.length] = {
|
73
|
+
top: 10,
|
74
|
+
bottom: 2,
|
75
|
+
lines: stafflines,
|
76
|
+
voices: [voiceNum],
|
77
|
+
specialY: {
|
78
|
+
tempoHeightAbove: 0,
|
79
|
+
partHeightAbove: 0,
|
80
|
+
volumeHeightAbove: 0,
|
81
|
+
dynamicHeightAbove: 0,
|
82
|
+
endingHeightAbove: 0,
|
83
|
+
chordHeightAbove: 0,
|
84
|
+
lyricHeightAbove: 0,
|
85
|
+
|
86
|
+
lyricHeightBelow: 0,
|
87
|
+
chordHeightBelow: 0,
|
88
|
+
volumeHeightBelow: 0,
|
89
|
+
dynamicHeightBelow: 0
|
90
|
+
}
|
91
|
+
};
|
65
92
|
}
|
66
93
|
voice.staff = this.staffs[staffnumber];
|
67
94
|
};
|
68
95
|
|
96
|
+
ABCJS.write.StaffGroupElement.prototype.setStaffLimits = function (voice) {
|
97
|
+
voice.staff.top = Math.max(voice.staff.top, voice.top);
|
98
|
+
voice.staff.bottom = Math.min(voice.staff.bottom, voice.bottom);
|
99
|
+
this.setLimit('tempoHeightAbove', voice);
|
100
|
+
this.setLimit('partHeightAbove', voice);
|
101
|
+
this.setLimit('volumeHeightAbove', voice);
|
102
|
+
this.setLimit('dynamicHeightAbove', voice);
|
103
|
+
this.setLimit('endingHeightAbove', voice);
|
104
|
+
this.setLimit('chordHeightAbove', voice);
|
105
|
+
this.setLimit('lyricHeightAbove', voice);
|
106
|
+
this.setLimit('lyricHeightBelow', voice);
|
107
|
+
this.setLimit('chordHeightBelow', voice);
|
108
|
+
this.setLimit('volumeHeightBelow', voice);
|
109
|
+
this.setLimit('dynamicHeightBelow', voice);
|
110
|
+
};
|
111
|
+
|
112
|
+
ABCJS.write.StaffGroupElement.prototype.setUpperAndLowerElements = function(renderer) {
|
113
|
+
// Each staff already has the top and bottom set, now we see if there are elements that are always on top and bottom, and resolve their pitch.
|
114
|
+
// Also, get the overall height of all the staves in this group.
|
115
|
+
var lastStaffBottom;
|
116
|
+
for (var i = 0; i < this.staffs.length; i++) {
|
117
|
+
var staff = this.staffs[i];
|
118
|
+
// the vertical order of elements that are above is: tempo, part, volume/dynamic, ending/chord, lyric
|
119
|
+
// the vertical order of elements that are below is: lyric, chord, volume/dynamic
|
120
|
+
var positionY = {
|
121
|
+
tempoHeightAbove: 0,
|
122
|
+
partHeightAbove: 0,
|
123
|
+
volumeHeightAbove: 0,
|
124
|
+
dynamicHeightAbove: 0,
|
125
|
+
endingHeightAbove: 0,
|
126
|
+
chordHeightAbove: 0,
|
127
|
+
lyricHeightAbove: 0,
|
128
|
+
|
129
|
+
lyricHeightBelow: 0,
|
130
|
+
chordHeightBelow: 0,
|
131
|
+
volumeHeightBelow: 0,
|
132
|
+
dynamicHeightBelow: 0
|
133
|
+
};
|
134
|
+
|
135
|
+
if (ABCJS.write.debugPlacement) {
|
136
|
+
staff.originalTop = staff.top; // This is just being stored for debugging purposes.
|
137
|
+
staff.originalBottom = staff.bottom; // This is just being stored for debugging purposes.
|
138
|
+
}
|
139
|
+
|
140
|
+
if (staff.specialY.lyricHeightAbove) { staff.top += staff.specialY.lyricHeightAbove; positionY.lyricHeightAbove = staff.top; }
|
141
|
+
if (staff.specialY.chordHeightAbove) { staff.top += staff.specialY.chordHeightAbove; positionY.chordHeightAbove = staff.top; }
|
142
|
+
if (staff.specialY.endingHeightAbove) {
|
143
|
+
if (staff.specialY.chordHeightAbove)
|
144
|
+
staff.top += 2;
|
145
|
+
else
|
146
|
+
staff.top += staff.specialY.endingHeightAbove;
|
147
|
+
positionY.endingHeightAbove = staff.top;
|
148
|
+
}
|
149
|
+
if (staff.specialY.dynamicHeightAbove && staff.specialY.volumeHeightAbove) {
|
150
|
+
staff.top += Math.max(staff.specialY.dynamicHeightAbove, staff.specialY.volumeHeightAbove);
|
151
|
+
positionY.dynamicHeightAbove = staff.top;
|
152
|
+
positionY.volumeHeightAbove = staff.top;
|
153
|
+
} else if (staff.specialY.dynamicHeightAbove) {
|
154
|
+
staff.top += staff.specialY.dynamicHeightAbove; positionY.dynamicHeightAbove = staff.top;
|
155
|
+
} else if (staff.specialY.volumeHeightAbove) { staff.top += staff.specialY.volumeHeightAbove; positionY.volumeHeightAbove = staff.top; }
|
156
|
+
if (staff.specialY.partHeightAbove) { staff.top += staff.specialY.partHeightAbove; positionY.partHeightAbove = staff.top; }
|
157
|
+
if (staff.specialY.tempoHeightAbove) { staff.top += staff.specialY.tempoHeightAbove; positionY.tempoHeightAbove = staff.top; }
|
158
|
+
|
159
|
+
if (staff.specialY.lyricHeightBelow) { positionY.lyricHeightBelow = staff.bottom; staff.bottom -= staff.specialY.lyricHeightBelow; }
|
160
|
+
if (staff.specialY.chordHeightBelow) { positionY.chordHeightBelow = staff.bottom; staff.bottom -= staff.specialY.chordHeightBelow; }
|
161
|
+
if (staff.specialY.volumeHeightBelow && staff.specialY.dynamicHeightBelow) {
|
162
|
+
positionY.volumeHeightBelow = staff.bottom;
|
163
|
+
positionY.dynamicHeightBelow = staff.bottom;
|
164
|
+
staff.bottom -= Math.max(staff.specialY.volumeHeightBelow, staff.specialY.dynamicHeightBelow);
|
165
|
+
} else if (staff.specialY.volumeHeightBelow) {
|
166
|
+
positionY.volumeHeightBelow = staff.bottom; staff.bottom -= staff.specialY.volumeHeightBelow;
|
167
|
+
} else if (staff.specialY.dynamicHeightBelow) {
|
168
|
+
positionY.dynamicHeightBelow = staff.bottom; staff.bottom -= staff.specialY.dynamicHeightBelow;
|
169
|
+
}
|
170
|
+
|
171
|
+
if (ABCJS.write.debugPlacement)
|
172
|
+
staff.positionY = positionY; // This is just being stored for debugging purposes.
|
173
|
+
|
174
|
+
for (var j = 0; j < staff.voices.length; j++) {
|
175
|
+
var voice = this.voices[staff.voices[j]];
|
176
|
+
voice.setUpperAndLowerElements(positionY);
|
177
|
+
}
|
178
|
+
// We might need a little space in between staves if the staves haven't been pushed far enough apart by notes or extra vertical stuff.
|
179
|
+
// Only try to put in extra space if this isn't the top staff.
|
180
|
+
if (lastStaffBottom !== undefined) {
|
181
|
+
var thisStaffTop = staff.top - 10;
|
182
|
+
var forcedSpacingBetween = lastStaffBottom + thisStaffTop;
|
183
|
+
var minSpacingInPitches = renderer.spacing.systemStaffSeparation/ABCJS.write.spacing.STEP;
|
184
|
+
var addedSpace = minSpacingInPitches - forcedSpacingBetween;
|
185
|
+
if (addedSpace > 0)
|
186
|
+
staff.top += addedSpace;
|
187
|
+
}
|
188
|
+
lastStaffBottom = 2 - staff.bottom; // the staff starts at position 2 and the bottom variable is negative. Therefore to find out how large the bottom is, we reverse the sign of the bottom, and add the 2 in.
|
189
|
+
|
190
|
+
// Now we need a little margin on the top, so we'll just throw that in.
|
191
|
+
//staff.top += 4;
|
192
|
+
//console.log("Staff Y: ",i,heightInPitches,staff.top,staff.bottom);
|
193
|
+
}
|
194
|
+
//console.log("Staff Height: ",heightInPitches,this.height);
|
195
|
+
};
|
196
|
+
|
69
197
|
ABCJS.write.StaffGroupElement.prototype.finished = function() {
|
70
198
|
for (var i=0;i<this.voices.length;i++) {
|
71
199
|
if (!this.voices[i].layoutEnded()) return false;
|
@@ -73,21 +201,36 @@ ABCJS.write.StaffGroupElement.prototype.finished = function() {
|
|
73
201
|
return true;
|
74
202
|
};
|
75
203
|
|
204
|
+
<<<<<<< HEAD
|
205
|
+
ABCJS.write.StaffGroupElement.prototype.layout = function(spacing, renderer, debug) {
|
206
|
+
this.spacingunits = 0; // number of times we will have ended up using the spacing distance (as opposed to fixed width distances)
|
207
|
+
this.minspace = 1000; // a big number to start off with - used to find out what the smallest space between two notes is -- GD 2014.1.7
|
208
|
+
var x = renderer.padding.left;
|
209
|
+
=======
|
76
210
|
ABCJS.write.StaffGroupElement.prototype.layout = function(spacing, controller, debug) {
|
77
211
|
this.spacingunits = 0; // number of times we will have ended up using the spacing distance (as opposed to fixed width distances)
|
78
212
|
this.minspace = 1000; // a big number to start off with - used to find out what the smallest space between two notes is -- GD 2014.1.7
|
79
213
|
var x = controller.paddingleft*controller.scale;
|
214
|
+
>>>>>>> origin/master
|
80
215
|
|
81
216
|
// find out how much space will be taken up by voice headers
|
82
217
|
var voiceheaderw = 0;
|
83
218
|
for (var i=0;i<this.voices.length;i++) {
|
84
219
|
if(this.voices[i].header) {
|
85
|
-
|
220
|
+
<<<<<<< HEAD
|
221
|
+
var size = renderer.getTextSize(this.voices[i].header, 'voicefont', '');
|
222
|
+
voiceheaderw = Math.max(voiceheaderw,size.width);
|
223
|
+
}
|
224
|
+
}
|
225
|
+
x=x+voiceheaderw*1.1; // When there is no voice header, 110% of 0 is 0
|
226
|
+
=======
|
227
|
+
var t = controller.renderText(100, this.y-10, this.voices[i].header, 'voicefont', ''); // code duplicated below // don't scale this as we ask for the bbox
|
86
228
|
voiceheaderw = Math.max(voiceheaderw,t.getBBox().width);
|
87
229
|
t.remove();
|
88
230
|
}
|
89
231
|
}
|
90
232
|
x=x+voiceheaderw*(1/controller.scale)*1.1; // 10% of 0 is 0
|
233
|
+
>>>>>>> origin/master
|
91
234
|
this.startx=x;
|
92
235
|
|
93
236
|
var currentduration = 0;
|
@@ -124,12 +267,14 @@ ABCJS.write.StaffGroupElement.prototype.layout = function(spacing, controller, d
|
|
124
267
|
spacingunit = 0; // number of spacingunits coming from the previously laid out element to this one
|
125
268
|
var spacingduration = 0;
|
126
269
|
for (i=0;i<currentvoices.length;i++) {
|
270
|
+
//console.log("greatest spacing unit", x, currentvoices[i].getNextX(), currentvoices[i].getSpacingUnits(), currentvoices[i].spacingduration);
|
127
271
|
if (currentvoices[i].getNextX()>x) {
|
128
272
|
x=currentvoices[i].getNextX();
|
129
273
|
spacingunit=currentvoices[i].getSpacingUnits();
|
130
274
|
spacingduration = currentvoices[i].spacingduration;
|
131
275
|
}
|
132
276
|
}
|
277
|
+
//console.log("new spacingunit", spacingunit, this.spacingunits, "="+(spacingunit+ this.spacingunits));
|
133
278
|
this.spacingunits+=spacingunit;
|
134
279
|
this.minspace = Math.min(this.minspace,spacingunit);
|
135
280
|
|
@@ -165,6 +310,7 @@ ABCJS.write.StaffGroupElement.prototype.layout = function(spacing, controller, d
|
|
165
310
|
spacingunit=this.voices[i].getSpacingUnits();
|
166
311
|
}
|
167
312
|
}
|
313
|
+
//console.log("greatest remaining",spacingunit,x);
|
168
314
|
this.spacingunits+=spacingunit;
|
169
315
|
this.w = x;
|
170
316
|
|
@@ -173,6 +319,18 @@ ABCJS.write.StaffGroupElement.prototype.layout = function(spacing, controller, d
|
|
173
319
|
}
|
174
320
|
};
|
175
321
|
|
322
|
+
<<<<<<< HEAD
|
323
|
+
ABCJS.write.StaffGroupElement.prototype.calcHeight = function () {
|
324
|
+
// the height is calculated here in a parallel way to the drawing below in hopes that both of these functions will be modified together.
|
325
|
+
// TODO-PER: also add the space between staves. (That's systemStaffSeparation, which is the minimum distance between the staff LINES.)
|
326
|
+
var height = 0;
|
327
|
+
for (var i=0;i<this.voices.length;i++) {
|
328
|
+
var staff = this.voices[i].staff;
|
329
|
+
if (!this.voices[i].duplicate) {
|
330
|
+
height += staff.top;
|
331
|
+
if (staff.bottom < 0)
|
332
|
+
height += -staff.bottom;
|
333
|
+
=======
|
176
334
|
ABCJS.write.StaffGroupElement.prototype.draw = function (renderer, y) {
|
177
335
|
|
178
336
|
this.y = y;
|
@@ -192,10 +350,59 @@ ABCJS.write.StaffGroupElement.prototype.draw = function (renderer, y) {
|
|
192
350
|
if (this.stafflines[i] === undefined)
|
193
351
|
this.stafflines[i] = 5;
|
194
352
|
renderer.printStave(this.startx, this.w, this.stafflines[i]);
|
353
|
+
>>>>>>> origin/master
|
195
354
|
}
|
196
355
|
}
|
197
|
-
|
356
|
+
return height;
|
357
|
+
};
|
198
358
|
|
359
|
+
<<<<<<< HEAD
|
360
|
+
ABCJS.write.StaffGroupElement.prototype.draw = function (renderer) {
|
361
|
+
// We enter this method with renderer.y pointing to the topmost coordinate that we're allowed to draw.
|
362
|
+
// All of the children that will be drawn have a relative "pitch" set, where zero is the first ledger line below the staff.
|
363
|
+
// renderer.y will be offset at the beginning of each staff by the amount required to make the relative pitch work.
|
364
|
+
// If there are multiple staves, then renderer.y will be incremented for each new staff.
|
365
|
+
|
366
|
+
var debugPrint;
|
367
|
+
var colorIndex;
|
368
|
+
if (ABCJS.write.debugPlacement) {
|
369
|
+
var colors = [ "rgba(207,27,36,0.4)", "rgba(168,214,80,0.4)", "rgba(110,161,224,0.4)", "rgba(191,119,218,0.4)", "rgba(195,30,151,0.4)",
|
370
|
+
"rgba(31,170,177,0.4)", "rgba(220,166,142,0.4)" ];
|
371
|
+
debugPrint = function(staff, key) {
|
372
|
+
if (staff.positionY[key]) {
|
373
|
+
//renderer.printHorizontalLine(50, renderer.calcY(staff.positionY[key]), key.substr(0, 4) + " " + Math.round(staff.positionY[key]));
|
374
|
+
var height = staff.specialY[key] * ABCJS.write.spacing.STEP;
|
375
|
+
renderer.printShadedBox(renderer.padding.left, renderer.calcY(staff.positionY[key]), renderer.controller.width, height,colors[colorIndex], key.substr(0, 4));
|
376
|
+
colorIndex += 1; if (colorIndex > 6) colorIndex = 0;
|
377
|
+
}
|
378
|
+
};
|
379
|
+
}
|
380
|
+
|
381
|
+
var startY = renderer.y; // So that it can be restored after we're done.
|
382
|
+
// Set the absolute Y position for each staff here, so the voice drawing below can just use if.
|
383
|
+
for (var j = 0; j < this.staffs.length; j++) {
|
384
|
+
var staff1 = this.staffs[j];
|
385
|
+
//renderer.printHorizontalLine(50, renderer.y, "start");
|
386
|
+
renderer.moveY(ABCJS.write.spacing.STEP, staff1.top);
|
387
|
+
staff1.absoluteY = renderer.y;
|
388
|
+
if (ABCJS.write.debugPlacement) {
|
389
|
+
colorIndex = 0;
|
390
|
+
renderer.printShadedBox(renderer.padding.left, renderer.calcY(staff1.originalTop), renderer.controller.width, renderer.calcY(staff1.originalBottom)-renderer.calcY(staff1.originalTop),"rgba(0,0,0,0.1)");
|
391
|
+
debugPrint(staff1, 'chordHeightAbove');
|
392
|
+
debugPrint(staff1, 'chordHeightBelow');
|
393
|
+
debugPrint(staff1, 'dynamicHeightAbove');
|
394
|
+
debugPrint(staff1, 'dynamicHeightBelow');
|
395
|
+
debugPrint(staff1, 'endingHeightAbove');
|
396
|
+
debugPrint(staff1, 'lyricHeightAbove');
|
397
|
+
debugPrint(staff1, 'lyricHeightBelow');
|
398
|
+
debugPrint(staff1, 'partHeightAbove');
|
399
|
+
debugPrint(staff1, 'tempoHeightAbove');
|
400
|
+
debugPrint(staff1, 'volumeHeightAbove');
|
401
|
+
debugPrint(staff1, 'volumeHeightBelow');
|
402
|
+
}
|
403
|
+
if (staff1.bottom < 0)
|
404
|
+
renderer.moveY(ABCJS.write.spacing.STEP, -staff1.bottom);
|
405
|
+
=======
|
199
406
|
var bartop = 0;
|
200
407
|
renderer.measureNumber = null;
|
201
408
|
for (i=0;i<this.voices.length;i++) {
|
@@ -210,8 +417,35 @@ ABCJS.write.StaffGroupElement.prototype.draw = function (renderer, y) {
|
|
210
417
|
renderer.y = this.staffs[this.staffs.length-1].y;
|
211
418
|
var bottom = renderer.calcY(2);
|
212
419
|
renderer.printStem(this.startx, 0.6, top, bottom);
|
420
|
+
>>>>>>> origin/master
|
213
421
|
}
|
422
|
+
var topLine; // these are to connect multiple staves. We need to remember where they are.
|
423
|
+
var bottomLine;
|
214
424
|
|
425
|
+
<<<<<<< HEAD
|
426
|
+
var bartop = 0;
|
427
|
+
renderer.measureNumber = null;
|
428
|
+
for (var i=0;i<this.voices.length;i++) {
|
429
|
+
var staff = this.voices[i].staff;
|
430
|
+
renderer.y = staff.absoluteY;
|
431
|
+
//renderer.y = staff.y;
|
432
|
+
// offset for starting the counting at middle C
|
433
|
+
if (!this.voices[i].duplicate) {
|
434
|
+
// renderer.moveY(ABCJS.write.spacing.STEP, staff.top);
|
435
|
+
if (!topLine) topLine = renderer.calcY(10);
|
436
|
+
bottomLine = renderer.calcY(2);
|
437
|
+
if (staff.lines !== 0)
|
438
|
+
renderer.printStave(this.startx, this.w, staff.lines);
|
439
|
+
}
|
440
|
+
this.voices[i].draw(renderer, bartop);
|
441
|
+
if (!this.voices[i].duplicate) {
|
442
|
+
bartop = renderer.calcY(2); // This connects the bar lines between two different staves.
|
443
|
+
// if (staff.bottom < 0)
|
444
|
+
// renderer.moveY(ABCJS.write.spacing.STEP, -staff.bottom);
|
445
|
+
}
|
446
|
+
}
|
447
|
+
renderer.measureNumber = null;
|
448
|
+
=======
|
215
449
|
// for (i=0;i<this.staffs.length;i++) {
|
216
450
|
// if (this.stafflines[i] === 0) continue;
|
217
451
|
// renderer.y = this.staffs[i].y;
|
@@ -220,6 +454,12 @@ ABCJS.write.StaffGroupElement.prototype.draw = function (renderer, y) {
|
|
220
454
|
// this.stafflines[i] = 5;
|
221
455
|
// renderer.printStave(this.startx,this.w, this.stafflines[i]);
|
222
456
|
// }
|
457
|
+
>>>>>>> origin/master
|
223
458
|
|
459
|
+
// connect all the staves together with a vertical line
|
460
|
+
if (this.staffs.length>1) {
|
461
|
+
renderer.printStem(this.startx, 0.6, topLine, bottomLine);
|
462
|
+
}
|
463
|
+
renderer.y = startY;
|
224
464
|
};
|
225
465
|
|
@@ -0,0 +1,104 @@
|
|
1
|
+
// abc_tempo_element.js: Definition of the TempoElement class.
|
2
|
+
// Copyright (C) 2014 Gregory Dyke (gregdyke at gmail dot com) and Paul Rosen
|
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
|
+
/*globals ABCJS */
|
18
|
+
|
19
|
+
if (!window.ABCJS)
|
20
|
+
window.ABCJS = {};
|
21
|
+
|
22
|
+
if (!window.ABCJS.write)
|
23
|
+
window.ABCJS.write = {};
|
24
|
+
|
25
|
+
(function() {
|
26
|
+
"use strict";
|
27
|
+
var totalHeightInPitches = 5;
|
28
|
+
|
29
|
+
ABCJS.write.TempoElement = function(tempo) {
|
30
|
+
this.tempo = tempo;
|
31
|
+
this.tempoHeightAbove = totalHeightInPitches;
|
32
|
+
this.pitch = undefined; // This will be set later
|
33
|
+
};
|
34
|
+
|
35
|
+
ABCJS.write.TempoElement.prototype.setUpperAndLowerElements = function(positionY) { // TODO-PER: This might not be called.
|
36
|
+
this.pitch = positionY.tempoHeightAbove;
|
37
|
+
};
|
38
|
+
|
39
|
+
ABCJS.write.TempoElement.prototype.setX = function (x) {
|
40
|
+
this.x = x;
|
41
|
+
};
|
42
|
+
|
43
|
+
ABCJS.write.TempoElement.prototype.draw = function(renderer) {
|
44
|
+
var x = this.x;
|
45
|
+
if (this.pitch === undefined)
|
46
|
+
window.console.error("Tempo Element y-coordinate not set.");
|
47
|
+
|
48
|
+
var y = renderer.calcY(this.pitch);
|
49
|
+
var text;
|
50
|
+
if (this.tempo.preString) {
|
51
|
+
text = renderer.renderText(x, y, this.tempo.preString, 'tempofont', 'tempo', "start");
|
52
|
+
var preWidth = text.getBBox().width;
|
53
|
+
var charWidth = preWidth / this.tempo.preString.length; // Just get some average number to increase the spacing.
|
54
|
+
x += preWidth + charWidth;
|
55
|
+
}
|
56
|
+
if (this.tempo.duration) {
|
57
|
+
var temposcale = 0.75;
|
58
|
+
var tempopitch = this.pitch - totalHeightInPitches + 1; // The pitch we receive is the top of the allotted area: change that to practically the bottom.
|
59
|
+
var duration = this.tempo.duration[0]; // TODO when multiple durations
|
60
|
+
var abselem = new ABCJS.write.AbsoluteElement(this.tempo, duration, 1, 'tempo');
|
61
|
+
var durlog = Math.floor(Math.log(duration) / Math.log(2));
|
62
|
+
var dot = 0;
|
63
|
+
for (var tot = Math.pow(2, durlog), inc = tot / 2; tot < duration; dot++, tot += inc, inc /= 2);
|
64
|
+
var c = renderer.engraver.chartable.note[-durlog];
|
65
|
+
var flag = renderer.engraver.chartable.uflags[-durlog];
|
66
|
+
var temponote = renderer.engraver.createNoteHead(abselem, // TODO-PER: This seems late to be creating this element. Shouldn't it happen before draw?
|
67
|
+
c,
|
68
|
+
{verticalPos: tempopitch},
|
69
|
+
"up",
|
70
|
+
0,
|
71
|
+
0,
|
72
|
+
flag,
|
73
|
+
dot,
|
74
|
+
0,
|
75
|
+
temposcale
|
76
|
+
);
|
77
|
+
abselem.addHead(temponote);
|
78
|
+
var stem;
|
79
|
+
if (duration < 1) {
|
80
|
+
var p1 = tempopitch + 1 / 3 * temposcale;
|
81
|
+
var p2 = tempopitch + 7 * temposcale;
|
82
|
+
var dx = temponote.dx + temponote.w;
|
83
|
+
var width = -0.6;
|
84
|
+
stem = new ABCJS.write.RelativeElement(null, dx, 0, p1, {"type": "stem", "pitch2": p2, linewidth: width});
|
85
|
+
stem.setX(x);
|
86
|
+
abselem.addExtra(stem);
|
87
|
+
}
|
88
|
+
abselem.x = x;
|
89
|
+
temponote.setX(x);
|
90
|
+
temponote.draw(renderer, x);
|
91
|
+
if (stem)
|
92
|
+
stem.draw(renderer, x);
|
93
|
+
x += (abselem.w + 5);
|
94
|
+
var str = "= " + this.tempo.bpm;
|
95
|
+
text = renderer.renderText(x, y, str, 'tempofont', 'tempo', "start");
|
96
|
+
var postWidth = text.getBBox().width;
|
97
|
+
var charWidth2 = postWidth / str.length; // Just get some average number to increase the spacing.
|
98
|
+
x += postWidth + charWidth2;
|
99
|
+
}
|
100
|
+
if (this.tempo.postString) {
|
101
|
+
renderer.renderText(x, y, this.tempo.postString, 'tempofont', 'tempo', "start");
|
102
|
+
}
|
103
|
+
};
|
104
|
+
})();
|