abcjs 6.6.2 → 6.6.3
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/RELEASE.md +12 -0
- package/dist/abcjs-basic-min.js +2 -2
- package/dist/abcjs-basic.js +239 -29
- package/dist/abcjs-basic.js.map +1 -1
- package/dist/abcjs-plugin-min.js +2 -2
- package/package.json +1 -1
- package/src/write/creation/abstract-engraver.js +5 -4
- package/src/write/creation/create-note-head.js +6 -5
- package/src/write/creation/elements/relative-element.js +3 -0
- package/src/write/draw/absolute.js +6 -0
- package/src/write/draw/triplet.js +3 -3
- package/src/write/layout/layout.js +90 -0
- package/src/write/layout/set-upper-and-lower-elements.js +18 -2
- package/src/write/layout/to-time-and-staff-based.js +35 -0
- package/src/write/layout/triplet.js +61 -14
- package/version.js +1 -1
package/dist/abcjs-basic.js
CHANGED
|
@@ -19014,6 +19014,7 @@ AbstractEngraver.prototype.addNoteToAbcElement = function (abselem, elem, dot, s
|
|
|
19014
19014
|
}
|
|
19015
19015
|
}
|
|
19016
19016
|
var hasStem = !nostem && durlog <= -1;
|
|
19017
|
+
var chordPos = pp > 1 ? p + 1 : null;
|
|
19017
19018
|
var ret = createNoteHead(abselem, c, elem.pitches[p], {
|
|
19018
19019
|
dir: dir,
|
|
19019
19020
|
extrax: -roomTaken,
|
|
@@ -19023,7 +19024,8 @@ AbstractEngraver.prototype.addNoteToAbcElement = function (abselem, elem, dot, s
|
|
|
19023
19024
|
scale: this.voiceScale,
|
|
19024
19025
|
accidentalSlot: accidentalSlot,
|
|
19025
19026
|
shouldExtendStem: !stemdir,
|
|
19026
|
-
printAccidentals: !voice.isPercussion
|
|
19027
|
+
printAccidentals: !voice.isPercussion,
|
|
19028
|
+
chordPos: chordPos
|
|
19027
19029
|
});
|
|
19028
19030
|
symbolWidth = Math.max(glyphs.getSymbolWidth(c), symbolWidth);
|
|
19029
19031
|
abselem.extraw -= ret.extraLeft;
|
|
@@ -19074,7 +19076,7 @@ AbstractEngraver.prototype.addNoteToAbcElement = function (abselem, elem, dot, s
|
|
|
19074
19076
|
symbolWidth: symbolWidth
|
|
19075
19077
|
};
|
|
19076
19078
|
};
|
|
19077
|
-
AbstractEngraver.prototype.addLyric = function (abselem, elem) {
|
|
19079
|
+
AbstractEngraver.prototype.addLyric = function (abselem, elem, voiceNumber) {
|
|
19078
19080
|
var lyricStr = "";
|
|
19079
19081
|
elem.lyric.forEach(function (ly) {
|
|
19080
19082
|
var div = ly.divider === ' ' ? "" : ly.divider;
|
|
@@ -19086,7 +19088,8 @@ AbstractEngraver.prototype.addLyric = function (abselem, elem) {
|
|
|
19086
19088
|
type: "lyric",
|
|
19087
19089
|
position: position,
|
|
19088
19090
|
height: lyricDim.height / spacing.STEP,
|
|
19089
|
-
dim: this.getTextSize.attr('vocalfont', "lyric")
|
|
19091
|
+
dim: this.getTextSize.attr('vocalfont', "lyric"),
|
|
19092
|
+
voiceNumber: voiceNumber
|
|
19090
19093
|
}));
|
|
19091
19094
|
};
|
|
19092
19095
|
AbstractEngraver.prototype.createNote = function (elem, nostem, isSingleLineStaff, voice) {
|
|
@@ -19138,7 +19141,7 @@ AbstractEngraver.prototype.createNote = function (elem, nostem, isSingleLineStaf
|
|
|
19138
19141
|
symbolWidth = ret2.symbolWidth;
|
|
19139
19142
|
}
|
|
19140
19143
|
if (elem.lyric !== undefined) {
|
|
19141
|
-
this.addLyric(abselem, elem);
|
|
19144
|
+
this.addLyric(abselem, elem, voice.voicenumber);
|
|
19142
19145
|
}
|
|
19143
19146
|
if (elem.gracenotes !== undefined) {
|
|
19144
19147
|
roomtaken += this.addGraceNotes(elem, voice, abselem, notehead, this.stemHeight * this.voiceScale, this.isBagpipes, roomtaken);
|
|
@@ -19784,6 +19787,7 @@ var createNoteHead = function createNoteHead(abselem, c, pitchelem, options) {
|
|
|
19784
19787
|
var accidentalSlot = options.accidentalSlot !== undefined ? options.accidentalSlot : [];
|
|
19785
19788
|
var shouldExtendStem = options.shouldExtendStem !== undefined ? options.shouldExtendStem : false;
|
|
19786
19789
|
var printAccidentals = options.printAccidentals !== undefined ? options.printAccidentals : true;
|
|
19790
|
+
var chordPos = options.chordPos;
|
|
19787
19791
|
|
|
19788
19792
|
// TODO scale the dot as well
|
|
19789
19793
|
var pitch = pitchelem.verticalPos;
|
|
@@ -19794,7 +19798,9 @@ var createNoteHead = function createNoteHead(abselem, c, pitchelem, options) {
|
|
|
19794
19798
|
if (c === undefined) abselem.addFixed(new RelativeElement("pitch is undefined", 0, 0, 0, {
|
|
19795
19799
|
type: "debug"
|
|
19796
19800
|
}));else if (c === "") {
|
|
19797
|
-
notehead = new RelativeElement(null, 0, 0, pitch
|
|
19801
|
+
notehead = new RelativeElement(null, 0, 0, pitch, {
|
|
19802
|
+
chordPos: chordPos
|
|
19803
|
+
});
|
|
19798
19804
|
} else {
|
|
19799
19805
|
var shiftheadx = headx;
|
|
19800
19806
|
if (pitchelem.printer_shift) {
|
|
@@ -19805,7 +19811,8 @@ var createNoteHead = function createNoteHead(abselem, c, pitchelem, options) {
|
|
|
19805
19811
|
scalex: scale,
|
|
19806
19812
|
scaley: scale,
|
|
19807
19813
|
thickness: glyphs.symbolHeightInPitches(c) * scale,
|
|
19808
|
-
name: pitchelem.name
|
|
19814
|
+
name: pitchelem.name,
|
|
19815
|
+
chordPos: chordPos
|
|
19809
19816
|
};
|
|
19810
19817
|
notehead = new RelativeElement(c, shiftheadx, glyphs.getSymbolWidth(c) * scale, pitch, opts);
|
|
19811
19818
|
notehead.stemDir = dir;
|
|
@@ -19820,13 +19827,16 @@ var createNoteHead = function createNoteHead(abselem, c, pitchelem, options) {
|
|
|
19820
19827
|
var xdelta = dir === "down" ? headx : headx + notehead.w - 0.6;
|
|
19821
19828
|
abselem.addRight(new RelativeElement(flag, xdelta, glyphs.getSymbolWidth(flag) * scale, pos, {
|
|
19822
19829
|
scalex: scale,
|
|
19823
|
-
scaley: scale
|
|
19830
|
+
scaley: scale,
|
|
19831
|
+
chordPos: chordPos
|
|
19824
19832
|
}));
|
|
19825
19833
|
}
|
|
19826
19834
|
newDotShiftX = notehead.w + dotshiftx - 2 + 5 * dot;
|
|
19827
19835
|
for (; dot > 0; dot--) {
|
|
19828
19836
|
var dotadjusty = 1 - Math.abs(pitch) % 2; //PER: take abs value of the pitch. And the shift still happens on ledger lines.
|
|
19829
|
-
abselem.addRight(new RelativeElement("dots.dot", notehead.w + dotshiftx - 2 + 5 * dot, glyphs.getSymbolWidth("dots.dot"), pitch + dotadjusty
|
|
19837
|
+
abselem.addRight(new RelativeElement("dots.dot", notehead.w + dotshiftx - 2 + 5 * dot, glyphs.getSymbolWidth("dots.dot"), pitch + dotadjusty, {
|
|
19838
|
+
chordPos: chordPos
|
|
19839
|
+
}));
|
|
19830
19840
|
}
|
|
19831
19841
|
}
|
|
19832
19842
|
if (notehead) notehead.highestVert = pitchelem.highestVert;
|
|
@@ -19875,7 +19885,8 @@ var createNoteHead = function createNoteHead(abselem, c, pitchelem, options) {
|
|
|
19875
19885
|
scalex: scale,
|
|
19876
19886
|
scaley: scale,
|
|
19877
19887
|
top: pitch + h / 2,
|
|
19878
|
-
bottom: pitch - h / 2
|
|
19888
|
+
bottom: pitch - h / 2,
|
|
19889
|
+
chordPos: chordPos
|
|
19879
19890
|
}));
|
|
19880
19891
|
extraLeft = glyphs.getSymbolWidth(symb) / 2; // TODO-PER: We need a little extra width if there is an accidental, but I'm not sure why it isn't the full width of the accidental.
|
|
19881
19892
|
}
|
|
@@ -21112,6 +21123,7 @@ var RelativeElement = function RelativeElement(c, dx, w, pitch, opt) {
|
|
|
21112
21123
|
this.pitch2 = opt.pitch2;
|
|
21113
21124
|
this.linewidth = opt.linewidth;
|
|
21114
21125
|
this.klass = opt.klass;
|
|
21126
|
+
this.chordPos = opt.chordPos;
|
|
21115
21127
|
this.anchor = opt.anchor ? opt.anchor : 'middle';
|
|
21116
21128
|
this.top = pitch;
|
|
21117
21129
|
if (this.pitch2 !== undefined && this.pitch2 > this.top) this.top = this.pitch2;
|
|
@@ -21126,6 +21138,7 @@ var RelativeElement = function RelativeElement(c, dx, w, pitch, opt) {
|
|
|
21126
21138
|
}
|
|
21127
21139
|
if (opt.dim) this.dim = opt.dim;
|
|
21128
21140
|
if (opt.position) this.position = opt.position;
|
|
21141
|
+
if (opt.voiceNumber !== undefined) this.voiceNumber = opt.voiceNumber;
|
|
21129
21142
|
this.height = opt.height ? opt.height : 4; // The +1 is to give a little bit of padding.
|
|
21130
21143
|
if (opt.top) this.top = opt.top;
|
|
21131
21144
|
if (opt.bottom) this.bottom = opt.bottom;
|
|
@@ -22679,6 +22692,11 @@ function drawAbsolute(renderer, params, bartop, selectables, staffPos) {
|
|
|
22679
22692
|
if (child.type === "symbol" && child.c && child.c.indexOf('notehead') >= 0) {
|
|
22680
22693
|
el.setAttribute('class', 'abcjs-notehead');
|
|
22681
22694
|
}
|
|
22695
|
+
if (el && child.chordPos && child.name.indexOf('flags.') !== 0) {
|
|
22696
|
+
var klass = el.getAttribute("class");
|
|
22697
|
+
if (klass) klass = klass + ' abcjs-chord-pos-' + child.chordPos;else klass = 'abcjs-chord-pos-' + child.chordPos;
|
|
22698
|
+
el.setAttribute('class', klass);
|
|
22699
|
+
}
|
|
22682
22700
|
}
|
|
22683
22701
|
}
|
|
22684
22702
|
var klass = params.type;
|
|
@@ -24842,7 +24860,7 @@ function drawTriplet(renderer, params, selectables) {
|
|
|
24842
24860
|
"data-name": "triplet"
|
|
24843
24861
|
});
|
|
24844
24862
|
if (!params.hasBeam) {
|
|
24845
|
-
drawBracket(renderer, params.anchor1.x, params.startNote, params.anchor2.x + params.anchor2.w, params.endNote);
|
|
24863
|
+
drawBracket(renderer, params.anchor1.x, params.startNote, params.anchor2.x + params.anchor2.w, params.endNote, params.up);
|
|
24846
24864
|
}
|
|
24847
24865
|
// HACK: adjust the position of "3". It is too high in all cases so we fudge it by subtracting 1 here.
|
|
24848
24866
|
renderText(renderer, {
|
|
@@ -24866,10 +24884,10 @@ function drawTriplet(renderer, params, selectables) {
|
|
|
24866
24884
|
function drawLine(l, t, r, b) {
|
|
24867
24885
|
return sprintf("M %f %f L %f %f", roundNumber(l), roundNumber(t), roundNumber(r), roundNumber(b));
|
|
24868
24886
|
}
|
|
24869
|
-
function drawBracket(renderer, x1, y1, x2, y2) {
|
|
24887
|
+
function drawBracket(renderer, x1, y1, x2, y2, up) {
|
|
24870
24888
|
y1 = renderer.calcY(y1);
|
|
24871
24889
|
y2 = renderer.calcY(y2);
|
|
24872
|
-
var bracketHeight = 5;
|
|
24890
|
+
var bracketHeight = up ? 5 : -5;
|
|
24873
24891
|
|
|
24874
24892
|
// Draw vertical lines at the beginning and end
|
|
24875
24893
|
var pathString = "";
|
|
@@ -26592,6 +26610,7 @@ var setUpperAndLowerElements = __webpack_require__(/*! ./set-upper-and-lower-ele
|
|
|
26592
26610
|
var layoutStaffGroup = __webpack_require__(/*! ./staff-group */ "./src/write/layout/staff-group.js");
|
|
26593
26611
|
var getLeftEdgeOfStaff = __webpack_require__(/*! ./get-left-edge-of-staff */ "./src/write/layout/get-left-edge-of-staff.js");
|
|
26594
26612
|
var layoutInGrid = __webpack_require__(/*! ./layout-in-grid */ "./src/write/layout/layout-in-grid.js");
|
|
26613
|
+
var toTimeAndStaffBased = __webpack_require__(/*! ./to-time-and-staff-based */ "./src/write/layout/to-time-and-staff-based.js");
|
|
26595
26614
|
|
|
26596
26615
|
// This sets the "x" attribute on all the children in abctune.lines
|
|
26597
26616
|
// It also sets the "w" and "startx" attributes on "voices"
|
|
@@ -26627,6 +26646,16 @@ var layout = function layout(renderer, abctune, width, space, expandToWidest, ti
|
|
|
26627
26646
|
}
|
|
26628
26647
|
}
|
|
26629
26648
|
|
|
26649
|
+
// See if there are collisions between voices that need to be tweaked
|
|
26650
|
+
var timeBased = toTimeAndStaffBased(abctune.lines);
|
|
26651
|
+
for (i = 0; i < abctune.lines.length; i++) {
|
|
26652
|
+
abcLine = abctune.lines[i];
|
|
26653
|
+
if (abcLine.staffGroup) {
|
|
26654
|
+
fixVoiceCollisions(timeBased[i]);
|
|
26655
|
+
//setUpperAndLowerElements(renderer, abcLine.staffGroup);
|
|
26656
|
+
}
|
|
26657
|
+
}
|
|
26658
|
+
|
|
26630
26659
|
// Set the staff spacing
|
|
26631
26660
|
// TODO-PER: we should have been able to do this by the time we called setUpperAndLowerElements, but for some reason the "bottom" element seems to be set as a side effect of setting the X spacing.
|
|
26632
26661
|
for (i = 0; i < abctune.lines.length; i++) {
|
|
@@ -26709,6 +26738,82 @@ function centerWholeRests(voices) {
|
|
|
26709
26738
|
}
|
|
26710
26739
|
}
|
|
26711
26740
|
}
|
|
26741
|
+
function fixVoiceCollisions(timeBasedLine) {
|
|
26742
|
+
for (var s = 0; s < timeBasedLine.length; s++) {
|
|
26743
|
+
var timeSlot = timeBasedLine[s];
|
|
26744
|
+
// If there is more than one thing happening at the same time,
|
|
26745
|
+
// and one of those things is a rest, then:
|
|
26746
|
+
// If the rest is in the first element, check to see if the bottom bumps into the top of any of the rest of the elements
|
|
26747
|
+
// If the rest is in the last element, check to see if the top bumps into the bottom of any of the rest of the elements.
|
|
26748
|
+
// Note: if there are more than two voices the staff will get sloppy, so there is a limit to how much that can be improved, but this should be fine when there are two voices.
|
|
26749
|
+
// If there is a collision, move the rest up or down to fix that.
|
|
26750
|
+
var keys = Object.keys(timeSlot);
|
|
26751
|
+
for (var z = 0; z < keys.length; z++) {
|
|
26752
|
+
var slot = timeSlot[keys[z]]; // slot is an array of all the things happening at a particular time
|
|
26753
|
+
var lastIndex = slot.length - 1;
|
|
26754
|
+
if (slot.length > 1) {
|
|
26755
|
+
var isRealRest = slot[0].abcelem.rest && slot[0].abcelem.rest.type === 'rest'; // weed out invisible rests
|
|
26756
|
+
var isRealRest2 = slot[lastIndex].abcelem.rest && slot[lastIndex].abcelem.rest.type === 'rest'; // weed out invisible rests
|
|
26757
|
+
if (isRealRest && !slot[lastIndex].abcelem.rest) {
|
|
26758
|
+
// the first voice has a rest and the second doesn't
|
|
26759
|
+
var restTop = slot[0].children.find(function (ch) {
|
|
26760
|
+
return ch.name.includes('rest');
|
|
26761
|
+
});
|
|
26762
|
+
var otherTop = closeTop(slot[lastIndex]);
|
|
26763
|
+
if (restTop) {
|
|
26764
|
+
var distance1 = restTop.bottom - otherTop;
|
|
26765
|
+
distance1 -= 2; // give some room between the rest and the note
|
|
26766
|
+
if (distance1 < 0 && slot[0].children.length > 0) {
|
|
26767
|
+
slot[0].bottom -= distance1;
|
|
26768
|
+
slot[0].top -= distance1;
|
|
26769
|
+
slot[0].children[0].bottom -= distance1;
|
|
26770
|
+
slot[0].children[0].top -= distance1;
|
|
26771
|
+
slot[0].children[0].pitch -= distance1;
|
|
26772
|
+
}
|
|
26773
|
+
}
|
|
26774
|
+
} else if (isRealRest2 && !slot[0].abcelem.rest) {
|
|
26775
|
+
// the last voice has a rest and the first doesn't
|
|
26776
|
+
var restBottom = slot[lastIndex].children.find(function (ch) {
|
|
26777
|
+
return ch.name.includes('rest');
|
|
26778
|
+
});
|
|
26779
|
+
if (restBottom) {
|
|
26780
|
+
var distance2 = restBottom.top - closeBottom(slot[0]);
|
|
26781
|
+
distance2 += 2; // give some room between the rest and the note
|
|
26782
|
+
if (distance2 > 0 && slot[lastIndex].children.length > 0) {
|
|
26783
|
+
slot[lastIndex].bottom -= distance2;
|
|
26784
|
+
slot[lastIndex].top -= distance2;
|
|
26785
|
+
slot[lastIndex].children[0].bottom -= distance2;
|
|
26786
|
+
slot[lastIndex].children[0].top -= distance2;
|
|
26787
|
+
slot[lastIndex].children[0].pitch -= distance2;
|
|
26788
|
+
}
|
|
26789
|
+
}
|
|
26790
|
+
}
|
|
26791
|
+
}
|
|
26792
|
+
}
|
|
26793
|
+
}
|
|
26794
|
+
}
|
|
26795
|
+
function closeTop(absElem) {
|
|
26796
|
+
if (absElem.children) {
|
|
26797
|
+
var max = -90; // This is clearly way lower than the max calculated below
|
|
26798
|
+
for (var i = 0; i < absElem.children.length; i++) {
|
|
26799
|
+
var child = absElem.children[i];
|
|
26800
|
+
if (child.type !== 'chord') max = Math.max(max, child.top);
|
|
26801
|
+
}
|
|
26802
|
+
if (max > -90) return max;
|
|
26803
|
+
}
|
|
26804
|
+
return absElem.top;
|
|
26805
|
+
}
|
|
26806
|
+
function closeBottom(absElem) {
|
|
26807
|
+
if (absElem.children) {
|
|
26808
|
+
var min = 90; // This is clearly way higher than the min calculated below
|
|
26809
|
+
for (var i = 0; i < absElem.children.length; i++) {
|
|
26810
|
+
var child = absElem.children[i];
|
|
26811
|
+
if (child.type !== 'lyric') min = Math.min(min, child.bottom);
|
|
26812
|
+
}
|
|
26813
|
+
if (min < 90) return min;
|
|
26814
|
+
}
|
|
26815
|
+
return absElem.bottom;
|
|
26816
|
+
}
|
|
26712
26817
|
module.exports = layout;
|
|
26713
26818
|
|
|
26714
26819
|
/***/ }),
|
|
@@ -26788,7 +26893,8 @@ var setUpperAndLowerElements = function setUpperAndLowerElements(renderer, staff
|
|
|
26788
26893
|
|
|
26789
26894
|
for (var j = 0; j < staff.voices.length; j++) {
|
|
26790
26895
|
var voice = staffGroup.voices[staff.voices[j]];
|
|
26791
|
-
setUpperAndLowerVoiceElements(positionY, voice, renderer.spacing);
|
|
26896
|
+
var diff = setUpperAndLowerVoiceElements(positionY, voice, renderer.spacing);
|
|
26897
|
+
staff.bottom -= diff; //
|
|
26792
26898
|
}
|
|
26793
26899
|
// 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.
|
|
26794
26900
|
// Only try to put in extra space if this isn't the top staff.
|
|
@@ -26821,10 +26927,18 @@ function incTop(staff, positionY, item, count) {
|
|
|
26821
26927
|
function setUpperAndLowerVoiceElements(positionY, voice, spacing) {
|
|
26822
26928
|
var i;
|
|
26823
26929
|
var abselem;
|
|
26930
|
+
var diff = 0;
|
|
26824
26931
|
for (i = 0; i < voice.children.length; i++) {
|
|
26825
26932
|
abselem = voice.children[i];
|
|
26826
|
-
setUpperAndLowerAbsoluteElements(positionY, abselem, spacing);
|
|
26933
|
+
var bottom = setUpperAndLowerAbsoluteElements(positionY, abselem, spacing);
|
|
26934
|
+
if (bottom < abselem.bottom) {
|
|
26935
|
+
// We're moving things down so tell the staff that it needs to be taller
|
|
26936
|
+
diff = abselem.bottom - bottom;
|
|
26937
|
+
abselem.bottom = bottom; //
|
|
26938
|
+
voice.bottom = bottom; //
|
|
26939
|
+
}
|
|
26827
26940
|
}
|
|
26941
|
+
|
|
26828
26942
|
for (i = 0; i < voice.otherchildren.length; i++) {
|
|
26829
26943
|
abselem = voice.otherchildren[i];
|
|
26830
26944
|
switch (abselem.type) {
|
|
@@ -26847,6 +26961,7 @@ function setUpperAndLowerVoiceElements(positionY, voice, spacing) {
|
|
|
26847
26961
|
break;
|
|
26848
26962
|
}
|
|
26849
26963
|
}
|
|
26964
|
+
return diff;
|
|
26850
26965
|
}
|
|
26851
26966
|
|
|
26852
26967
|
// For each of the relative elements that can't be placed in advance (because their vertical placement depends on everything
|
|
@@ -26854,6 +26969,7 @@ function setUpperAndLowerVoiceElements(positionY, voice, spacing) {
|
|
|
26854
26969
|
// hash with the vertical placement (in pitch units) for each type.
|
|
26855
26970
|
// TODO-PER: I think this needs to be separated by "above" and "below". How do we know that for dynamics at the point where they are being defined, though? We need a pass through all the relative elements to set "above" and "below".
|
|
26856
26971
|
function setUpperAndLowerAbsoluteElements(specialYResolved, element, spacing) {
|
|
26972
|
+
var bottom = element.bottom;
|
|
26857
26973
|
// specialYResolved contains the actual pitch for each of the classes of elements.
|
|
26858
26974
|
for (var i = 0; i < element.children.length; i++) {
|
|
26859
26975
|
var child = element.children[i];
|
|
@@ -26863,6 +26979,12 @@ function setUpperAndLowerAbsoluteElements(specialYResolved, element, spacing) {
|
|
|
26863
26979
|
if (child[key]) {
|
|
26864
26980
|
// If this relative element has defined a height for this class of element
|
|
26865
26981
|
child.pitch = specialYResolved[key];
|
|
26982
|
+
if (key === 'lyricHeightBelow' && child.type === 'lyric' && child.voiceNumber) {
|
|
26983
|
+
// TODO-PER: This can result in extra unused vertical space if there are lyrics only on the second but not the first voice.
|
|
26984
|
+
child.pitch -= child.voiceNumber * child[key]; //
|
|
26985
|
+
bottom = Math.min(element.bottom, child.pitch); //
|
|
26986
|
+
}
|
|
26987
|
+
|
|
26866
26988
|
if (child.top === undefined) {
|
|
26867
26989
|
// TODO-PER: HACK! Not sure this is the right place to do this.
|
|
26868
26990
|
if (child.type === 'TempoElement') {
|
|
@@ -26877,6 +26999,7 @@ function setUpperAndLowerAbsoluteElements(specialYResolved, element, spacing) {
|
|
|
26877
26999
|
}
|
|
26878
27000
|
}
|
|
26879
27001
|
}
|
|
27002
|
+
return bottom;
|
|
26880
27003
|
}
|
|
26881
27004
|
function setUpperAndLowerCrescendoElements(positionY, element) {
|
|
26882
27005
|
if (element.dynamicHeightAbove) element.pitch = positionY.dynamicHeightAbove;else element.pitch = positionY.dynamicHeightBelow;
|
|
@@ -27083,6 +27206,47 @@ module.exports = layoutStaffGroup;
|
|
|
27083
27206
|
|
|
27084
27207
|
/***/ }),
|
|
27085
27208
|
|
|
27209
|
+
/***/ "./src/write/layout/to-time-and-staff-based.js":
|
|
27210
|
+
/*!*****************************************************!*\
|
|
27211
|
+
!*** ./src/write/layout/to-time-and-staff-based.js ***!
|
|
27212
|
+
\*****************************************************/
|
|
27213
|
+
/***/ (function(module) {
|
|
27214
|
+
|
|
27215
|
+
function toTimeAndStaffBased(abcLines) {
|
|
27216
|
+
var results = [];
|
|
27217
|
+
for (var lin = 0; lin < abcLines.length; lin++) {
|
|
27218
|
+
var line = abcLines[lin];
|
|
27219
|
+
var staffGroup = line.staffGroup;
|
|
27220
|
+
var group = [];
|
|
27221
|
+
if (staffGroup && staffGroup && staffGroup.staffs) {
|
|
27222
|
+
for (var s = 0; s < staffGroup.staffs.length; s++) {
|
|
27223
|
+
var staff = staffGroup.staffs[s];
|
|
27224
|
+
var timeSlot = {};
|
|
27225
|
+
for (var i = 0; i < staff.voices.length; i++) {
|
|
27226
|
+
var voice = staffGroup.voices[staff.voices[i]];
|
|
27227
|
+
var time = 0;
|
|
27228
|
+
for (var k = 0; k < voice.children.length; k++) {
|
|
27229
|
+
var index = 'T' + Math.round(time * 1000); // There can be inexactness when calculating triplets, so we'll round, but we'll make sure that no make sure that we don't lose necessary precision by making it a shorter time than would ever happen
|
|
27230
|
+
if (!timeSlot[index]) timeSlot[index] = [];
|
|
27231
|
+
if (voice.children[k].abcelem.el_type === 'note') {
|
|
27232
|
+
timeSlot[index].push(voice.children[k]);
|
|
27233
|
+
time += voice.children[k].duration;
|
|
27234
|
+
}
|
|
27235
|
+
}
|
|
27236
|
+
}
|
|
27237
|
+
// Now timeSlot is an object with all the voices on a particular staff that
|
|
27238
|
+
// happen at the same time as an array.
|
|
27239
|
+
group.push(timeSlot);
|
|
27240
|
+
}
|
|
27241
|
+
}
|
|
27242
|
+
results.push(group);
|
|
27243
|
+
}
|
|
27244
|
+
return results;
|
|
27245
|
+
}
|
|
27246
|
+
module.exports = toTimeAndStaffBased;
|
|
27247
|
+
|
|
27248
|
+
/***/ }),
|
|
27249
|
+
|
|
27086
27250
|
/***/ "./src/write/layout/triplet.js":
|
|
27087
27251
|
/*!*************************************!*\
|
|
27088
27252
|
!*** ./src/write/layout/triplet.js ***!
|
|
@@ -27108,30 +27272,56 @@ function layoutTriplet(element) {
|
|
|
27108
27272
|
element.bottom = element.yTextPos - 2;
|
|
27109
27273
|
if (isAbove(beam)) element.endingHeightAbove = 4;
|
|
27110
27274
|
} else {
|
|
27111
|
-
// If there isn't a beam, then we need to draw the bracket and the text. The bracket is
|
|
27275
|
+
// If there isn't a beam, then we need to draw the bracket and the text. The bracket is either above or below depending on the stem direction of the notes.
|
|
27276
|
+
// Above:
|
|
27112
27277
|
// The bracket is never lower than the 'a' line, but is 4 pitches above the first and last notes. If there is
|
|
27113
27278
|
// a tall note in the middle, the bracket is horizontal and above the highest note.
|
|
27114
|
-
|
|
27115
|
-
|
|
27279
|
+
// Below: The bracket is never higher than the 'C' line, and is 4 pitches below.
|
|
27280
|
+
|
|
27281
|
+
// To decide if the bracket goes above or below, go in the direction of the most stems. If there are the same number it will put the bracket above.
|
|
27282
|
+
var up = stemDirectionUp(element);
|
|
27283
|
+
element.up = up;
|
|
27284
|
+
element.startNote = up ? Math.max(element.anchor1.parent.top, 9) + 4 : Math.min(element.anchor1.parent.bottom, 0) - 2;
|
|
27285
|
+
element.endNote = up ? Math.max(element.anchor2.parent.top, 9) + 4 : Math.min(element.anchor2.parent.bottom, 0) - 2;
|
|
27286
|
+
|
|
27116
27287
|
// If it starts or ends on a rest, make the beam horizontal
|
|
27117
27288
|
if (element.anchor1.parent.type === "rest" && element.anchor2.parent.type !== "rest") element.startNote = element.endNote;else if (element.anchor2.parent.type === "rest" && element.anchor1.parent.type !== "rest") element.endNote = element.startNote;
|
|
27118
|
-
|
|
27119
|
-
|
|
27120
|
-
|
|
27121
|
-
|
|
27122
|
-
|
|
27123
|
-
|
|
27124
|
-
|
|
27125
|
-
element.startNote
|
|
27126
|
-
|
|
27289
|
+
if (up) {
|
|
27290
|
+
// See if the middle note is really high.
|
|
27291
|
+
var max = 0;
|
|
27292
|
+
for (var i = 0; i < element.middleElems.length; i++) {
|
|
27293
|
+
max = Math.max(max, element.middleElems[i].top);
|
|
27294
|
+
}
|
|
27295
|
+
max += 4;
|
|
27296
|
+
if (max > element.startNote || max > element.endNote) {
|
|
27297
|
+
element.startNote = max + 3;
|
|
27298
|
+
element.endNote = max + 3;
|
|
27299
|
+
}
|
|
27300
|
+
} else {
|
|
27301
|
+
// See if the middle note is really low.
|
|
27302
|
+
var min = 0;
|
|
27303
|
+
for (var i = 0; i < element.middleElems.length; i++) {
|
|
27304
|
+
min = Math.min(min, element.middleElems[i].bottom - element.middleElems[i].height);
|
|
27305
|
+
}
|
|
27306
|
+
min -= 3;
|
|
27307
|
+
if (min < element.startNote && min < element.endNote) {
|
|
27308
|
+
element.startNote = Math.min(min, element.startNote) - 2;
|
|
27309
|
+
element.endNote = Math.min(min, element.endNote) - 2;
|
|
27310
|
+
}
|
|
27127
27311
|
}
|
|
27128
27312
|
if (element.flatBeams) {
|
|
27129
|
-
|
|
27130
|
-
|
|
27313
|
+
if (up) {
|
|
27314
|
+
element.startNote = Math.max(element.startNote, element.endNote);
|
|
27315
|
+
element.endNote = Math.max(element.startNote, element.endNote);
|
|
27316
|
+
} else {
|
|
27317
|
+
element.startNote = Math.min(element.startNote, element.endNote);
|
|
27318
|
+
element.endNote = Math.min(element.startNote, element.endNote);
|
|
27319
|
+
}
|
|
27131
27320
|
}
|
|
27132
27321
|
element.yTextPos = element.startNote + (element.endNote - element.startNote) / 2;
|
|
27133
27322
|
element.xTextPos = element.anchor1.x + (element.anchor2.x + element.anchor2.w - element.anchor1.x) / 2;
|
|
27134
27323
|
element.top = element.yTextPos + 1;
|
|
27324
|
+
element.bottom = element.yTextPos - 2;
|
|
27135
27325
|
}
|
|
27136
27326
|
}
|
|
27137
27327
|
delete element.middleElems;
|
|
@@ -27140,6 +27330,26 @@ function layoutTriplet(element) {
|
|
|
27140
27330
|
function isAbove(beam) {
|
|
27141
27331
|
return beam.stemsUp;
|
|
27142
27332
|
}
|
|
27333
|
+
function stemDirectionUp(element) {
|
|
27334
|
+
var up = 0;
|
|
27335
|
+
var down = 0;
|
|
27336
|
+
if (element.anchor1) {
|
|
27337
|
+
if (element.anchor1.stemDir === 'up') up++;
|
|
27338
|
+
if (element.anchor1.stemDir === 'down') down++;
|
|
27339
|
+
}
|
|
27340
|
+
if (element.anchor2) {
|
|
27341
|
+
if (element.anchor2.stemDir === 'up') up++;
|
|
27342
|
+
if (element.anchor2.stemDir === 'down') down++;
|
|
27343
|
+
}
|
|
27344
|
+
if (element.middleElems) {
|
|
27345
|
+
for (var i = 0; i < element.middleElems.length; i++) {
|
|
27346
|
+
var elem = element.middleElems[i];
|
|
27347
|
+
if (elem.stemDir === 'up') up++;
|
|
27348
|
+
if (elem.stemDir === 'down') down++;
|
|
27349
|
+
}
|
|
27350
|
+
}
|
|
27351
|
+
return up >= down;
|
|
27352
|
+
}
|
|
27143
27353
|
|
|
27144
27354
|
// 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
|
|
27145
27355
|
function heightAtMidpoint(startX, endX, beam) {
|
|
@@ -27980,7 +28190,7 @@ module.exports = Svg;
|
|
|
27980
28190
|
\********************/
|
|
27981
28191
|
/***/ (function(module) {
|
|
27982
28192
|
|
|
27983
|
-
var version = '6.6.
|
|
28193
|
+
var version = '6.6.3';
|
|
27984
28194
|
module.exports = version;
|
|
27985
28195
|
|
|
27986
28196
|
/***/ })
|