abcjs-rails 1.11 → 2.0
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 +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
@@ -22,40 +22,192 @@ if (!window.ABCJS)
|
|
22
22
|
if (!window.ABCJS.write)
|
23
23
|
window.ABCJS.write = {};
|
24
24
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
25
|
+
// Most elements on the page are related to a particular absolute element -- notes, rests, bars, etc. Beams, however, span multiple elements.
|
26
|
+
// This means that beams can't be laid out until the absolute elements are placed. There is the further complication that the stems for beamed
|
27
|
+
// notes can't be laid out until the beams are because we don't know how long they will be until we know the slope of the beam and the horizontal
|
28
|
+
// spacing of the absolute elements.
|
29
|
+
//
|
30
|
+
// So, when a beam is detected, a BeamElem is created, then all notes belonging to that beam are added to it. These notes are not given stems at that time.
|
31
|
+
// Then, after the horizontal layout is complete, all of the BeamElem are iterated to set the beam position, then all of the notes that are beamed are given
|
32
|
+
// stems. After that, we are ready for the drawing step.
|
33
|
+
|
34
|
+
// There are three phases: the setup phase, when new elements are being discovered, the layout phase, when everything is calculated, and the drawing phase,
|
35
|
+
// when the object is not changed, but is used to put the elements on the page.
|
36
|
+
|
37
|
+
(function() {
|
38
|
+
"use strict";
|
39
|
+
|
40
|
+
//
|
41
|
+
// Setup phase
|
42
|
+
//
|
43
|
+
ABCJS.write.BeamElem = function(stemHeight, type, flat) {
|
44
|
+
// type is "grace", "up", "down", or undefined. flat is used to force flat beams, as it commonly found in the grace notes of bagpipe music.
|
45
|
+
this.isflat = flat;
|
46
|
+
this.isgrace = (type && type === "grace");
|
47
|
+
this.forceup = this.isgrace || (type && type === "up");
|
48
|
+
this.forcedown = (type && type === "down");
|
49
|
+
this.elems = []; // all the ABCJS.write.AbsoluteElements that this beam touches. It may include embedded rests.
|
50
|
+
this.total = 0;
|
51
|
+
this.allrests = true;
|
52
|
+
this.stemHeight = stemHeight;
|
53
|
+
this.beams = []; // During the layout phase, this will become a list of the beams that need to be drawn.
|
54
|
+
};
|
55
|
+
|
56
|
+
ABCJS.write.BeamElem.prototype.add = function(abselem) {
|
57
|
+
var pitch = abselem.abcelem.averagepitch;
|
58
|
+
if (pitch === undefined) return; // don't include elements like spacers in beams
|
59
|
+
this.allrests = this.allrests && abselem.abcelem.rest;
|
60
|
+
abselem.beam = this;
|
61
|
+
this.elems.push(abselem);
|
62
|
+
//var pitch = abselem.abcelem.averagepitch;
|
63
|
+
this.total += pitch; // TODO CHORD (get pitches from abselem.heads)
|
64
|
+
if (!this.min || abselem.abcelem.minpitch < this.min) {
|
65
|
+
this.min = abselem.abcelem.minpitch;
|
66
|
+
}
|
67
|
+
if (!this.max || abselem.abcelem.maxpitch > this.max) {
|
68
|
+
this.max = abselem.abcelem.maxpitch;
|
69
|
+
}
|
70
|
+
};
|
71
|
+
|
72
|
+
var middleLine = 6; // hardcoded 6 is B
|
73
|
+
|
74
|
+
ABCJS.write.BeamElem.prototype.calcDir = function() {
|
75
|
+
if (this.forceup) return true;
|
76
|
+
if (this.forcedown) return false;
|
77
|
+
var average = calcAverage(this.total, this.elems.length);
|
78
|
+
return average < middleLine;
|
79
|
+
};
|
80
|
+
|
81
|
+
//
|
82
|
+
// layout phase
|
83
|
+
//
|
84
|
+
ABCJS.write.BeamElem.prototype.layout = function() {
|
85
|
+
if (this.elems.length === 0 || this.allrests) return;
|
86
|
+
|
87
|
+
this.stemsUp = this.calcDir(); // True means the stems are facing up.
|
88
|
+
var dy = calcDy(this.stemsUp, this.isgrace); // This is the width of the beam line.
|
89
|
+
|
90
|
+
// create the main beam
|
91
|
+
var firstElement = this.elems[0];
|
92
|
+
var lastElement = this.elems[this.elems.length - 1];
|
93
|
+
var yPos = calcYPos(this.total, this.elems.length, this.stemHeight, this.stemsUp, firstElement.abcelem.averagepitch, lastElement.abcelem.averagepitch, this.isflat, this.min, this.max, this.isgrace);
|
94
|
+
var xPos = calcXPos(this.stemsUp, firstElement, lastElement);
|
95
|
+
this.beams.push({ startX: xPos[0], endX: xPos[1], startY: yPos[0], endY: yPos[1], dy: dy });
|
96
|
+
|
97
|
+
// create the rest of the beams (in the case of 1/16th notes, etc.
|
98
|
+
var beams = createAdditionalBeams(this.elems, this.stemsUp, this.beams[0], this.isgrace, dy);
|
99
|
+
for (var i = 0; i < beams.length; i++)
|
100
|
+
this.beams.push(beams[i]);
|
101
|
+
|
102
|
+
// Now that the main beam is defined, we know how tall the stems should be, so create them and attach them to the original notes.
|
103
|
+
createStems(this.elems, this.stemsUp, this.beams[0], dy, this.mainNote);
|
104
|
+
};
|
105
|
+
|
106
|
+
ABCJS.write.BeamElem.prototype.isAbove = function() {
|
107
|
+
return this.stemsUp;
|
108
|
+
};
|
109
|
+
|
110
|
+
// We can't just use the entire beam for the calculation. The range has to be passed in, because the beam might extend into some unrelated notes. for instance, (3_a'f'e'f'2 when L:16
|
111
|
+
ABCJS.write.BeamElem.prototype.heightAtMidpoint = function(startX, endX) {
|
112
|
+
if (this.beams.length === 0)
|
113
|
+
return 0;
|
114
|
+
var beam = this.beams[0];
|
115
|
+
var midPoint = startX + (endX - startX) / 2;
|
116
|
+
return getBarYAt(beam.startX, beam.startY, beam.endX, beam.endY, midPoint);
|
117
|
+
};
|
118
|
+
|
119
|
+
ABCJS.write.BeamElem.prototype.xAtMidpoint = function(startX, endX) {
|
120
|
+
return startX + (endX - startX)/2;
|
121
|
+
};
|
122
|
+
|
123
|
+
//
|
124
|
+
// Drawing phase
|
125
|
+
//
|
126
|
+
ABCJS.write.BeamElem.prototype.draw = function(renderer) {
|
127
|
+
if (this.beams.length === 0) return;
|
128
|
+
|
129
|
+
renderer.beginGroup();
|
130
|
+
for (var i = 0; i < this.beams.length; i++) {
|
131
|
+
var beam = this.beams[i];
|
132
|
+
drawBeam(renderer, beam.startX, beam.startY, beam.endX, beam.endY, beam.dy);
|
133
|
+
}
|
134
|
+
renderer.endGroup('beam-elem');
|
135
|
+
};
|
136
|
+
|
137
|
+
//
|
138
|
+
// private functions
|
139
|
+
//
|
140
|
+
function calcSlant(leftAveragePitch, rightAveragePitch, numStems, isFlat) {
|
141
|
+
if (isFlat)
|
142
|
+
return 0;
|
143
|
+
var slant = leftAveragePitch - rightAveragePitch;
|
144
|
+
var maxSlant = numStems / 2;
|
36
145
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
this.allrests = this.allrests && abselem.abcelem.rest;
|
41
|
-
abselem.beam = this;
|
42
|
-
this.elems.push(abselem);
|
43
|
-
//var pitch = abselem.abcelem.averagepitch;
|
44
|
-
this.total += pitch; // TODO CHORD (get pitches from abselem.heads)
|
45
|
-
if (!this.min || abselem.abcelem.minpitch<this.min) {
|
46
|
-
this.min = abselem.abcelem.minpitch;
|
146
|
+
if (slant > maxSlant) slant = maxSlant;
|
147
|
+
if (slant < -maxSlant) slant = -maxSlant;
|
148
|
+
return slant;
|
47
149
|
}
|
48
|
-
|
49
|
-
|
150
|
+
|
151
|
+
function calcAverage(total, numElements) {
|
152
|
+
if (!numElements)
|
153
|
+
return 0;
|
154
|
+
return total / numElements;
|
155
|
+
}
|
156
|
+
|
157
|
+
function getBarYAt(startx, starty, endx, endy, x) {
|
158
|
+
return starty + (endy - starty) / (endx - startx) * (x - startx);
|
159
|
+
}
|
160
|
+
|
161
|
+
function calcDy(asc, isGrace) {
|
162
|
+
var dy = (asc) ? ABCJS.write.spacing.STEP : -ABCJS.write.spacing.STEP;
|
163
|
+
if (isGrace) dy = dy * 0.4;
|
164
|
+
return dy;
|
50
165
|
}
|
51
|
-
};
|
52
166
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
167
|
+
function drawBeam(renderer, startX, startY, endX, endY, dy) {
|
168
|
+
// the X coordinates are actual coordinates, but the Y coordinates are in pitches.
|
169
|
+
startY = renderer.calcY(startY);
|
170
|
+
endY = renderer.calcY(endY);
|
171
|
+
var pathString = "M" + startX + " " + startY + " L" + endX + " " + endY +
|
172
|
+
"L" + endX + " " + (endY + dy) + " L" + startX + " " + (startY + dy) + "z";
|
173
|
+
renderer.printPath({
|
174
|
+
path: pathString,
|
175
|
+
stroke: "none",
|
176
|
+
fill: "#000000",
|
177
|
+
'class': renderer.addClasses('beam-elem')
|
178
|
+
});
|
58
179
|
}
|
180
|
+
<<<<<<< HEAD
|
181
|
+
|
182
|
+
function calcXPos(asc, firstElement, lastElement) {
|
183
|
+
var starthead = firstElement.heads[asc ? 0 : firstElement.heads.length - 1];
|
184
|
+
var endhead = lastElement.heads[asc ? 0 : lastElement.heads.length - 1];
|
185
|
+
var startX = starthead.x;
|
186
|
+
if (asc) startX += starthead.w - 0.6;
|
187
|
+
var endX = endhead.x;
|
188
|
+
if (asc) endX += endhead.w;
|
189
|
+
return [ startX, endX ];
|
190
|
+
}
|
191
|
+
|
192
|
+
function calcYPos(total, numElements, stemHeight, asc, firstAveragePitch, lastAveragePitch, isFlat, minPitch, maxPitch, isGrace) {
|
193
|
+
var average = calcAverage(total, numElements); // This is the average pitch for the all the notes that will be beamed.
|
194
|
+
var barpos = stemHeight - 2; // (isGrace)? 5:7;
|
195
|
+
var barminpos = stemHeight - 2;
|
196
|
+
var pos = Math.round(asc ? Math.max(average + barpos, maxPitch + barminpos) : Math.min(average - barpos, minPitch - barminpos));
|
197
|
+
|
198
|
+
var slant = calcSlant(firstAveragePitch, lastAveragePitch, numElements, isFlat);
|
199
|
+
var startY = pos + Math.floor(slant / 2);
|
200
|
+
var endY = pos + Math.floor(-slant / 2);
|
201
|
+
|
202
|
+
// If the notes are too high or too low, make the beam go down to the middle
|
203
|
+
if (!isGrace) {
|
204
|
+
if (asc && pos < 6) {
|
205
|
+
startY = 6;
|
206
|
+
endY = 6;
|
207
|
+
} else if (!asc && pos > 6) {
|
208
|
+
startY = 6;
|
209
|
+
endY = 6;
|
210
|
+
=======
|
59
211
|
};
|
60
212
|
|
61
213
|
ABCJS.write.BeamElem.prototype.draw = function(renderer) {
|
@@ -131,32 +283,106 @@ ABCJS.write.BeamElem.prototype.drawStems = function(renderer) {
|
|
131
283
|
} else {
|
132
284
|
auxbeams[-4-durlog] = {x:x+((this.asc)?-0.6:0), y:bary+sy*(-4-durlog+1),
|
133
285
|
durlog:durlog, single:true};
|
286
|
+
>>>>>>> origin/master
|
134
287
|
}
|
135
288
|
}
|
136
289
|
|
137
|
-
|
138
|
-
|
290
|
+
return [ startY, endY];
|
291
|
+
}
|
139
292
|
|
140
|
-
|
141
|
-
|
293
|
+
function createStems(elems, asc, beam, dy, mainNote) {
|
294
|
+
for (var i = 0; i < elems.length; i++) {
|
295
|
+
var elem = elems[i];
|
296
|
+
if (elem.abcelem.rest)
|
297
|
+
continue;
|
298
|
+
// TODO-PER: This is odd. If it is a regular beam then elems is an array of AbsoluteElements, if it is a grace beam then it is an array of objects , so we directly attach the element to the parent. We tell it if is a grace note because they are passed in as a generic object instead of an AbsoluteElement.
|
299
|
+
var isGrace = elem.addExtra ? false : true;
|
300
|
+
var parent = isGrace ? mainNote : elem;
|
301
|
+
var furthestHead = elem.heads[(asc) ? 0 : elem.heads.length - 1];
|
302
|
+
var ovalDelta = 1 / 5;//(isGrace)?1/3:1/5;
|
303
|
+
var pitch = furthestHead.pitch + ((asc) ? ovalDelta : -ovalDelta);
|
304
|
+
var dx = asc ? furthestHead.w : 0; // down-pointing stems start on the left side of the note, up-pointing stems start on the right side, so we offset by the note width.
|
305
|
+
var x = furthestHead.x + dx; // this is now the actual x location in pixels.
|
306
|
+
var bary = getBarYAt(beam.startX, beam.startY, beam.endX, beam.endY, x);
|
307
|
+
var lineWidth = (asc) ? -0.6 : 0.6;
|
308
|
+
if (!asc)
|
309
|
+
bary -= (dy / 2) / ABCJS.write.spacing.STEP; // TODO-PER: This is just a fudge factor so the down-pointing stems don't overlap.
|
310
|
+
if (isGrace)
|
311
|
+
dx += elem.heads[0].dx;
|
312
|
+
// TODO-PER-HACK: One type of note head has a different placement of the stem. This should be more generically calculated:
|
313
|
+
if (furthestHead.c === 'noteheads.slash.quarter') {
|
314
|
+
if (asc)
|
315
|
+
pitch += 1;
|
316
|
+
else
|
317
|
+
pitch -= 1;
|
318
|
+
}
|
319
|
+
var stem = new ABCJS.write.RelativeElement(null, dx, 0, pitch, {
|
320
|
+
"type": "stem",
|
321
|
+
"pitch2": bary,
|
322
|
+
linewidth: lineWidth
|
323
|
+
});
|
324
|
+
stem.setX(parent.x); // This is after the x coordinates were set, so we have to set it directly.
|
325
|
+
parent.addExtra(stem);
|
326
|
+
}
|
327
|
+
|
328
|
+
}
|
142
329
|
|
330
|
+
function createAdditionalBeams(elems, asc, beam, isGrace, dy) {
|
331
|
+
var beams = [];
|
332
|
+
var auxBeams = []; // auxbeam will be {x, y, durlog, single} auxbeam[0] should match with durlog=-4 (16th) (j=-4-durlog)
|
333
|
+
for (var i = 0; i < elems.length; i++) {
|
334
|
+
var elem = elems[i];
|
335
|
+
if (elem.abcelem.rest)
|
336
|
+
continue;
|
337
|
+
var furthestHead = elem.heads[(asc) ? 0 : elem.heads.length - 1];
|
338
|
+
var x = furthestHead.x + ((asc) ? furthestHead.w : 0);
|
339
|
+
var bary = getBarYAt(beam.startX, beam.startY, beam.endX, beam.endY, x);
|
143
340
|
|
144
|
-
|
145
|
-
|
146
|
-
|
341
|
+
var sy = (asc) ? -1.5 : 1.5;
|
342
|
+
if (isGrace) sy = sy * 2 / 3; // This makes the second beam on grace notes closer to the first one.
|
343
|
+
for (var durlog = ABCJS.write.getDurlog(elem.abcelem.duration); durlog < -3; durlog++) { // get the duration via abcelem because of triplets
|
344
|
+
if (auxBeams[-4 - durlog]) {
|
345
|
+
auxBeams[-4 - durlog].single = false;
|
346
|
+
} else {
|
347
|
+
auxBeams[-4 - durlog] = {
|
348
|
+
x: x + ((asc) ? -0.6 : 0), y: bary + sy * (-4 - durlog + 1),
|
349
|
+
durlog: durlog, single: true
|
350
|
+
};
|
147
351
|
}
|
148
|
-
|
352
|
+
}
|
353
|
+
|
354
|
+
<<<<<<< HEAD
|
355
|
+
for (var j = auxBeams.length - 1; j >= 0; j--) {
|
356
|
+
if (i === elems.length - 1 || ABCJS.write.getDurlog(elems[i + 1].abcelem.duration) > (-j - 4)) {
|
357
|
+
|
358
|
+
var auxBeamEndX = x;
|
359
|
+
var auxBeamEndY = bary + sy * (j + 1);
|
149
360
|
|
361
|
+
|
362
|
+
if (auxBeams[j].single) {
|
363
|
+
auxBeamEndX = (i === 0) ? x + 5 : x - 5;
|
364
|
+
auxBeamEndY = getBarYAt(beam.startX, beam.startY, beam.endX, beam.endY, auxBeamEndX) + sy * (j + 1);
|
365
|
+
}
|
366
|
+
beams.push({ startX: auxBeams[j].x, endX: auxBeamEndX, startY: auxBeams[j].y, endY: auxBeamEndY, dy: dy });
|
367
|
+
auxBeams = auxBeams.slice(0, j);
|
368
|
+
}
|
369
|
+
=======
|
150
370
|
var pathString ="M"+auxbeams[j].x+" "+auxbeams[j].y+" L"+auxbeamendx+" "+auxbeamendy+
|
151
371
|
"L"+auxbeamendx+" "+(auxbeamendy+this.dy) +" L"+auxbeams[j].x+" "+(auxbeams[j].y+this.dy)+"z";
|
152
372
|
renderer.printPath({path:pathString, stroke:"none", fill:"#000000", 'class': renderer.addClasses('beam-elem')});
|
153
373
|
auxbeams = auxbeams.slice(0,j);
|
374
|
+
>>>>>>> origin/master
|
154
375
|
}
|
155
376
|
}
|
377
|
+
return beams;
|
156
378
|
}
|
379
|
+
<<<<<<< HEAD
|
380
|
+
})();
|
381
|
+
=======
|
157
382
|
renderer.endGroup('beam-elem');
|
158
383
|
};
|
159
384
|
|
160
385
|
ABCJS.write.BeamElem.prototype.getBarYAt = function(x) {
|
161
386
|
return this.starty + (this.endy-this.starty)/(this.endx-this.startx)*(x-this.startx);
|
162
387
|
};
|
388
|
+
>>>>>>> origin/master
|
@@ -0,0 +1,76 @@
|
|
1
|
+
// abc_create_clef.js
|
2
|
+
// Copyright (C) 2010,2015 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
|
+
|
28
|
+
ABCJS.write.createClef = function(elem) {
|
29
|
+
var clef;
|
30
|
+
var octave = 0;
|
31
|
+
var abselem = new ABCJS.write.AbsoluteElement(elem,0,10, 'staff-extra');
|
32
|
+
switch (elem.type) {
|
33
|
+
case "treble": clef = "clefs.G"; break;
|
34
|
+
case "tenor": clef="clefs.C"; break;
|
35
|
+
case "alto": clef="clefs.C"; break;
|
36
|
+
case "bass": clef="clefs.F"; break;
|
37
|
+
case 'treble+8': clef = "clefs.G"; octave = 1; break;
|
38
|
+
case 'tenor+8':clef="clefs.C"; octave = 1; break;
|
39
|
+
case 'bass+8': clef="clefs.F"; octave = 1; break;
|
40
|
+
case 'alto+8': clef="clefs.C"; octave = 1; break;
|
41
|
+
case 'treble-8': clef = "clefs.G"; octave = -1; break;
|
42
|
+
case 'tenor-8':clef="clefs.C"; octave = -1; break;
|
43
|
+
case 'bass-8': clef="clefs.F"; octave = -1; break;
|
44
|
+
case 'alto-8': clef="clefs.C"; octave = -1; break;
|
45
|
+
case 'none': return null;
|
46
|
+
case 'perc': clef="clefs.perc"; break;
|
47
|
+
default: abselem.addChild(new ABCJS.write.RelativeElement("clef="+elem.type, 0, 0, undefined, {type:"debug"}));
|
48
|
+
}
|
49
|
+
// if (elem.verticalPos) {
|
50
|
+
// pitch = elem.verticalPos;
|
51
|
+
// }
|
52
|
+
var dx =5;
|
53
|
+
if (clef) {
|
54
|
+
abselem.addRight(new ABCJS.write.RelativeElement(clef, dx, ABCJS.write.glyphs.getSymbolWidth(clef), elem.clefPos));
|
55
|
+
|
56
|
+
if (clef === 'clefs.G') {
|
57
|
+
abselem.top = 13;
|
58
|
+
abselem.bottom = -1;
|
59
|
+
} else {
|
60
|
+
abselem.top = 10;
|
61
|
+
abselem.bottom = 2;
|
62
|
+
}
|
63
|
+
if (octave !== 0) {
|
64
|
+
var scale = 2 / 3;
|
65
|
+
var adjustspacing = (ABCJS.write.glyphs.getSymbolWidth(clef) - ABCJS.write.glyphs.getSymbolWidth("8") * scale) / 2;
|
66
|
+
abselem.addRight(new ABCJS.write.RelativeElement("8", dx + adjustspacing, ABCJS.write.glyphs.getSymbolWidth("8") * scale, (octave > 0) ? abselem.top + 3 : abselem.bottom - 1, {
|
67
|
+
scalex: scale,
|
68
|
+
scaley: scale
|
69
|
+
}));
|
70
|
+
abselem.top += 2;
|
71
|
+
}
|
72
|
+
}
|
73
|
+
return abselem;
|
74
|
+
};
|
75
|
+
|
76
|
+
})();
|
@@ -0,0 +1,41 @@
|
|
1
|
+
// abc_create_key_signature.js
|
2
|
+
// Copyright (C) 2010,2015 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
|
+
|
28
|
+
ABCJS.write.createKeySignature = function(elem) {
|
29
|
+
if (!elem.accidentals || elem.accidentals.length === 0)
|
30
|
+
return null;
|
31
|
+
var abselem = new ABCJS.write.AbsoluteElement(elem, 0, 10, 'staff-extra');
|
32
|
+
var dx = 0;
|
33
|
+
window.ABCJS.parse.each(elem.accidentals, function(acc) {
|
34
|
+
var symbol = (acc.acc === "sharp") ? "accidentals.sharp" : (acc.acc === "natural") ? "accidentals.nat" : "accidentals.flat";
|
35
|
+
//var notes = { 'A': 5, 'B': 6, 'C': 0, 'D': 1, 'E': 2, 'F': 3, 'G':4, 'a': 12, 'b': 13, 'c': 7, 'd': 8, 'e': 9, 'f': 10, 'g':11 };
|
36
|
+
abselem.addRight(new ABCJS.write.RelativeElement(symbol, dx, ABCJS.write.glyphs.getSymbolWidth(symbol), acc.verticalPos, {thickness: ABCJS.write.glyphs.symbolHeightInPitches(symbol)}));
|
37
|
+
dx += ABCJS.write.glyphs.getSymbolWidth(symbol) + 2;
|
38
|
+
}, this);
|
39
|
+
return abselem;
|
40
|
+
};
|
41
|
+
})();
|