abcjs 6.0.0-beta.32 → 6.0.0-beta.36
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 +13 -7
- package/RELEASE.md +130 -0
- package/dist/abcjs-basic-min.js +2 -2
- package/dist/abcjs-basic.js +3763 -825
- package/dist/abcjs-basic.js.map +1 -1
- package/dist/abcjs-plugin-min.js +2 -2
- package/dist/report-basic.html +37 -0
- package/dist/report-before-glyph-compress.html +37 -0
- package/dist/report-brown-ts-target-es5.html +37 -0
- package/dist/report-dev-orig-no-babel.html +37 -0
- package/dist/report-synth.html +37 -0
- package/docker-build.sh +1 -0
- package/glyphs.json +1 -0
- package/package.json +9 -9
- package/src/api/abc_tablatures.js +144 -0
- package/src/api/abc_timing_callbacks.js +49 -26
- package/src/api/abc_tunebook.js +10 -1
- package/src/api/abc_tunebook_svg.js +16 -22
- package/src/data/abc_tune.js +90 -25
- package/src/data/deline-tune.js +199 -0
- package/src/edit/abc_editor.js +33 -11
- package/src/midi/abc_midi_create.js +6 -2
- package/src/parse/abc_parse.js +10 -6
- package/src/parse/abc_parse_directive.js +19 -12
- package/src/parse/abc_parse_header.js +12 -12
- package/src/parse/abc_parse_music.js +15 -5
- package/src/parse/tune-builder.js +23 -30
- package/src/parse/wrap_lines.js +13 -36
- package/src/synth/abc_midi_flattener.js +44 -29
- package/src/synth/abc_midi_sequencer.js +52 -13
- package/src/synth/create-synth.js +22 -7
- package/src/synth/load-note.js +31 -65
- package/src/synth/place-note.js +59 -60
- package/src/synth/register-audio-context.js +4 -1
- package/src/synth/supports-audio.js +9 -8
- package/src/synth/synth-controller.js +5 -3
- package/src/tablatures/instruments/guitar/guitar-fonts.js +19 -0
- package/src/tablatures/instruments/guitar/guitar-patterns.js +23 -0
- package/src/tablatures/instruments/guitar/tab-guitar.js +50 -0
- package/src/tablatures/instruments/string-patterns.js +277 -0
- package/src/tablatures/instruments/string-tablature.js +56 -0
- package/src/tablatures/instruments/tab-note.js +282 -0
- package/src/tablatures/instruments/tab-notes.js +41 -0
- package/src/tablatures/instruments/violin/tab-violin.js +47 -0
- package/src/tablatures/instruments/violin/violin-fonts.js +19 -0
- package/src/tablatures/instruments/violin/violin-patterns.js +23 -0
- package/src/tablatures/tab-absolute-elements.js +310 -0
- package/src/tablatures/tab-common.js +29 -0
- package/src/tablatures/tab-renderer.js +243 -0
- package/src/tablatures/transposer.js +110 -0
- package/src/test/abc_parser_lint.js +62 -6
- package/src/write/abc_absolute_element.js +2 -2
- package/src/write/abc_abstract_engraver.js +9 -7
- package/src/write/abc_create_key_signature.js +1 -0
- package/src/write/abc_create_note_head.js +1 -1
- package/src/write/abc_engraver_controller.js +22 -9
- package/src/write/abc_glyphs.js +5 -2
- package/src/write/abc_relative_element.js +11 -3
- package/src/write/abc_renderer.js +5 -1
- package/src/write/add-chord.js +5 -2
- package/src/write/add-text-if.js +33 -0
- package/src/write/bottom-text.js +8 -29
- package/src/write/draw/absolute.js +12 -14
- package/src/write/draw/brace.js +3 -3
- package/src/write/draw/crescendo.js +1 -1
- package/src/write/draw/draw.js +3 -4
- package/src/write/draw/dynamics.js +8 -1
- package/src/write/draw/ending.js +4 -3
- package/src/write/draw/group-elements.js +10 -8
- package/src/write/draw/non-music.js +11 -6
- package/src/write/draw/print-line.js +24 -0
- package/src/write/draw/print-stem.js +12 -11
- package/src/write/draw/print-symbol.js +11 -10
- package/src/write/draw/relative.js +33 -13
- package/src/write/draw/selectables.js +9 -6
- package/src/write/draw/staff-group.js +45 -9
- package/src/write/draw/staff-line.js +3 -17
- package/src/write/draw/staff.js +15 -2
- package/src/write/draw/tab-line.js +40 -0
- package/src/write/draw/tempo.js +7 -7
- package/src/write/draw/text.js +11 -4
- package/src/write/draw/tie.js +2 -2
- package/src/write/draw/triplet.js +3 -3
- package/src/write/draw/voice.js +10 -2
- package/src/write/format-jazz-chord.js +15 -0
- package/src/write/free-text.js +20 -12
- package/src/write/layout/VoiceElements.js +33 -1
- package/src/write/layout/beam.js +2 -0
- package/src/write/layout/staffGroup.js +37 -2
- package/src/write/layout/voice.js +2 -1
- package/src/write/selection.js +15 -5
- package/src/write/separator.js +1 -1
- package/src/write/subtitle.js +3 -3
- package/src/write/svg.js +41 -14
- package/src/write/top-text.js +19 -25
- package/types/index.d.ts +1007 -39
- package/version.js +1 -1
|
@@ -11,17 +11,12 @@ function drawAbsolute(renderer, params, bartop, selectables, staffPos) {
|
|
|
11
11
|
elementGroup.beginGroup(renderer.paper, renderer.controller);
|
|
12
12
|
for (var i=0; i<params.children.length; i++) {
|
|
13
13
|
var child = params.children[i];
|
|
14
|
-
var el;
|
|
15
14
|
switch (child.type) {
|
|
16
15
|
case "TempoElement":
|
|
17
|
-
|
|
18
|
-
if (el)
|
|
19
|
-
params.elemset = params.elemset.concat(el);
|
|
16
|
+
drawTempo(renderer, child);
|
|
20
17
|
break;
|
|
21
18
|
default:
|
|
22
|
-
|
|
23
|
-
if (el)
|
|
24
|
-
params.elemset.push(el);
|
|
19
|
+
drawRelativeElement(renderer, child, bartop);
|
|
25
20
|
}
|
|
26
21
|
}
|
|
27
22
|
var klass = params.type;
|
|
@@ -35,16 +30,19 @@ function drawAbsolute(renderer, params, bartop, selectables, staffPos) {
|
|
|
35
30
|
}
|
|
36
31
|
}
|
|
37
32
|
}
|
|
38
|
-
var g = elementGroup.endGroup(klass);
|
|
33
|
+
var g = elementGroup.endGroup(klass, params.type);
|
|
39
34
|
if (g) {
|
|
40
|
-
if (isTempo
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
selectables.add(params, params.elemset[0], false, staffPos);
|
|
35
|
+
if (isTempo) {
|
|
36
|
+
params.startChar = params.abcelem.startChar;
|
|
37
|
+
params.endChar = params.abcelem.endChar;
|
|
38
|
+
selectables.add(params, g, false, staffPos);
|
|
45
39
|
} else {
|
|
46
40
|
params.elemset.push(g);
|
|
47
|
-
|
|
41
|
+
var isSelectable = false;
|
|
42
|
+
if (params.type === 'note' || params.type === 'tabNumber') {
|
|
43
|
+
isSelectable = true;
|
|
44
|
+
}
|
|
45
|
+
selectables.add(params, g, isSelectable, staffPos);
|
|
48
46
|
}
|
|
49
47
|
} else if (params.elemset.length > 0)
|
|
50
48
|
selectables.add(params, params.elemset[0], params.type === 'note', staffPos);
|
package/src/write/draw/brace.js
CHANGED
|
@@ -45,7 +45,7 @@ function straightPath(renderer, xLeft, yTop, yBottom, type) {
|
|
|
45
45
|
-wCurve*0.1, -hCurve*0.3,
|
|
46
46
|
-wCurve, -hCurve-spacing.STEP // left bottom
|
|
47
47
|
);
|
|
48
|
-
return renderer.paper.path({path:pathString, stroke:renderer.foregroundColor, fill:renderer.foregroundColor, 'class': renderer.controller.classes.generate(type)});
|
|
48
|
+
return renderer.paper.path({path:pathString, stroke:renderer.foregroundColor, fill:renderer.foregroundColor, 'class': renderer.controller.classes.generate(type), "data-name": type});
|
|
49
49
|
}
|
|
50
50
|
|
|
51
51
|
function curvyPath(renderer, xLeft, yTop, yBottom, type) {
|
|
@@ -61,7 +61,7 @@ function curvyPath(renderer, xLeft, yTop, yBottom, type) {
|
|
|
61
61
|
[0, 17.5, -7.5, 6.6, -5, 20, 0],
|
|
62
62
|
[yHeight/2, yHeight/1.46, yHeight/1.22, yHeight, yHeight/1.19, yHeight/1.42, yHeight/2]);
|
|
63
63
|
|
|
64
|
-
return renderer.paper.path({path:pathString, stroke:renderer.foregroundColor, fill:renderer.foregroundColor, 'class': renderer.controller.classes.generate(type)});
|
|
64
|
+
return renderer.paper.path({path:pathString, stroke:renderer.foregroundColor, fill:renderer.foregroundColor, 'class': renderer.controller.classes.generate(type), "data-name": type});
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
function curve(xLeft, yTop, xCurve, yCurve) {
|
|
@@ -78,7 +78,7 @@ function curve(xLeft, yTop, xCurve, yCurve) {
|
|
|
78
78
|
var draw = function (renderer, xLeft, yTop, yBottom, type, header, selectables) {//Tony
|
|
79
79
|
var ret;
|
|
80
80
|
if (header) {
|
|
81
|
-
renderer.paper.openGroup({klass: renderer.controller.classes.generate("staff-extra voice-name")});
|
|
81
|
+
renderer.paper.openGroup({klass: renderer.controller.classes.generate("staff-extra voice-name"), "data-name": type});
|
|
82
82
|
var position = yTop + (yBottom - yTop) / 2;
|
|
83
83
|
position = position - renderer.controller.getTextSize.baselineToCenter(header, "voicefont", 'staff-extra voice-name', 0, 1);
|
|
84
84
|
|
|
@@ -32,7 +32,7 @@ var drawLine = function (renderer, y1, y2, y3, y4, left, right) {
|
|
|
32
32
|
|
|
33
33
|
var pathString = sprintf("M %f %f L %f %f M %f %f L %f %f",
|
|
34
34
|
left, y1, right, y2, left, y3, right, y4);
|
|
35
|
-
return printPath(renderer, {path:pathString, highlight: "stroke", stroke:renderer.foregroundColor, 'class': renderer.controller.classes.generate('dynamics decoration')});
|
|
35
|
+
return printPath(renderer, {path:pathString, highlight: "stroke", stroke:renderer.foregroundColor, 'class': renderer.controller.classes.generate('dynamics decoration'), "data-name": "dynamics"});
|
|
36
36
|
};
|
|
37
37
|
|
|
38
38
|
module.exports = drawCrescendo;
|
package/src/write/draw/draw.js
CHANGED
|
@@ -9,7 +9,6 @@ function draw(renderer, classes, abcTune, width, maxWidth, responsive, scale, se
|
|
|
9
9
|
renderer.moveY(renderer.padding.top);
|
|
10
10
|
nonMusic(renderer, abcTune.topText, selectables);
|
|
11
11
|
renderer.moveY(renderer.spacing.music);
|
|
12
|
-
|
|
13
12
|
var staffgroups = [];
|
|
14
13
|
for (var line = 0; line < abcTune.lines.length; line++) {
|
|
15
14
|
classes.incrLine();
|
|
@@ -20,7 +19,7 @@ function draw(renderer, classes, abcTune, width, maxWidth, responsive, scale, se
|
|
|
20
19
|
}
|
|
21
20
|
if (staffgroups.length >= 1)
|
|
22
21
|
addStaffPadding(renderer, renderer.spacing.staffSeparation, staffgroups[staffgroups.length - 1], abcLine.staffGroup);
|
|
23
|
-
var staffgroup = engraveStaffLine(renderer, abcLine.staffGroup, selectables);
|
|
22
|
+
var staffgroup = engraveStaffLine(renderer, abcLine.staffGroup, selectables,line);
|
|
24
23
|
staffgroup.line = line; // If there are non-music lines then the staffgroup array won't line up with the line array, so this keeps track.
|
|
25
24
|
staffgroups.push(staffgroup);
|
|
26
25
|
} else if (abcLine.nonMusic) {
|
|
@@ -35,8 +34,8 @@ function draw(renderer, classes, abcTune, width, maxWidth, responsive, scale, se
|
|
|
35
34
|
return { staffgroups: staffgroups, selectables: selectables.getElements() };
|
|
36
35
|
}
|
|
37
36
|
|
|
38
|
-
function engraveStaffLine(renderer, staffGroup, selectables) {
|
|
39
|
-
drawStaffGroup(renderer, staffGroup, selectables);
|
|
37
|
+
function engraveStaffLine(renderer, staffGroup, selectables,lineNumber) {
|
|
38
|
+
drawStaffGroup(renderer, staffGroup, selectables,lineNumber);
|
|
40
39
|
var height = staffGroup.height * spacing.STEP;
|
|
41
40
|
renderer.y += height;
|
|
42
41
|
return staffGroup;
|
|
@@ -5,7 +5,14 @@ function drawDynamics(renderer, params, selectables) {
|
|
|
5
5
|
window.console.error("Dynamic Element y-coordinate not set.");
|
|
6
6
|
var scalex = 1;
|
|
7
7
|
var scaley = 1;
|
|
8
|
-
var el = printSymbol(renderer, params.anchor.x, params.pitch, params.dec,
|
|
8
|
+
var el = printSymbol(renderer, params.anchor.x, params.pitch, params.dec, {
|
|
9
|
+
scalex: scalex,
|
|
10
|
+
scaley: scaley,
|
|
11
|
+
klass: renderer.controller.classes.generate('decoration dynamics'),
|
|
12
|
+
fill:renderer.foregroundColor,
|
|
13
|
+
stroke: "none",
|
|
14
|
+
name: "dynamics"
|
|
15
|
+
});
|
|
9
16
|
selectables.wrapSvgEl({el_type: "dynamicDecoration", startChar: -1, endChar: -1, decoration: params.dec}, el);
|
|
10
17
|
return [el];
|
|
11
18
|
}
|
package/src/write/draw/ending.js
CHANGED
|
@@ -25,8 +25,8 @@ function drawEnding(renderer, params, linestartx, lineendx, selectables) {
|
|
|
25
25
|
pathString += sprintf("M %f %f L %f %f ",
|
|
26
26
|
linestartx, y, lineendx, y);
|
|
27
27
|
|
|
28
|
-
renderer.paper.openGroup({klass: renderer.controller.classes.generate("ending")});
|
|
29
|
-
printPath(renderer, {path: pathString, stroke: renderer.foregroundColor, fill: renderer.foregroundColor});
|
|
28
|
+
renderer.paper.openGroup({klass: renderer.controller.classes.generate("ending"), "data-name": "ending"});
|
|
29
|
+
printPath(renderer, {path: pathString, stroke: renderer.foregroundColor, fill: renderer.foregroundColor, "data-name": "line"});
|
|
30
30
|
if (params.anchor1)
|
|
31
31
|
renderText(renderer, {
|
|
32
32
|
x: roundNumber(linestartx + 5),
|
|
@@ -35,7 +35,8 @@ function drawEnding(renderer, params, linestartx, lineendx, selectables) {
|
|
|
35
35
|
type: 'repeatfont',
|
|
36
36
|
klass: 'ending',
|
|
37
37
|
anchor: "start",
|
|
38
|
-
noClass: true
|
|
38
|
+
noClass: true,
|
|
39
|
+
name: params.text
|
|
39
40
|
});
|
|
40
41
|
var g = renderer.paper.closeGroup();
|
|
41
42
|
selectables.wrapSvgEl({el_type: "ending", startChar: -1, endChar: -1}, g);
|
|
@@ -14,6 +14,7 @@ var roundNumber = require("./round-number");
|
|
|
14
14
|
this.path = [];
|
|
15
15
|
this.lastM = [0, 0];
|
|
16
16
|
this.ingroup = true;
|
|
17
|
+
this.paper.openGroup();
|
|
17
18
|
};
|
|
18
19
|
|
|
19
20
|
Group.prototype.isInGroup = function() {
|
|
@@ -41,20 +42,21 @@ var roundNumber = require("./round-number");
|
|
|
41
42
|
/**
|
|
42
43
|
* End a group of glyphs that will always be moved, scaled and highlighted together
|
|
43
44
|
*/
|
|
44
|
-
Group.prototype.endGroup = function (klass) {
|
|
45
|
+
Group.prototype.endGroup = function (klass, name) {
|
|
45
46
|
this.ingroup = false;
|
|
46
|
-
if (this.path.length === 0) return null;
|
|
47
|
+
//if (this.path.length === 0) return null;
|
|
47
48
|
var path = "";
|
|
48
49
|
for (var i = 0; i < this.path.length; i++)
|
|
49
50
|
path += this.path[i].join(" ");
|
|
50
|
-
var ret = this.paper.path({
|
|
51
|
-
path: path,
|
|
52
|
-
stroke: "none",
|
|
53
|
-
fill: this.controller.renderer.foregroundColor,
|
|
54
|
-
'class': this.controller.classes.generate(klass)
|
|
55
|
-
});
|
|
56
51
|
this.path = [];
|
|
57
52
|
|
|
53
|
+
var ret = this.paper.closeGroup();
|
|
54
|
+
if (ret) {
|
|
55
|
+
ret.setAttribute("class", this.controller.classes.generate(klass))
|
|
56
|
+
ret.setAttribute("fill", this.controller.renderer.foregroundColor)
|
|
57
|
+
ret.setAttribute("stroke", "none")
|
|
58
|
+
ret.setAttribute("data-name", name)
|
|
59
|
+
}
|
|
58
60
|
return ret;
|
|
59
61
|
};
|
|
60
62
|
|
|
@@ -4,7 +4,9 @@ var renderText = require('./text');
|
|
|
4
4
|
function nonMusic(renderer, obj, selectables) {
|
|
5
5
|
for (var i = 0; i < obj.rows.length; i++) {
|
|
6
6
|
var row = obj.rows[i];
|
|
7
|
-
if (row.
|
|
7
|
+
if (row.absmove) {
|
|
8
|
+
renderer.absolutemoveY(row.absmove);
|
|
9
|
+
} else if (row.move) {
|
|
8
10
|
renderer.moveY(row.move);
|
|
9
11
|
} else if (row.text) {
|
|
10
12
|
var x = row.left ? row.left : 0;
|
|
@@ -14,28 +16,31 @@ function nonMusic(renderer, obj, selectables) {
|
|
|
14
16
|
text: row.text,
|
|
15
17
|
type: row.font,
|
|
16
18
|
klass: row.klass,
|
|
19
|
+
name: row.name,
|
|
17
20
|
anchor: row.anchor
|
|
18
21
|
});
|
|
19
22
|
if (row.absElemType) {
|
|
20
23
|
selectables.wrapSvgEl({
|
|
21
24
|
el_type: row.absElemType,
|
|
22
|
-
|
|
23
|
-
|
|
25
|
+
name: row.name,
|
|
26
|
+
startChar: row.startChar,
|
|
27
|
+
endChar: row.endChar,
|
|
24
28
|
text: row.text
|
|
25
29
|
}, el);
|
|
26
30
|
}
|
|
27
31
|
} else if (row.separator) {
|
|
28
32
|
drawSeparator(renderer, row.separator)
|
|
29
33
|
} else if (row.startGroup) {
|
|
30
|
-
renderer.paper.openGroup({klass: row.klass});
|
|
34
|
+
renderer.paper.openGroup({klass: row.klass, "data-name": row.name});
|
|
31
35
|
} else if (row.endGroup) {
|
|
32
36
|
// TODO-PER: also create a history element with the title "row.endGroup"
|
|
33
37
|
var g = renderer.paper.closeGroup();
|
|
34
38
|
if (row.absElemType)
|
|
35
39
|
selectables.wrapSvgEl({
|
|
36
40
|
el_type: row.absElemType,
|
|
37
|
-
|
|
38
|
-
|
|
41
|
+
name: row.name,
|
|
42
|
+
startChar: row.startChar,
|
|
43
|
+
endChar: row.endChar,
|
|
39
44
|
text: ""
|
|
40
45
|
}, g);
|
|
41
46
|
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
var sprintf = require('./sprintf');
|
|
2
|
+
var roundNumber = require("./round-number");
|
|
3
|
+
|
|
4
|
+
function printLine(renderer, x1, x2, y , klass, name ,dy ) {
|
|
5
|
+
if (!dy ) dy = 0.35;
|
|
6
|
+
var fill = renderer.foregroundColor;
|
|
7
|
+
x1 = roundNumber(x1);
|
|
8
|
+
x2 = roundNumber(x2);
|
|
9
|
+
var y1 = roundNumber(y - dy);
|
|
10
|
+
var y2 = roundNumber(y + dy);
|
|
11
|
+
var pathString = sprintf("M %f %f L %f %f L %f %f L %f %f z", x1, y1, x2, y1,
|
|
12
|
+
x2, y2, x1, y2);
|
|
13
|
+
var options = { path: pathString, stroke: "none", fill: fill };
|
|
14
|
+
if (name)
|
|
15
|
+
options['data-name'] = name;
|
|
16
|
+
if (klass)
|
|
17
|
+
options['class'] = klass;
|
|
18
|
+
var ret = renderer.paper.pathToBack(options);
|
|
19
|
+
|
|
20
|
+
return ret;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
module.exports = printLine;
|
|
24
|
+
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
var elementGroup = require('./group-elements');
|
|
2
2
|
var roundNumber = require("./round-number");
|
|
3
3
|
|
|
4
|
-
function printStem(renderer, x, dx, y1, y2) {
|
|
4
|
+
function printStem(renderer, x, dx, y1, y2, klass, name) {
|
|
5
5
|
if (dx<0 || y1<y2) { // correct path "handedness" for intersection with other elements
|
|
6
6
|
var tmp = roundNumber(y2);
|
|
7
7
|
y2 = roundNumber(y1);
|
|
@@ -12,18 +12,19 @@ function printStem(renderer, x, dx, y1, y2) {
|
|
|
12
12
|
}
|
|
13
13
|
x = roundNumber(x);
|
|
14
14
|
var x2 = roundNumber(x+dx);
|
|
15
|
-
var fill = renderer.foregroundColor;
|
|
16
15
|
var pathArray = [["M",x,y1],["L", x, y2],["L", x2, y2],["L",x2,y1],["z"]];
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
16
|
+
var attr = { path: ""};
|
|
17
|
+
for (var i = 0; i < pathArray.length; i++)
|
|
18
|
+
attr.path += pathArray[i].join(" ");
|
|
19
|
+
if (klass)
|
|
20
|
+
attr['class'] = klass;
|
|
21
|
+
if (name)
|
|
22
|
+
attr['data-name'] = name;
|
|
23
|
+
if (!elementGroup.isInGroup()) {
|
|
24
|
+
attr.stroke ="none";
|
|
25
|
+
attr.fill = renderer.foregroundColor;
|
|
26
26
|
}
|
|
27
|
+
return renderer.paper.pathToBack(attr);
|
|
27
28
|
}
|
|
28
29
|
|
|
29
30
|
module.exports = printStem;
|
|
@@ -7,22 +7,23 @@ var elementGroup = require('./group-elements');
|
|
|
7
7
|
* if symbol is a multichar string without a . (as in scripts.staccato) 1 symbol per char is assumed
|
|
8
8
|
* not scaled if not in printgroup
|
|
9
9
|
*/
|
|
10
|
-
function printSymbol(renderer, x, offset, symbol,
|
|
10
|
+
function printSymbol(renderer, x, offset, symbol, options) {
|
|
11
|
+
// TODO-PER: what happened to scalex, and scaley? That might have been a bug introduced in refactoring
|
|
11
12
|
var el;
|
|
12
13
|
var ycorr;
|
|
13
14
|
if (!symbol) return null;
|
|
14
15
|
if (symbol.length > 1 && symbol.indexOf(".") < 0) {
|
|
15
|
-
renderer.paper.openGroup({klass: klass});
|
|
16
|
+
renderer.paper.openGroup({"data-name": options.name, klass: options.klass});
|
|
16
17
|
var dx = 0;
|
|
17
18
|
for (var i = 0; i < symbol.length; i++) {
|
|
18
19
|
var s = symbol.charAt(i);
|
|
19
20
|
ycorr = glyphs.getYCorr(s);
|
|
20
|
-
el = glyphs.printSymbol(x + dx, renderer.calcY(offset + ycorr), s, renderer.paper,
|
|
21
|
+
el = glyphs.printSymbol(x + dx, renderer.calcY(offset + ycorr), s, renderer.paper, {stroke: options.stroke, fill: options.fill, "data-name": options.name});
|
|
21
22
|
if (el) {
|
|
22
23
|
if (i < symbol.length - 1)
|
|
23
24
|
dx += kernSymbols(s, symbol.charAt(i + 1), glyphs.getSymbolWidth(s));
|
|
24
25
|
} else {
|
|
25
|
-
renderText(renderer, { x: x, y: renderer.y, text: "no symbol:" + symbol, type: "debugfont", klass: 'debug-msg', anchor: 'start'});
|
|
26
|
+
renderText(renderer, { x: x, y: renderer.y, text: "no symbol:" + symbol, type: "debugfont", klass: 'debug-msg', anchor: 'start'}, false);
|
|
26
27
|
}
|
|
27
28
|
}
|
|
28
29
|
var g = renderer.paper.closeGroup();
|
|
@@ -30,14 +31,14 @@ function printSymbol(renderer, x, offset, symbol, scalex, scaley, klass) {
|
|
|
30
31
|
} else {
|
|
31
32
|
ycorr = glyphs.getYCorr(symbol);
|
|
32
33
|
if (elementGroup.isInGroup()) {
|
|
33
|
-
|
|
34
|
+
el = glyphs.printSymbol(x, renderer.calcY(offset + ycorr), symbol, renderer.paper, {"data-name": options.name});
|
|
34
35
|
} else {
|
|
35
|
-
el = glyphs.printSymbol(x, renderer.calcY(offset + ycorr), symbol, renderer.paper, klass, "
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
renderText(renderer, { x: x, y: renderer.y, text: "no symbol:" + symbol, type: "debugfont", klass: 'debug-msg', anchor: 'start'});
|
|
36
|
+
el = glyphs.printSymbol(x, renderer.calcY(offset + ycorr), symbol, renderer.paper, {klass: options.klass, stroke: options.stroke, fill: options.fill, "data-name": options.name});
|
|
37
|
+
}
|
|
38
|
+
if (el) {
|
|
39
|
+
return el;
|
|
40
40
|
}
|
|
41
|
+
renderText(renderer, { x: x, y: renderer.y, text: "no symbol:" + symbol, type: "debugfont", klass: 'debug-msg', anchor: 'start'}, false);
|
|
41
42
|
return null;
|
|
42
43
|
}
|
|
43
44
|
}
|
|
@@ -9,40 +9,60 @@ function drawRelativeElement(renderer, params, bartop) {
|
|
|
9
9
|
var y = renderer.calcY(params.pitch);
|
|
10
10
|
switch(params.type) {
|
|
11
11
|
case "symbol":
|
|
12
|
-
if (params.c===null) return null;
|
|
12
|
+
if (params.c === null) return null;
|
|
13
13
|
var klass = "symbol";
|
|
14
14
|
if (params.klass) klass += " " + params.klass;
|
|
15
|
-
params.graphelem = printSymbol(renderer, params.x, params.pitch, params.c,
|
|
15
|
+
params.graphelem = printSymbol(renderer, params.x, params.pitch, params.c, {
|
|
16
|
+
scalex: params.scalex,
|
|
17
|
+
scaley: params.scaley,
|
|
18
|
+
klass: renderer.controller.classes.generate(klass),
|
|
19
|
+
// fill:"none",
|
|
20
|
+
// stroke: renderer.foregroundColor,
|
|
21
|
+
name: params.name
|
|
22
|
+
});
|
|
23
|
+
break;
|
|
16
24
|
case "debug":
|
|
17
|
-
params.graphelem = renderText(renderer, { x: params.x, y: renderer.calcY(15), text: ""+params.c, type: "debugfont", klass: renderer.controller.classes.generate('debug-msg'), anchor: 'start', centerVertically: false, dim: params.dim});
|
|
25
|
+
params.graphelem = renderText(renderer, { x: params.x, y: renderer.calcY(15), text: "" + params.c, type: "debugfont", klass: renderer.controller.classes.generate('debug-msg'), anchor: 'start', centerVertically: false, dim: params.dim }, false);
|
|
26
|
+
break;
|
|
27
|
+
case "tabNumber":
|
|
28
|
+
var hAnchor = "middle";
|
|
29
|
+
var tabFont = "tabnumberfont";
|
|
30
|
+
var tabClass = 'tab-number';
|
|
31
|
+
if (params.isGrace) {
|
|
32
|
+
tabFont = "tabgracefont";
|
|
33
|
+
y += 2.5;
|
|
34
|
+
tabClass = 'tab-grace'
|
|
35
|
+
}
|
|
36
|
+
params.graphelem = renderText(renderer, { x: params.x, y: y, text: "" + params.c, type: tabFont, klass: renderer.controller.classes.generate(tabClass), anchor: hAnchor, centerVertically: false, dim: params.dim , cursor: 'default'}, false);
|
|
37
|
+
break;
|
|
18
38
|
case "barNumber":
|
|
19
|
-
params.graphelem = renderText(renderer, { x: params.x, y: y, text: ""+params.c, type: "measurefont", klass: renderer.controller.classes.generate('bar-number'), anchor: "middle", dim: params.dim});
|
|
39
|
+
params.graphelem = renderText(renderer, { x: params.x, y: y, text: ""+params.c, type: "measurefont", klass: renderer.controller.classes.generate('bar-number'), anchor: "middle", dim: params.dim, name: "bar-number"}, true);
|
|
20
40
|
break;
|
|
21
41
|
case "lyric":
|
|
22
|
-
params.graphelem = renderText(renderer, { x: params.x, y: y, text: params.c, type: "vocalfont", klass: renderer.controller.classes.generate('lyric'), anchor: "middle", dim: params.dim});
|
|
42
|
+
params.graphelem = renderText(renderer, { x: params.x, y: y, text: params.c, type: "vocalfont", klass: renderer.controller.classes.generate('lyric'), anchor: "middle", dim: params.dim, name: "lyric"}, false);
|
|
23
43
|
break;
|
|
24
44
|
case "chord":
|
|
25
|
-
params.graphelem = renderText(renderer, { x: params.x, y: y, text: params.c, type: 'gchordfont', klass: renderer.controller.classes.generate("chord"), anchor: "middle", dim: params.dim, lane: params.getLane()});
|
|
45
|
+
params.graphelem = renderText(renderer, { x: params.x, y: y, text: params.c, type: 'gchordfont', klass: renderer.controller.classes.generate("chord"), anchor: "middle", dim: params.dim, lane: params.getLane(), name: "chord"}, false);
|
|
26
46
|
break;
|
|
27
47
|
case "decoration":
|
|
28
48
|
// The +6 is to compensate for the placement of text in svg: to be on the same row as symbols, the y-coord needs to compensate for the center line.
|
|
29
|
-
params.graphelem = renderText(renderer, { x: params.x, y: y+6, text: params.c, type: 'annotationfont', klass: renderer.controller.classes.generate("annotation"), anchor: "middle", centerVertically: true, dim: params.dim});
|
|
49
|
+
params.graphelem = renderText(renderer, { x: params.x, y: y+6, text: params.c, type: 'annotationfont', klass: renderer.controller.classes.generate("annotation"), anchor: "middle", centerVertically: true, dim: params.dim}, false);
|
|
30
50
|
break;
|
|
31
51
|
case "text":
|
|
32
|
-
params.graphelem = renderText(renderer, { x: params.x, y: y, text: params.c, type: 'annotationfont', klass: renderer.controller.classes.generate("annotation"), anchor: "start", centerVertically: params.centerVertically, dim: params.dim, lane: params.getLane()});
|
|
52
|
+
params.graphelem = renderText(renderer, { x: params.x, y: y, text: params.c, type: 'annotationfont', klass: renderer.controller.classes.generate("annotation"), anchor: "start", centerVertically: params.centerVertically, dim: params.dim, lane: params.getLane(), name: "annotation"}, false);
|
|
33
53
|
break;
|
|
34
54
|
case "multimeasure-text":
|
|
35
|
-
params.graphelem = renderText(renderer, { x: params.x+params.w/2, y: y, text: params.c, type: 'tempofont', klass: renderer.controller.classes.generate("rest"), anchor: "middle", centerVertically: false, dim: params.dim});
|
|
55
|
+
params.graphelem = renderText(renderer, { x: params.x+params.w/2, y: y, text: params.c, type: 'tempofont', klass: renderer.controller.classes.generate("rest"), anchor: "middle", centerVertically: false, dim: params.dim}, false);
|
|
36
56
|
break;
|
|
37
57
|
case "part":
|
|
38
|
-
params.graphelem = renderText(renderer, { x: params.x, y: y, text: params.c, type: 'partsfont', klass: renderer.controller.classes.generate("part"), anchor: "start", dim: params.dim});
|
|
58
|
+
params.graphelem = renderText(renderer, { x: params.x, y: y, text: params.c, type: 'partsfont', klass: renderer.controller.classes.generate("part"), anchor: "start", dim: params.dim, name: params.c}, true);
|
|
39
59
|
break;
|
|
40
60
|
case "bar":
|
|
41
|
-
params.graphelem = printStem(renderer, params.x, params.linewidth, y, (bartop)?bartop:renderer.calcY(params.pitch2)); break; // bartop can't be 0
|
|
61
|
+
params.graphelem = printStem(renderer, params.x, params.linewidth, y, (bartop)?bartop:renderer.calcY(params.pitch2), null, "bar"); break; // bartop can't be 0
|
|
42
62
|
case "stem":
|
|
43
|
-
params.graphelem = printStem(renderer, params.x, params.linewidth, y, renderer.calcY(params.pitch2)); break;
|
|
63
|
+
params.graphelem = printStem(renderer, params.x, params.linewidth, y, renderer.calcY(params.pitch2), 'abcjs-stem', 'stem'); break;
|
|
44
64
|
case "ledger":
|
|
45
|
-
params.graphelem = printStaffLine(renderer, params.x, params.x+params.w, params.pitch,
|
|
65
|
+
params.graphelem = printStaffLine(renderer, params.x, params.x+params.w, params.pitch, "abcjs-ledger", "ledger"); break;
|
|
46
66
|
}
|
|
47
67
|
if (params.scalex!==1 && params.graphelem) {
|
|
48
68
|
scaleExistingElem(renderer.paper, params.graphelem, params.scalex, params.scaley, params.x, y);
|
|
@@ -10,9 +10,9 @@ function Selectables(paper, selectTypes, tuneNumber) {
|
|
|
10
10
|
|
|
11
11
|
Selectables.prototype.getElements = function () {
|
|
12
12
|
return this.elements;
|
|
13
|
-
}
|
|
13
|
+
};
|
|
14
14
|
|
|
15
|
-
Selectables.prototype.add = function (absEl, svgEl,
|
|
15
|
+
Selectables.prototype.add = function (absEl, svgEl, isNoteOrTabNumber, staffPos) {
|
|
16
16
|
if (!this.canSelect(absEl))
|
|
17
17
|
return;
|
|
18
18
|
var params;
|
|
@@ -21,7 +21,7 @@ Selectables.prototype.add = function (absEl, svgEl, isNote, staffPos) {
|
|
|
21
21
|
else
|
|
22
22
|
params = { selectable: true, tabindex: 0, "data-index": this.elements.length};
|
|
23
23
|
this.paper.setAttributeOnElement(svgEl, params);
|
|
24
|
-
var sel = { absEl: absEl, svgEl: svgEl, isDraggable:
|
|
24
|
+
var sel = { absEl: absEl, svgEl: svgEl, isDraggable: isNoteOrTabNumber };
|
|
25
25
|
if (staffPos !== undefined)
|
|
26
26
|
sel.staffPos = staffPos;
|
|
27
27
|
this.elements.push(sel);
|
|
@@ -36,8 +36,11 @@ Selectables.prototype.canSelect = function (absEl) {
|
|
|
36
36
|
if (this.selectTypes === true)
|
|
37
37
|
return true;
|
|
38
38
|
if (this.selectTypes === undefined) {
|
|
39
|
-
// by default, only notes can be clicked.
|
|
40
|
-
|
|
39
|
+
// by default, only notes and tab numbers can be clicked.
|
|
40
|
+
if (absEl.abcelem.el_type === 'note' || absEl.abcelem.el_type === 'tabNumber') {
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
return false;
|
|
41
44
|
}
|
|
42
45
|
return this.selectTypes.indexOf(absEl.abcelem.el_type) >= 0;
|
|
43
46
|
};
|
|
@@ -49,7 +52,7 @@ Selectables.prototype.wrapSvgEl = function(abcelem, el) {
|
|
|
49
52
|
elemset: [el],
|
|
50
53
|
highlight: highlight,
|
|
51
54
|
unhighlight: unhighlight
|
|
52
|
-
}
|
|
55
|
+
};
|
|
53
56
|
this.add(absEl, el, false);
|
|
54
57
|
};
|
|
55
58
|
|
|
@@ -4,8 +4,9 @@ var drawVoice = require('./voice');
|
|
|
4
4
|
var printStaff = require('./staff');
|
|
5
5
|
var printDebugBox = require('./debug-box');
|
|
6
6
|
var printStem = require('./print-stem');
|
|
7
|
+
var nonMusic = require('./non-music');
|
|
7
8
|
|
|
8
|
-
function drawStaffGroup(renderer, params, selectables) {
|
|
9
|
+
function drawStaffGroup(renderer, params, selectables,lineNumber) {
|
|
9
10
|
// We enter this method with renderer.y pointing to the topmost coordinate that we're allowed to draw.
|
|
10
11
|
// All of the children that will be drawn have a relative "pitch" set, where zero is the first ledger line below the staff.
|
|
11
12
|
// renderer.y will be offset at the beginning of each staff by the amount required to make the relative pitch work.
|
|
@@ -14,7 +15,7 @@ function drawStaffGroup(renderer, params, selectables) {
|
|
|
14
15
|
var colorIndex;
|
|
15
16
|
|
|
16
17
|
// An invisible marker is useful to be able to find where each system starts.
|
|
17
|
-
addInvisibleMarker(renderer,"abcjs-top-of-system");
|
|
18
|
+
addInvisibleMarker(renderer, "abcjs-top-of-system");
|
|
18
19
|
|
|
19
20
|
var startY = renderer.y; // So that it can be restored after we're done.
|
|
20
21
|
// Set the absolute Y position for each staff here, so the voice drawing below can just use if.
|
|
@@ -28,7 +29,7 @@ function drawStaffGroup(renderer, params, selectables) {
|
|
|
28
29
|
boxAllElements(renderer, params.voices, staff1.voices);
|
|
29
30
|
}
|
|
30
31
|
if (renderer.showDebug.indexOf("grid") >= 0) {
|
|
31
|
-
renderer.paper.dottedLine({x1: renderer.padding.left, x2: renderer.padding.left+renderer.controller.width, y1: startY, y2: startY, stroke: "#0000ff"})
|
|
32
|
+
renderer.paper.dottedLine({x1: renderer.padding.left, x2: renderer.padding.left+renderer.controller.width, y1: startY, y2: startY, stroke: "#0000ff"});
|
|
32
33
|
printDebugBox(renderer,
|
|
33
34
|
{ x: renderer.padding.left,
|
|
34
35
|
y: renderer.calcY(staff1.originalTop),
|
|
@@ -68,20 +69,40 @@ function drawStaffGroup(renderer, params, selectables) {
|
|
|
68
69
|
var topLine; // these are to connect multiple staves. We need to remember where they are.
|
|
69
70
|
var bottomLine;
|
|
70
71
|
|
|
72
|
+
var linePitch = 2;
|
|
71
73
|
var bartop = 0;
|
|
72
74
|
for (var i=0;i<params.voices.length;i++) {
|
|
73
75
|
var staff = params.voices[i].staff;
|
|
74
|
-
|
|
76
|
+
var tabName = params.voices[i].tabNameInfos;
|
|
77
|
+
renderer.y = staff.absoluteY ;
|
|
75
78
|
renderer.controller.classes.incrVoice();
|
|
76
79
|
//renderer.y = staff.y;
|
|
77
80
|
// offset for starting the counting at middle C
|
|
78
81
|
if (!params.voices[i].duplicate) {
|
|
79
82
|
// renderer.moveY(spacing.STEP, staff.top);
|
|
80
83
|
if (!topLine) topLine = renderer.calcY(10);
|
|
81
|
-
bottomLine = renderer.calcY(
|
|
84
|
+
bottomLine = renderer.calcY(linePitch);
|
|
82
85
|
if (staff.lines !== 0) {
|
|
86
|
+
if (staff.linePitch) {
|
|
87
|
+
linePitch = staff.linePitch;
|
|
88
|
+
}
|
|
83
89
|
renderer.controller.classes.newMeasure();
|
|
84
|
-
printStaff(renderer, params.startx, params.w, staff.lines);
|
|
90
|
+
var lines = printStaff(renderer, params.startx, params.w, staff.lines, staff.linePitch, staff.dy);
|
|
91
|
+
bottomLine = lines[1];
|
|
92
|
+
staff.bottomLine = bottomLine;
|
|
93
|
+
staff.topLine = lines[0];
|
|
94
|
+
// rework bartop when tabs are present with current staff
|
|
95
|
+
if (staff.hasTab) {
|
|
96
|
+
// do not link to staff above (ugly looking)
|
|
97
|
+
bartop = staff.topLine;
|
|
98
|
+
}
|
|
99
|
+
if (staff.hasStaff) {
|
|
100
|
+
// this is a tab
|
|
101
|
+
bartop = staff.hasStaff.topLine;
|
|
102
|
+
params.voices[i].barto = true;
|
|
103
|
+
params.voices[i].topLine = topLine;
|
|
104
|
+
}
|
|
105
|
+
|
|
85
106
|
}
|
|
86
107
|
printBrace(renderer, staff.absoluteY, params.brace, i, selectables);
|
|
87
108
|
printBrace(renderer, staff.absoluteY, params.bracket, i, selectables);
|
|
@@ -91,9 +112,21 @@ function drawStaffGroup(renderer, params, selectables) {
|
|
|
91
112
|
zero: renderer.y,
|
|
92
113
|
height: params.height*spacing.STEP
|
|
93
114
|
});
|
|
115
|
+
var tabNameHeight = 0;
|
|
116
|
+
if (tabName) {
|
|
117
|
+
// print tab infos on staffBottom
|
|
118
|
+
var r = { rows: [] };
|
|
119
|
+
r.rows.push({ absmove: bottomLine + 2 });
|
|
120
|
+
var leftMargin = 8;
|
|
121
|
+
r.rows.push({ left: params.startx+leftMargin, text: tabName.name, font: 'tablabelfont', klass: 'text instrument-name', anchor: 'start' });
|
|
122
|
+
r.rows.push({ move: tabName.textSize.height });
|
|
123
|
+
nonMusic(renderer, r);
|
|
124
|
+
tabNameHeight = tabName.textSize.height;
|
|
125
|
+
}
|
|
126
|
+
|
|
94
127
|
renderer.controller.classes.newMeasure();
|
|
95
128
|
if (!params.voices[i].duplicate) {
|
|
96
|
-
|
|
129
|
+
bartop = renderer.calcY(2 + tabNameHeight); // This connects the bar lines between two different staves.
|
|
97
130
|
// if (staff.bottom < 0)
|
|
98
131
|
// renderer.moveY(spacing.STEP, -staff.bottom);
|
|
99
132
|
}
|
|
@@ -101,8 +134,11 @@ function drawStaffGroup(renderer, params, selectables) {
|
|
|
101
134
|
renderer.controller.classes.newMeasure();
|
|
102
135
|
|
|
103
136
|
// connect all the staves together with a vertical line
|
|
104
|
-
|
|
105
|
-
|
|
137
|
+
var staffSize = params.staffs.length;
|
|
138
|
+
if (staffSize > 1) {
|
|
139
|
+
topLine = params.staffs[0].topLine;
|
|
140
|
+
bottomLine = params.staffs[staffSize - 1].bottomLine;
|
|
141
|
+
printStem(renderer, params.startx, 0.6, topLine, bottomLine, null);
|
|
106
142
|
}
|
|
107
143
|
renderer.y = startY;
|
|
108
144
|
|
|
@@ -1,22 +1,8 @@
|
|
|
1
|
-
var
|
|
2
|
-
var roundNumber = require("./round-number");
|
|
1
|
+
var printLine = require('./print-line');
|
|
3
2
|
|
|
4
|
-
function printStaffLine(renderer, x1,x2, pitch, klass) {
|
|
5
|
-
var dy = 0.35;
|
|
6
|
-
var fill = renderer.foregroundColor;
|
|
3
|
+
function printStaffLine(renderer, x1,x2, pitch, klass, name , dy) {
|
|
7
4
|
var y = renderer.calcY(pitch);
|
|
8
|
-
|
|
9
|
-
x2 = roundNumber(x2);
|
|
10
|
-
var y1 = roundNumber(y-dy);
|
|
11
|
-
var y2 = roundNumber(y+dy);
|
|
12
|
-
var pathString = sprintf("M %f %f L %f %f L %f %f L %f %f z", x1, y1, x2, y1,
|
|
13
|
-
x2, y2, x1, y2);
|
|
14
|
-
var options = {path:pathString, stroke:"none", fill:fill};
|
|
15
|
-
if (klass)
|
|
16
|
-
options['class'] = klass;
|
|
17
|
-
var ret = renderer.paper.pathToBack(options);
|
|
18
|
-
|
|
19
|
-
return ret;
|
|
5
|
+
return printLine(renderer,x1,x2,y,klass,name,dy);
|
|
20
6
|
}
|
|
21
7
|
|
|
22
8
|
module.exports = printStaffLine;
|
package/src/write/draw/staff.js
CHANGED
|
@@ -1,18 +1,31 @@
|
|
|
1
1
|
var printStaffLine = require('./staff-line');
|
|
2
2
|
|
|
3
|
-
function printStaff(renderer, startx, endx, numLines) {
|
|
3
|
+
function printStaff(renderer, startx, endx, numLines , linePitch , dy) {
|
|
4
4
|
var klass = "abcjs-top-line";
|
|
5
|
+
var pitch = 2;
|
|
6
|
+
if (linePitch) {
|
|
7
|
+
pitch = linePitch;
|
|
8
|
+
}
|
|
5
9
|
renderer.paper.openGroup({ prepend: true, klass: renderer.controller.classes.generate("abcjs-staff") });
|
|
6
10
|
// If there is one line, it is the B line. Otherwise, the bottom line is the E line.
|
|
11
|
+
var firstYLine = 0;
|
|
12
|
+
var lastYLine = 0;
|
|
7
13
|
if (numLines === 1) {
|
|
8
14
|
printStaffLine(renderer, startx,endx,6, klass);
|
|
9
15
|
} else {
|
|
16
|
+
|
|
10
17
|
for (var i = numLines - 1; i >= 0; i--) {
|
|
11
|
-
|
|
18
|
+
var curpitch = (i + 1) * pitch;
|
|
19
|
+
lastYLine = renderer.calcY(curpitch);
|
|
20
|
+
if (firstYLine == 0) {
|
|
21
|
+
firstYLine = lastYLine;
|
|
22
|
+
}
|
|
23
|
+
printStaffLine(renderer, startx, endx, curpitch, klass , null , dy) ;
|
|
12
24
|
klass = undefined;
|
|
13
25
|
}
|
|
14
26
|
}
|
|
15
27
|
renderer.paper.closeGroup();
|
|
28
|
+
return [firstYLine,lastYLine];
|
|
16
29
|
}
|
|
17
30
|
|
|
18
31
|
module.exports = printStaff;
|