abcjs 6.2.2 → 6.3.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.
- package/README.md +4 -0
- package/RELEASE.md +78 -0
- package/abc2xml_239/abc2xml.html +769 -0
- package/abc2xml_239/abc2xml.py +2248 -0
- package/abc2xml_239/abc2xml_changelog.html +124 -0
- package/abc2xml_239/lazy-river.abc +26 -0
- package/abc2xml_239/lazy-river.xml +3698 -0
- package/abc2xml_239/mean-to-me.abc +22 -0
- package/abc2xml_239/mean-to-me.xml +2954 -0
- package/abc2xml_239/pyparsing.py +3672 -0
- package/abc2xml_239/pyparsing.pyc +0 -0
- package/dist/abcjs-basic-min.js +2 -2
- package/dist/abcjs-basic.js +909 -485
- package/dist/abcjs-basic.js.map +1 -1
- package/dist/abcjs-plugin-min.js +2 -2
- package/index.js +2 -0
- package/package.json +1 -1
- package/plugin.js +1 -1
- package/src/api/abc_tablatures.js +51 -13
- package/src/api/abc_tunebook_svg.js +5 -3
- package/src/parse/abc_parse_directive.js +17 -16
- package/src/parse/abc_parse_header.js +22 -19
- package/src/parse/abc_parse_music.js +18 -53
- package/src/parse/abc_parse_settings.js +165 -0
- package/src/parse/abc_tokenizer.js +72 -7
- package/src/parse/tune-builder.js +60 -1
- package/src/synth/create-synth.js +4 -0
- package/src/synth/place-note.js +6 -0
- package/src/synth/play-event.js +7 -5
- package/src/synth/synth-controller.js +6 -2
- package/src/tablatures/instruments/string-patterns.js +11 -0
- package/src/tablatures/instruments/{guitar/guitar-patterns.js → tab-string-patterns.js} +6 -6
- package/src/tablatures/instruments/{violin/tab-violin.js → tab-string.js} +13 -11
- package/src/tablatures/tab-absolute-elements.js +19 -9
- package/src/tablatures/tab-renderer.js +24 -10
- package/src/test/abc_parser_lint.js +1 -0
- package/src/write/creation/abstract-engraver.js +9 -2
- package/src/write/creation/add-chord.js +102 -82
- package/src/write/creation/add-text-if.js +2 -2
- package/src/write/creation/decoration.js +16 -8
- package/src/write/creation/elements/bottom-text.js +62 -47
- package/src/write/creation/elements/rich-text.js +51 -0
- package/src/write/creation/elements/top-text.js +37 -11
- package/src/write/creation/glyphs.js +2 -2
- package/src/write/draw/absolute.js +4 -1
- package/src/write/draw/draw.js +13 -4
- package/src/write/draw/glissando.js +1 -0
- package/src/write/draw/non-music.js +3 -1
- package/src/write/draw/relative.js +1 -1
- package/src/write/draw/set-paper-size.js +1 -1
- package/src/write/draw/tempo.js +1 -1
- package/src/write/draw/text.js +10 -0
- package/src/write/draw/tie.js +9 -1
- package/src/write/engraver-controller.js +58 -11
- package/src/write/helpers/classes.js +1 -1
- package/src/write/helpers/get-font-and-attr.js +8 -1
- package/src/write/helpers/get-text-size.js +8 -1
- package/src/write/interactive/selection.js +6 -0
- package/src/write/layout/layout.js +33 -3
- package/src/write/svg.js +30 -0
- package/temp.txt +50 -0
- package/types/index.d.ts +74 -26
- package/version.js +1 -1
- package/.github/workflows/tests.yml +0 -29
- package/src/tablatures/instruments/guitar/tab-guitar.js +0 -48
- package/src/tablatures/instruments/violin/violin-patterns.js +0 -23
|
@@ -11,6 +11,7 @@ function drawGlissando(renderer, params, selectables) {
|
|
|
11
11
|
var rightY = renderer.calcY(params.anchor2.heads[0].pitch)
|
|
12
12
|
var leftX = params.anchor1.x + params.anchor1.w / 2
|
|
13
13
|
var rightX = params.anchor2.x + params.anchor2.w / 2
|
|
14
|
+
|
|
14
15
|
var len = lineLength(leftX, leftY, rightX, rightY)
|
|
15
16
|
var marginLeft = params.anchor1.w / 2 + margin
|
|
16
17
|
var marginRight = params.anchor2.w / 2 + margin
|
|
@@ -8,12 +8,14 @@ function nonMusic(renderer, obj, selectables) {
|
|
|
8
8
|
renderer.absolutemoveY(row.absmove);
|
|
9
9
|
} else if (row.move) {
|
|
10
10
|
renderer.moveY(row.move);
|
|
11
|
-
} else if (row.text) {
|
|
11
|
+
} else if (row.text || row.phrases) {
|
|
12
12
|
var x = row.left ? row.left : 0;
|
|
13
13
|
var el = renderText(renderer, {
|
|
14
14
|
x: x,
|
|
15
15
|
y: renderer.y,
|
|
16
16
|
text: row.text,
|
|
17
|
+
phrases: row.phrases,
|
|
18
|
+
'dominant-baseline': row['dominant-baseline'],
|
|
17
19
|
type: row.font,
|
|
18
20
|
klass: row.klass,
|
|
19
21
|
name: row.name,
|
|
@@ -27,7 +27,7 @@ function drawRelativeElement(renderer, params, bartop) {
|
|
|
27
27
|
case "tabNumber":
|
|
28
28
|
var hAnchor = "middle";
|
|
29
29
|
var tabFont = "tabnumberfont";
|
|
30
|
-
var tabClass = 'tab-number';
|
|
30
|
+
var tabClass = 'abcjs-tab-number';
|
|
31
31
|
if (params.isGrace) {
|
|
32
32
|
tabFont = "tabgracefont";
|
|
33
33
|
y += 2.5;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
function setPaperSize(renderer, maxwidth, scale, responsive) {
|
|
2
|
-
var w = (maxwidth + renderer.padding.right) * scale;
|
|
2
|
+
var w = (maxwidth + renderer.padding.left + renderer.padding.right) * scale;
|
|
3
3
|
var h = (renderer.y + renderer.padding.bottom) * scale;
|
|
4
4
|
if (renderer.isPrint)
|
|
5
5
|
h = Math.max(h, 1056); // 11in x 72pt/in x 1.33px/pt
|
package/src/write/draw/tempo.js
CHANGED
|
@@ -16,7 +16,7 @@ function drawTempo(renderer, params) {
|
|
|
16
16
|
var text;
|
|
17
17
|
var size;
|
|
18
18
|
if (params.tempo.preString) {
|
|
19
|
-
text = renderText(renderer, { x: x, y: y, text: params.tempo.preString, type: 'tempofont', klass: 'abcjs-tempo', anchor: "start", noClass: true,
|
|
19
|
+
text = renderText(renderer, { x: x, y: y, text: params.tempo.preString, type: 'tempofont', klass: 'abcjs-tempo', anchor: "start", noClass: true, name: "pre" }, true);
|
|
20
20
|
size = renderer.controller.getTextSize.calc(params.tempo.preString, 'tempofont', 'tempo', text);
|
|
21
21
|
var preWidth = size.width;
|
|
22
22
|
var charWidth = preWidth / params.tempo.preString.length; // Just get some average number to increase the spacing.
|
package/src/write/draw/text.js
CHANGED
|
@@ -2,6 +2,14 @@ var roundNumber = require("./round-number");
|
|
|
2
2
|
|
|
3
3
|
function renderText(renderer, params, alreadyInGroup) {
|
|
4
4
|
var y = params.y;
|
|
5
|
+
|
|
6
|
+
// TODO-PER: Probably need to merge the regular text and rich text better. At the least, rich text loses the font box.
|
|
7
|
+
if (params.phrases) {
|
|
8
|
+
//richTextLine = function (phrases, x, y, klass, anchor, target)
|
|
9
|
+
var elem = renderer.paper.richTextLine(params.phrases, params.x, params.y, params.klass, params.anchor);
|
|
10
|
+
return elem;
|
|
11
|
+
}
|
|
12
|
+
|
|
5
13
|
if (params.lane) {
|
|
6
14
|
var laneMargin = params.dim.font.size * 0.25;
|
|
7
15
|
y += (params.dim.font.size + laneMargin) * params.lane;
|
|
@@ -15,6 +23,8 @@ function renderText(renderer, params, alreadyInGroup) {
|
|
|
15
23
|
hash = renderer.controller.getFontAndAttr.calc(params.type, params.klass);
|
|
16
24
|
if (params.anchor)
|
|
17
25
|
hash.attr["text-anchor"] = params.anchor;
|
|
26
|
+
if (params['dominant-baseline'])
|
|
27
|
+
hash.attr["dominant-baseline"] = params['dominant-baseline'];
|
|
18
28
|
hash.attr.x = params.x;
|
|
19
29
|
hash.attr.y = y;
|
|
20
30
|
if (!params.centerVertically)
|
package/src/write/draw/tie.js
CHANGED
|
@@ -17,7 +17,15 @@ function drawTie(renderer, params, linestartx, lineendx, selectables) {
|
|
|
17
17
|
klass = "abcjs-hint";
|
|
18
18
|
var fudgeY = params.fixedY ? 1.5 : 0; // TODO-PER: This just compensates for drawArc, which contains too much knowledge of ties and slurs.
|
|
19
19
|
var el = drawArc(renderer, params.startX, params.endX, params.startY + fudgeY, params.endY + fudgeY, params.above, klass, params.isTie, params.dotted);
|
|
20
|
-
|
|
20
|
+
var startChar = -1
|
|
21
|
+
// This gets the start and end points of the contents of the slur. We assume that the parenthesis are just to the outside of that.
|
|
22
|
+
if (params.anchor1 && !params.isTie)
|
|
23
|
+
startChar = params.anchor1.parent.abcelem.startChar - 1
|
|
24
|
+
var endChar = -1
|
|
25
|
+
if (params.anchor2 && !params.isTie)
|
|
26
|
+
endChar = params.anchor2.parent.abcelem.endChar + 1
|
|
27
|
+
|
|
28
|
+
selectables.wrapSvgEl({ el_type: "slur", startChar: startChar, endChar: endChar }, el);
|
|
21
29
|
return [el];
|
|
22
30
|
}
|
|
23
31
|
|
|
@@ -40,6 +40,7 @@ var EngraverController = function (paper, params) {
|
|
|
40
40
|
this.responsive = params.responsive;
|
|
41
41
|
this.space = 3 * spacing.SPACE;
|
|
42
42
|
this.initialClef = params.initialClef;
|
|
43
|
+
this.expandToWidest = !!params.expandToWidest;
|
|
43
44
|
this.scale = params.scale ? parseFloat(params.scale) : 0;
|
|
44
45
|
this.classes = new Classes({ shouldAddClasses: params.add_classes });
|
|
45
46
|
if (!(this.scale > 0.1))
|
|
@@ -64,6 +65,8 @@ var EngraverController = function (paper, params) {
|
|
|
64
65
|
this.renderer.showDebug = params.showDebug;
|
|
65
66
|
if (params.jazzchords)
|
|
66
67
|
this.jazzchords = params.jazzchords;
|
|
68
|
+
if (params.accentAbove)
|
|
69
|
+
this.accentAbove = params.accentAbove;
|
|
67
70
|
if (params.germanAlphabet)
|
|
68
71
|
this.germanAlphabet = params.germanAlphabet;
|
|
69
72
|
if (params.lineThickness)
|
|
@@ -122,6 +125,7 @@ EngraverController.prototype.getMeasureWidths = function (abcTune) {
|
|
|
122
125
|
this.reset();
|
|
123
126
|
this.getFontAndAttr = new GetFontAndAttr(abcTune.formatting, this.classes);
|
|
124
127
|
this.getTextSize = new GetTextSize(this.getFontAndAttr, this.renderer.paper);
|
|
128
|
+
var origJazzChords = this.jazzchords
|
|
125
129
|
|
|
126
130
|
this.setupTune(abcTune, 0);
|
|
127
131
|
this.constructTuneElements(abcTune);
|
|
@@ -169,6 +173,7 @@ EngraverController.prototype.getMeasureWidths = function (abcTune) {
|
|
|
169
173
|
} else
|
|
170
174
|
needNewSection = true;
|
|
171
175
|
}
|
|
176
|
+
this.jazzchords = origJazzChords
|
|
172
177
|
return ret;
|
|
173
178
|
};
|
|
174
179
|
|
|
@@ -177,6 +182,8 @@ EngraverController.prototype.setupTune = function (abcTune, tuneNumber) {
|
|
|
177
182
|
|
|
178
183
|
if (abcTune.formatting.jazzchords !== undefined)
|
|
179
184
|
this.jazzchords = abcTune.formatting.jazzchords;
|
|
185
|
+
if (abcTune.formatting.accentAbove !== undefined)
|
|
186
|
+
this.accentAbove = abcTune.formatting.accentAbove;
|
|
180
187
|
|
|
181
188
|
this.renderer.newTune(abcTune);
|
|
182
189
|
this.engraver = new AbstractEngraver(this.getTextSize, tuneNumber, {
|
|
@@ -186,6 +193,7 @@ EngraverController.prototype.setupTune = function (abcTune, tuneNumber) {
|
|
|
186
193
|
percmap: abcTune.formatting.percmap,
|
|
187
194
|
initialClef: this.initialClef,
|
|
188
195
|
jazzchords: this.jazzchords,
|
|
196
|
+
accentAbove: this.accentAbove,
|
|
189
197
|
germanAlphabet: this.germanAlphabet
|
|
190
198
|
});
|
|
191
199
|
this.engraver.setStemHeight(this.renderer.spacing.stemHeight);
|
|
@@ -205,7 +213,7 @@ EngraverController.prototype.setupTune = function (abcTune, tuneNumber) {
|
|
|
205
213
|
};
|
|
206
214
|
|
|
207
215
|
EngraverController.prototype.constructTuneElements = function (abcTune) {
|
|
208
|
-
abcTune.topText = new TopText(abcTune.metaText, abcTune.metaTextInfo, abcTune.formatting, abcTune.lines, this.width, this.renderer.isPrint, this.renderer.padding.left, this.renderer.spacing, this.getTextSize);
|
|
216
|
+
abcTune.topText = new TopText(abcTune.metaText, abcTune.metaTextInfo, abcTune.formatting, abcTune.lines, this.width, this.renderer.isPrint, this.renderer.padding.left, this.renderer.spacing, this.classes.shouldAddClasses, this.getTextSize);
|
|
209
217
|
|
|
210
218
|
// Generate the raw staff line data
|
|
211
219
|
var i;
|
|
@@ -232,35 +240,74 @@ EngraverController.prototype.constructTuneElements = function (abcTune) {
|
|
|
232
240
|
abcLine.nonMusic = new Separator(abcLine.separator.spaceAbove, abcLine.separator.lineLength, abcLine.separator.spaceBelow);
|
|
233
241
|
}
|
|
234
242
|
}
|
|
235
|
-
abcTune.bottomText = new BottomText(abcTune.metaText, this.width, this.renderer.isPrint, this.renderer.padding.left, this.renderer.spacing, this.getTextSize);
|
|
243
|
+
abcTune.bottomText = new BottomText(abcTune.metaText, this.width, this.renderer.isPrint, this.renderer.padding.left, this.renderer.spacing, this.classes.shouldAddClasses, this.getTextSize);
|
|
236
244
|
};
|
|
237
245
|
|
|
238
246
|
EngraverController.prototype.engraveTune = function (abcTune, tuneNumber, lineOffset) {
|
|
239
|
-
var scale = this.setupTune(abcTune, tuneNumber);
|
|
240
247
|
|
|
248
|
+
var origJazzChords = this.jazzchords
|
|
249
|
+
var scale = this.setupTune(abcTune, tuneNumber);
|
|
250
|
+
|
|
241
251
|
// Create all of the element objects that will appear on the page.
|
|
242
252
|
this.constructTuneElements(abcTune);
|
|
243
|
-
|
|
253
|
+
|
|
254
|
+
//Set the top text now that we know the width
|
|
255
|
+
|
|
244
256
|
// Do all the positioning, both horizontally and vertically
|
|
245
|
-
var maxWidth = layout(this.renderer, abcTune, this.width, this.space);
|
|
257
|
+
var maxWidth = layout(this.renderer, abcTune, this.width, this.space, this.expandToWidest);
|
|
258
|
+
|
|
259
|
+
//Set the top text now that we know the width
|
|
260
|
+
if (this.expandToWidest && maxWidth > this.width + 1) {
|
|
261
|
+
|
|
262
|
+
abcTune.topText = new TopText(abcTune.metaText, abcTune.metaTextInfo, abcTune.formatting, abcTune.lines, maxWidth, this.renderer.isPrint, this.renderer.padding.left, this.renderer.spacing, this.classes.shouldAddClasses, this.getTextSize);
|
|
263
|
+
|
|
264
|
+
if ((abcTune.lines)&&(abcTune.lines.length > 0)){
|
|
265
|
+
var nlines = abcTune.lines.length;
|
|
266
|
+
|
|
267
|
+
for (var i=0;i<nlines;++i){
|
|
268
|
+
var entry = abcTune.lines[i];
|
|
269
|
+
if (entry.nonMusic){
|
|
270
|
+
if ((entry.nonMusic.rows) && (entry.nonMusic.rows.length > 0)){
|
|
271
|
+
var nRows = entry.nonMusic.rows.length;
|
|
272
|
+
for (var j=0;j<nRows;++j){
|
|
273
|
+
var thisRow = entry.nonMusic.rows[j];
|
|
274
|
+
// Recenter the element if it's a subtitle or centered text
|
|
275
|
+
if (thisRow.left){
|
|
276
|
+
if (entry.subtitle){
|
|
277
|
+
thisRow.left = (maxWidth/2) + this.renderer.padding.left;
|
|
278
|
+
} else {
|
|
279
|
+
if ((entry.text)&&(entry.text.length>0)){
|
|
280
|
+
if (entry.text[0].center){
|
|
281
|
+
thisRow.left = (maxWidth/2) + this.renderer.padding.left;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
246
292
|
|
|
247
293
|
// Deal with tablature for staff
|
|
248
294
|
if (abcTune.tablatures) {
|
|
249
|
-
|
|
295
|
+
tablatures.layoutTablatures(this.renderer, abcTune);
|
|
250
296
|
}
|
|
251
|
-
|
|
297
|
+
|
|
252
298
|
// Do all the writing to the SVG
|
|
253
299
|
var ret = draw(this.renderer, this.classes, abcTune, this.width, maxWidth, this.responsive, scale, this.selectTypes, tuneNumber, lineOffset);
|
|
254
300
|
this.staffgroups = ret.staffgroups;
|
|
255
301
|
this.selectables = ret.selectables;
|
|
256
|
-
|
|
257
302
|
if (this.oneSvgPerLine) {
|
|
258
|
-
|
|
259
|
-
|
|
303
|
+
var div = this.renderer.paper.svg.parentNode;
|
|
304
|
+
this.svgs = splitSvgIntoLines(this.renderer, div, abcTune.metaText.title, this.responsive);
|
|
260
305
|
} else {
|
|
261
|
-
|
|
306
|
+
this.svgs = [this.renderer.paper.svg];
|
|
262
307
|
}
|
|
263
308
|
setupSelection(this, this.svgs);
|
|
309
|
+
|
|
310
|
+
this.jazzchords = origJazzChords
|
|
264
311
|
};
|
|
265
312
|
|
|
266
313
|
function splitSvgIntoLines(renderer, output, title, responsive) {
|
|
@@ -79,7 +79,7 @@ Classes.prototype.generate = function (c) {
|
|
|
79
79
|
return "";
|
|
80
80
|
var ret = [];
|
|
81
81
|
if (c && c.length > 0) ret.push(c);
|
|
82
|
-
if (c === "tab-number") // TODO-PER-HACK! straighten out the tablature
|
|
82
|
+
if (c === "abcjs-tab-number") // TODO-PER-HACK! straighten out the tablature
|
|
83
83
|
return ret.join(' ')
|
|
84
84
|
if (c === "text instrument-name")
|
|
85
85
|
return "abcjs-text abcjs-instrument-name"
|
|
@@ -14,6 +14,13 @@ GetFontAndAttr.prototype.updateFonts = function (fontOverrides) {
|
|
|
14
14
|
this.formatting.vocalfont = fontOverrides.vocalfont;
|
|
15
15
|
};
|
|
16
16
|
|
|
17
|
+
GetFontAndAttr.prototype.getFamily = function (type) {
|
|
18
|
+
if (type[0] === '"' && type[type.length-1] === '"') {
|
|
19
|
+
return type.substring(1, type.length-1)
|
|
20
|
+
}
|
|
21
|
+
return type
|
|
22
|
+
};
|
|
23
|
+
|
|
17
24
|
GetFontAndAttr.prototype.calc = function (type, klass) {
|
|
18
25
|
var font;
|
|
19
26
|
if (typeof type === 'string') {
|
|
@@ -30,7 +37,7 @@ GetFontAndAttr.prototype.calc = function (type, klass) {
|
|
|
30
37
|
|
|
31
38
|
var attr = {
|
|
32
39
|
"font-size": font.size, 'font-style': font.style,
|
|
33
|
-
"font-family": font.face, 'font-weight': font.weight, 'text-decoration': font.decoration,
|
|
40
|
+
"font-family": this.getFamily(font.face), 'font-weight': font.weight, 'text-decoration': font.decoration,
|
|
34
41
|
'class': this.classes.generate(klass)
|
|
35
42
|
};
|
|
36
43
|
return { font: font, attr: attr };
|
|
@@ -11,6 +11,13 @@ GetTextSize.prototype.attr = function (type, klass) {
|
|
|
11
11
|
return this.getFontAndAttr.calc(type, klass);
|
|
12
12
|
};
|
|
13
13
|
|
|
14
|
+
GetTextSize.prototype.getFamily = function (type) {
|
|
15
|
+
if (type[0] === '"' && type[type.length-1] === '"') {
|
|
16
|
+
return type.substring(1, type.length-1)
|
|
17
|
+
}
|
|
18
|
+
return type
|
|
19
|
+
};
|
|
20
|
+
|
|
14
21
|
GetTextSize.prototype.calc = function (text, type, klass, el) {
|
|
15
22
|
var hash;
|
|
16
23
|
// This can be passed in either a string or a font. If it is a string it names one of the standard fonts.
|
|
@@ -28,7 +35,7 @@ GetTextSize.prototype.calc = function (text, type, klass, el) {
|
|
|
28
35
|
attr: {
|
|
29
36
|
"font-size": type.size,
|
|
30
37
|
"font-style": type.style,
|
|
31
|
-
"font-family": type.face,
|
|
38
|
+
"font-family": this.getFamily(type.face),
|
|
32
39
|
"font-weight": type.weight,
|
|
33
40
|
"text-decoration": type.decoration,
|
|
34
41
|
"class": this.getFontAndAttr.classes.generate(klass)
|
|
@@ -127,6 +127,8 @@ function keyboardSelection(ev) {
|
|
|
127
127
|
}
|
|
128
128
|
|
|
129
129
|
function findElementInHistory(selectables, el) {
|
|
130
|
+
if (!el)
|
|
131
|
+
return -1;
|
|
130
132
|
for (var i = 0; i < selectables.length; i++) {
|
|
131
133
|
if (el.dataset.index === selectables[i].svgEl.dataset.index)
|
|
132
134
|
return i;
|
|
@@ -195,9 +197,13 @@ function getBestMatchCoordinates(dim, ev, scale) {
|
|
|
195
197
|
|
|
196
198
|
function getTarget(target) {
|
|
197
199
|
// This searches up the dom for the first item containing the attribute "selectable", or stopping at the SVG.
|
|
200
|
+
if (!target)
|
|
201
|
+
return null;
|
|
198
202
|
if (target.tagName === "svg")
|
|
199
203
|
return target;
|
|
200
204
|
|
|
205
|
+
if (!target.getAttribute)
|
|
206
|
+
return null;
|
|
201
207
|
var found = target.getAttribute("selectable");
|
|
202
208
|
while (!found) {
|
|
203
209
|
if (!target.parentElement)
|
|
@@ -3,7 +3,7 @@ var setUpperAndLowerElements = require('./set-upper-and-lower-elements');
|
|
|
3
3
|
var layoutStaffGroup = require('./staff-group');
|
|
4
4
|
var getLeftEdgeOfStaff = require('./get-left-edge-of-staff');
|
|
5
5
|
|
|
6
|
-
var layout = function (renderer, abctune, width, space) {
|
|
6
|
+
var layout = function (renderer, abctune, width, space, expandToWidest) {
|
|
7
7
|
var i;
|
|
8
8
|
var abcLine;
|
|
9
9
|
// Adjust the x-coordinates to their absolute positions
|
|
@@ -11,8 +11,14 @@ var layout = function (renderer, abctune, width, space) {
|
|
|
11
11
|
for (i = 0; i < abctune.lines.length; i++) {
|
|
12
12
|
abcLine = abctune.lines[i];
|
|
13
13
|
if (abcLine.staff) {
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
// console.log("=== line", i)
|
|
15
|
+
var thisWidth = setXSpacing(renderer, maxWidth, space, abcLine.staffGroup, abctune.formatting, i === abctune.lines.length - 1, false);
|
|
16
|
+
// console.log(thisWidth, maxWidth)
|
|
17
|
+
if (Math.round(thisWidth) > Math.round(maxWidth)) { // to take care of floating point weirdness
|
|
18
|
+
maxWidth = thisWidth
|
|
19
|
+
if (expandToWidest)
|
|
20
|
+
i = -1 // do the calculations over with the new width
|
|
21
|
+
}
|
|
16
22
|
}
|
|
17
23
|
}
|
|
18
24
|
|
|
@@ -41,15 +47,39 @@ var setXSpacing = function (renderer, width, space, staffGroup, formatting, isLa
|
|
|
41
47
|
var leftEdge = getLeftEdgeOfStaff(renderer, staffGroup.getTextSize, staffGroup.voices, staffGroup.brace, staffGroup.bracket);
|
|
42
48
|
var newspace = space;
|
|
43
49
|
for (var it = 0; it < 8; it++) { // TODO-PER: shouldn't need multiple passes, but each pass gets it closer to the right spacing. (Only affects long lines: normal lines break out of this loop quickly.)
|
|
50
|
+
// console.log("iteration", it)
|
|
51
|
+
// dumpGroup("before", staffGroup)
|
|
44
52
|
var ret = layoutStaffGroup(newspace, renderer, debug, staffGroup, leftEdge);
|
|
53
|
+
// dumpGroup("after",staffGroup)
|
|
45
54
|
newspace = calcHorizontalSpacing(isLastLine, formatting.stretchlast, width + renderer.padding.left, staffGroup.w, newspace, ret.spacingUnits, ret.minSpace, renderer.padding.left + renderer.padding.right);
|
|
46
55
|
if (debug)
|
|
47
56
|
console.log("setXSpace", it, staffGroup.w, newspace, staffGroup.minspace);
|
|
48
57
|
if (newspace === null) break;
|
|
49
58
|
}
|
|
50
59
|
centerWholeRests(staffGroup.voices);
|
|
60
|
+
return staffGroup.w - leftEdge
|
|
51
61
|
};
|
|
52
62
|
|
|
63
|
+
// function dumpGroup(label, staffGroup) {
|
|
64
|
+
// var output = {
|
|
65
|
+
// line: staffGroup.line,
|
|
66
|
+
// w: staffGroup.w,
|
|
67
|
+
// voice: {
|
|
68
|
+
// i: staffGroup.voices[0].i,
|
|
69
|
+
// minx: staffGroup.voices[0].minx,
|
|
70
|
+
// nextx: staffGroup.voices[0].nextx,
|
|
71
|
+
// spacingduration: staffGroup.voices[0].spacingduration,
|
|
72
|
+
// w: staffGroup.voices[0].w,
|
|
73
|
+
// children: [],
|
|
74
|
+
// }
|
|
75
|
+
// }
|
|
76
|
+
// for (var i = 0; i < staffGroup.voices[0].children.length; i++) {
|
|
77
|
+
// var child = staffGroup.voices[0].children[i]
|
|
78
|
+
// output.voice.children.push({ fixedW: child.fixed.w, w: child.w, x: child.x, type: child.type })
|
|
79
|
+
// }
|
|
80
|
+
// console.log(label,output)
|
|
81
|
+
// }
|
|
82
|
+
|
|
53
83
|
function calcHorizontalSpacing(isLastLine, stretchLast, targetWidth, lineWidth, spacing, spacingUnits, minSpace, padding) {
|
|
54
84
|
if (isLastLine) {
|
|
55
85
|
if (stretchLast === undefined) {
|
package/src/write/svg.js
CHANGED
|
@@ -211,6 +211,36 @@ Svg.prototype.text = function (text, attr, target) {
|
|
|
211
211
|
return el;
|
|
212
212
|
};
|
|
213
213
|
|
|
214
|
+
Svg.prototype.richTextLine = function (phrases, x, y, klass, anchor, target) {
|
|
215
|
+
var el = document.createElementNS(svgNS, 'text');
|
|
216
|
+
el.setAttribute("stroke", "none");
|
|
217
|
+
el.setAttribute("class", klass);
|
|
218
|
+
el.setAttribute("x", x);
|
|
219
|
+
el.setAttribute("y", y);
|
|
220
|
+
el.setAttribute("text-anchor", anchor);
|
|
221
|
+
el.setAttribute("dominant-baseline", "middle");
|
|
222
|
+
|
|
223
|
+
for (var i = 0; i < phrases.length; i++) {
|
|
224
|
+
var phrase = phrases[i]
|
|
225
|
+
var tspan = document.createElementNS(svgNS, 'tspan');
|
|
226
|
+
var attrs = Object.keys(phrase.attrs)
|
|
227
|
+
for (var j = 0; j < attrs.length; j++) {
|
|
228
|
+
var value = phrase.attrs[attrs[j]]
|
|
229
|
+
if (value !== '')
|
|
230
|
+
tspan.setAttribute(attrs[j], value)
|
|
231
|
+
}
|
|
232
|
+
tspan.textContent = phrase.content;
|
|
233
|
+
|
|
234
|
+
el.appendChild(tspan);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
if (target)
|
|
238
|
+
target.appendChild(el);
|
|
239
|
+
else
|
|
240
|
+
this.append(el);
|
|
241
|
+
return el;
|
|
242
|
+
}
|
|
243
|
+
|
|
214
244
|
Svg.prototype.guessWidth = function (text, attr) {
|
|
215
245
|
var svg = this.createDummySvg();
|
|
216
246
|
var el = this.text(text, attr, svg);
|
package/temp.txt
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
## Features
|
|
2
|
+
|
|
3
|
+
### Tablature
|
|
4
|
+
* Add tab feature `hideTabSymbol`
|
|
5
|
+
* Add 5-string tab named "fiveString"
|
|
6
|
+
* Make "mandolin" and "fiddle" synonyms for "violin" in tablature.
|
|
7
|
+
|
|
8
|
+
### Synth
|
|
9
|
+
* change the default synth control options for "play" and "progress" to be true
|
|
10
|
+
* expose the MIDI creator function
|
|
11
|
+
* Add a `getIsRunning()` function to enable play/pause
|
|
12
|
+
* allow passing in soundfont and debug callback when playing an event directly.
|
|
13
|
+
|
|
14
|
+
### Rich Text
|
|
15
|
+
* allow up to 9 custom fonts in `%%setfont`
|
|
16
|
+
* for rich text fields, escape two dollar signs
|
|
17
|
+
* allow rich text in all non-music fields
|
|
18
|
+
* give all non-music fields a unique class
|
|
19
|
+
|
|
20
|
+
### Miscellaneous
|
|
21
|
+
* add abcjs-notehead class to note heads;
|
|
22
|
+
* add `accentAbove` parameter
|
|
23
|
+
* handle numbered tune names in the reverser
|
|
24
|
+
* support reversing tune names with ", a" and ", an", with a variable amount of whitespace and case-insensitive
|
|
25
|
+
* Add Glissando Synonyms
|
|
26
|
+
* Put start and end char on slurs so they can be selected.
|
|
27
|
+
* Add `expandToWidest` option
|
|
28
|
+
|
|
29
|
+
## Bugs
|
|
30
|
+
* fix placement of tab staff when there is no label
|
|
31
|
+
* fix font placement bugs
|
|
32
|
+
* remove spurious quotes in font name in svg attribute
|
|
33
|
+
* Fix the name of the `abcjs-tab-number` class
|
|
34
|
+
* fix crash when skipping a staff when creating tablature
|
|
35
|
+
* Fix tab staff height when there is a label
|
|
36
|
+
* Fix for crash when rendering multiple tab staves
|
|
37
|
+
* Offset breath mark to the right
|
|
38
|
+
* Center text when using `expandToWidest` set true
|
|
39
|
+
* fix placement of triangle notehead
|
|
40
|
+
* `afterParsing` now works with line wrapping.
|
|
41
|
+
* Add paddingleft to the size of the SVG - it was cut off if the padding was larger than the default.
|
|
42
|
+
* Guard against crash when the synth note wasn't loaded.
|
|
43
|
+
* protect against spurious mouse click in selection
|
|
44
|
+
* Fix bug in Firefox that cuts off the last line of the SVG
|
|
45
|
+
|
|
46
|
+
## Documentation
|
|
47
|
+
* add missing typescript types
|
|
48
|
+
* fix synth control types
|
|
49
|
+
* fixed some typescript types in the TimingCallbacks
|
|
50
|
+
* TimingEvent is now NoteTimingEvent
|