@coderline/alphatab 1.8.0-alpha.1637 → 1.8.0-alpha.1640
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/dist/alphaTab.core.min.mjs +2 -2
- package/dist/alphaTab.core.mjs +860 -757
- package/dist/alphaTab.js +860 -757
- package/dist/alphaTab.min.js +2 -2
- package/dist/alphaTab.min.mjs +1 -1
- package/dist/alphaTab.mjs +1 -1
- package/dist/alphaTab.worker.min.mjs +1 -1
- package/dist/alphaTab.worker.mjs +1 -1
- package/dist/alphaTab.worklet.min.mjs +1 -1
- package/dist/alphaTab.worklet.mjs +1 -1
- package/package.json +3 -3
package/dist/alphaTab.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* alphaTab v1.8.0-alpha.
|
|
2
|
+
* alphaTab v1.8.0-alpha.1640 (develop, build 1640)
|
|
3
3
|
*
|
|
4
4
|
* Copyright © 2025, Daniel Kuschny and Contributors, All rights reserved.
|
|
5
5
|
*
|
|
@@ -209,9 +209,9 @@
|
|
|
209
209
|
* @internal
|
|
210
210
|
*/
|
|
211
211
|
class VersionInfo {
|
|
212
|
-
static version = '1.8.0-alpha.
|
|
213
|
-
static date = '2025-12-
|
|
214
|
-
static commit = '
|
|
212
|
+
static version = '1.8.0-alpha.1640';
|
|
213
|
+
static date = '2025-12-10T02:19:08.776Z';
|
|
214
|
+
static commit = '343f59ee6b39b4f3a41636b3c33db34bccf631f9';
|
|
215
215
|
static print(print) {
|
|
216
216
|
print(`alphaTab ${VersionInfo.version}`);
|
|
217
217
|
print(`commit: ${VersionInfo.commit}`);
|
|
@@ -48533,7 +48533,7 @@
|
|
|
48533
48533
|
onNotes;
|
|
48534
48534
|
minWidth = 0;
|
|
48535
48535
|
get onTimeX() {
|
|
48536
|
-
return this.onNotes.x + this.onNotes.
|
|
48536
|
+
return this.onNotes.x + this.onNotes.onTimeX;
|
|
48537
48537
|
}
|
|
48538
48538
|
constructor(beat, voiceContainer) {
|
|
48539
48539
|
super(0, 0);
|
|
@@ -48557,8 +48557,8 @@
|
|
|
48557
48557
|
return helper.hasFlag(false, undefined);
|
|
48558
48558
|
}
|
|
48559
48559
|
registerLayoutingInfo(layoutings) {
|
|
48560
|
-
const preBeatStretch = this.preNotes.computedWidth + this.onNotes.
|
|
48561
|
-
let postBeatStretch = this.onNotes.computedWidth - this.onNotes.
|
|
48560
|
+
const preBeatStretch = this.preNotes.computedWidth + this.onNotes.onTimeX;
|
|
48561
|
+
let postBeatStretch = this.onNotes.computedWidth - this.onNotes.onTimeX;
|
|
48562
48562
|
// make space for flag
|
|
48563
48563
|
const helper = this.renderer.helpers.getBeamingHelperForBeat(this.beat);
|
|
48564
48564
|
if (this.beat.graceType !== GraceType.None) {
|
|
@@ -48701,7 +48701,7 @@
|
|
|
48701
48701
|
beatBoundings.realBounds.y = barBounds.realBounds.y;
|
|
48702
48702
|
beatBoundings.realBounds.w = this.width;
|
|
48703
48703
|
beatBoundings.realBounds.h = barBounds.realBounds.h;
|
|
48704
|
-
beatBoundings.onNotesX = cx + this.x + this.onNotes.
|
|
48704
|
+
beatBoundings.onNotesX = cx + this.x + this.onNotes.x + this.onNotes.onTimeX;
|
|
48705
48705
|
}
|
|
48706
48706
|
else {
|
|
48707
48707
|
beatBoundings.visualBounds = new Bounds();
|
|
@@ -48739,7 +48739,7 @@
|
|
|
48739
48739
|
beatBoundings.realBounds.y = barBounds.realBounds.y;
|
|
48740
48740
|
beatBoundings.realBounds.w = this.width;
|
|
48741
48741
|
beatBoundings.realBounds.h = barBounds.realBounds.h;
|
|
48742
|
-
beatBoundings.onNotesX = cx + this.x + this.onNotes.x + this.onNotes.
|
|
48742
|
+
beatBoundings.onNotesX = cx + this.x + this.onNotes.x + this.onNotes.onTimeX;
|
|
48743
48743
|
}
|
|
48744
48744
|
barBounds.addBeat(beatBoundings);
|
|
48745
48745
|
if (this.renderer.settings.core.includeNoteBounds) {
|
|
@@ -54364,6 +54364,7 @@
|
|
|
54364
54364
|
class ScalableHtmlElementContainer extends HtmlElementContainer {
|
|
54365
54365
|
_xscale;
|
|
54366
54366
|
_yscale;
|
|
54367
|
+
centerAtPosition = false;
|
|
54367
54368
|
constructor(element, xscale, yscale) {
|
|
54368
54369
|
super(element);
|
|
54369
54370
|
this._xscale = xscale;
|
|
@@ -54405,7 +54406,11 @@
|
|
|
54405
54406
|
else {
|
|
54406
54407
|
h = h / this._yscale;
|
|
54407
54408
|
}
|
|
54408
|
-
|
|
54409
|
+
let transform = `translate(${x}px, ${y}px) scale(${w}, ${h})`;
|
|
54410
|
+
if (this.centerAtPosition) {
|
|
54411
|
+
transform += ` translateX(-50%)`;
|
|
54412
|
+
}
|
|
54413
|
+
this.element.style.transform = transform;
|
|
54409
54414
|
this.element.style.transformOrigin = 'top left';
|
|
54410
54415
|
this.lastBounds.x = x;
|
|
54411
54416
|
this.lastBounds.y = y;
|
|
@@ -55266,6 +55271,7 @@
|
|
|
55266
55271
|
beatCursor.style.willChange = 'transform';
|
|
55267
55272
|
beatCursorContainer.width = 3;
|
|
55268
55273
|
beatCursorContainer.height = 1;
|
|
55274
|
+
beatCursorContainer.centerAtPosition = true;
|
|
55269
55275
|
beatCursorContainer.setBounds(0, 0, 1, 1);
|
|
55270
55276
|
// add cursors to UI
|
|
55271
55277
|
element.insertBefore(cursorWrapper, element.firstChild);
|
|
@@ -56640,7 +56646,7 @@
|
|
|
56640
56646
|
*/
|
|
56641
56647
|
BeatXPosition[BeatXPosition["OnNotes"] = 1] = "OnNotes";
|
|
56642
56648
|
/**
|
|
56643
|
-
* Gets the middle-notes position which is located after in the
|
|
56649
|
+
* Gets the middle-notes position which is located after in the exact center of the note heads.
|
|
56644
56650
|
*/
|
|
56645
56651
|
BeatXPosition[BeatXPosition["MiddleNotes"] = 2] = "MiddleNotes";
|
|
56646
56652
|
/**
|
|
@@ -56670,12 +56676,12 @@
|
|
|
56670
56676
|
this.endPosition = endPosition;
|
|
56671
56677
|
}
|
|
56672
56678
|
get isLinkedWithPrevious() {
|
|
56673
|
-
return !!this.previousGlyph && this.previousGlyph.renderer.staff
|
|
56679
|
+
return !!this.previousGlyph && this.previousGlyph.renderer.staff?.system === this.renderer.staff.system;
|
|
56674
56680
|
}
|
|
56675
56681
|
get isLinkedWithNext() {
|
|
56676
56682
|
return (!!this.nextGlyph &&
|
|
56677
56683
|
this.nextGlyph.renderer.isFinalized &&
|
|
56678
|
-
this.nextGlyph.renderer.staff
|
|
56684
|
+
this.nextGlyph.renderer.staff?.system === this.renderer.staff.system);
|
|
56679
56685
|
}
|
|
56680
56686
|
paint(cx, cy, canvas) {
|
|
56681
56687
|
// if we are linked with the previous, the first glyph of the group will also render this one.
|
|
@@ -59063,6 +59069,437 @@
|
|
|
59063
59069
|
}
|
|
59064
59070
|
}
|
|
59065
59071
|
|
|
59072
|
+
/**
|
|
59073
|
+
* @internal
|
|
59074
|
+
*/
|
|
59075
|
+
class TieGlyph extends Glyph {
|
|
59076
|
+
tieDirection = BeamDirection.Up;
|
|
59077
|
+
slurEffectId;
|
|
59078
|
+
isForEnd;
|
|
59079
|
+
constructor(slurEffectId, forEnd) {
|
|
59080
|
+
super(0, 0);
|
|
59081
|
+
this.slurEffectId = slurEffectId;
|
|
59082
|
+
this.isForEnd = forEnd;
|
|
59083
|
+
}
|
|
59084
|
+
_startX = 0;
|
|
59085
|
+
_startY = 0;
|
|
59086
|
+
_endX = 0;
|
|
59087
|
+
_endY = 0;
|
|
59088
|
+
_tieHeight = 0;
|
|
59089
|
+
_boundingBox;
|
|
59090
|
+
_shouldPaint = false;
|
|
59091
|
+
get checkForOverflow() {
|
|
59092
|
+
return this._shouldPaint && this._boundingBox !== undefined;
|
|
59093
|
+
}
|
|
59094
|
+
getBoundingBoxTop() {
|
|
59095
|
+
if (this._boundingBox) {
|
|
59096
|
+
return this._boundingBox.y;
|
|
59097
|
+
}
|
|
59098
|
+
return this._startY;
|
|
59099
|
+
}
|
|
59100
|
+
getBoundingBoxBottom() {
|
|
59101
|
+
if (this._boundingBox) {
|
|
59102
|
+
return this._boundingBox.y + this._boundingBox.h;
|
|
59103
|
+
}
|
|
59104
|
+
return this._startY;
|
|
59105
|
+
}
|
|
59106
|
+
doLayout() {
|
|
59107
|
+
this.width = 0;
|
|
59108
|
+
const startNoteRenderer = this.lookupStartBeatRenderer();
|
|
59109
|
+
const endNoteRenderer = this.lookupEndBeatRenderer();
|
|
59110
|
+
this._startX = 0;
|
|
59111
|
+
this._endX = 0;
|
|
59112
|
+
this._startY = 0;
|
|
59113
|
+
this._endY = 0;
|
|
59114
|
+
this.height = 0;
|
|
59115
|
+
// if we are on the tie start, we check if we
|
|
59116
|
+
// either can draw till the end note, or we just can draw till the bar end
|
|
59117
|
+
this.tieDirection = this.calculateTieDirection();
|
|
59118
|
+
const forEnd = this.isForEnd;
|
|
59119
|
+
this._shouldPaint = false;
|
|
59120
|
+
if (!forEnd) {
|
|
59121
|
+
if (startNoteRenderer !== endNoteRenderer) {
|
|
59122
|
+
this._startX = this.calculateStartX();
|
|
59123
|
+
this._startY = this.calculateStartY();
|
|
59124
|
+
if (!endNoteRenderer || startNoteRenderer.staff !== endNoteRenderer.staff) {
|
|
59125
|
+
const lastRendererInStaff = startNoteRenderer.staff.barRenderers[startNoteRenderer.staff.barRenderers.length - 1];
|
|
59126
|
+
this._endX = lastRendererInStaff.x + lastRendererInStaff.width;
|
|
59127
|
+
this._endY = this._startY;
|
|
59128
|
+
startNoteRenderer.scoreRenderer.layout.slurRegistry.startMultiSystemSlur(this);
|
|
59129
|
+
}
|
|
59130
|
+
else {
|
|
59131
|
+
this._endX = this.calculateEndX();
|
|
59132
|
+
this._endY = this.caclculateEndY();
|
|
59133
|
+
}
|
|
59134
|
+
}
|
|
59135
|
+
else {
|
|
59136
|
+
this._shouldPaint = true;
|
|
59137
|
+
this._startX = this.calculateStartX();
|
|
59138
|
+
this._endX = this.calculateEndX();
|
|
59139
|
+
this._startY = this.calculateStartY();
|
|
59140
|
+
this._endY = this.caclculateEndY();
|
|
59141
|
+
}
|
|
59142
|
+
this._shouldPaint = true;
|
|
59143
|
+
}
|
|
59144
|
+
else if (startNoteRenderer.staff !== endNoteRenderer.staff) {
|
|
59145
|
+
const firstRendererInStaff = startNoteRenderer.staff.barRenderers[0];
|
|
59146
|
+
this._startX = firstRendererInStaff.x;
|
|
59147
|
+
this._endX = this.calculateEndX();
|
|
59148
|
+
const startGlyph = startNoteRenderer.scoreRenderer.layout.slurRegistry.completeMultiSystemSlur(this);
|
|
59149
|
+
if (startGlyph) {
|
|
59150
|
+
this._startY = startGlyph.calculateMultiSystemSlurY(endNoteRenderer);
|
|
59151
|
+
}
|
|
59152
|
+
else {
|
|
59153
|
+
this._startY = this.caclculateEndY();
|
|
59154
|
+
}
|
|
59155
|
+
this._endY = this.caclculateEndY();
|
|
59156
|
+
this._shouldPaint = startNoteRenderer.staff !== endNoteRenderer.staff;
|
|
59157
|
+
}
|
|
59158
|
+
this._boundingBox = undefined;
|
|
59159
|
+
this.y = Math.min(this._startY, this._endY);
|
|
59160
|
+
if (this.shouldDrawBendSlur()) {
|
|
59161
|
+
this._tieHeight = 0; // TODO: Bend slur height to be considered?
|
|
59162
|
+
}
|
|
59163
|
+
else {
|
|
59164
|
+
this._tieHeight = this.getTieHeight(this._startX, this._startY, this._endX, this._endY);
|
|
59165
|
+
const tieBoundingBox = TieGlyph.calculateActualTieHeight(1, this._startX, this._startY, this._endX, this._endY, this.tieDirection === BeamDirection.Down, this._tieHeight, this.renderer.smuflMetrics.tieMidpointThickness);
|
|
59166
|
+
this._boundingBox = tieBoundingBox;
|
|
59167
|
+
this.height = tieBoundingBox.h;
|
|
59168
|
+
if (this.tieDirection === BeamDirection.Up) {
|
|
59169
|
+
// the tie might go above `this.y` due to its shape
|
|
59170
|
+
// here we calculate how much this is so we can consider the
|
|
59171
|
+
// respective overflow
|
|
59172
|
+
const overlap = this.y - tieBoundingBox.y;
|
|
59173
|
+
if (overlap > 0) {
|
|
59174
|
+
this.y -= overlap;
|
|
59175
|
+
}
|
|
59176
|
+
}
|
|
59177
|
+
}
|
|
59178
|
+
}
|
|
59179
|
+
paint(cx, cy, canvas) {
|
|
59180
|
+
if (!this._shouldPaint) {
|
|
59181
|
+
return;
|
|
59182
|
+
}
|
|
59183
|
+
if (this.shouldDrawBendSlur()) {
|
|
59184
|
+
TieGlyph.drawBendSlur(canvas, cx + this._startX, cy + this._startY, cx + this._endX, cy + this._endY, this.tieDirection === BeamDirection.Down, 1, this.renderer.smuflMetrics.tieHeight);
|
|
59185
|
+
}
|
|
59186
|
+
else {
|
|
59187
|
+
TieGlyph.paintTie(canvas, 1, cx + this._startX, cy + this._startY, cx + this._endX, cy + this._endY, this.tieDirection === BeamDirection.Down, this._tieHeight, this.renderer.smuflMetrics.tieMidpointThickness);
|
|
59188
|
+
}
|
|
59189
|
+
}
|
|
59190
|
+
getTieHeight(_startX, _startY, _endX, _endY) {
|
|
59191
|
+
return this.renderer.smuflMetrics.tieHeight;
|
|
59192
|
+
}
|
|
59193
|
+
calculateMultiSystemSlurY(renderer) {
|
|
59194
|
+
const startRenderer = this.lookupStartBeatRenderer();
|
|
59195
|
+
const startY = this.calculateStartY();
|
|
59196
|
+
const relY = startY - startRenderer.y;
|
|
59197
|
+
return renderer.y + relY;
|
|
59198
|
+
}
|
|
59199
|
+
shouldCreateMultiSystemSlur(renderer) {
|
|
59200
|
+
const endStaff = this.lookupEndBeatRenderer()?.staff;
|
|
59201
|
+
if (!endStaff) {
|
|
59202
|
+
return true;
|
|
59203
|
+
}
|
|
59204
|
+
return renderer.staff.system.index < endStaff.system.index;
|
|
59205
|
+
}
|
|
59206
|
+
static calculateActualTieHeight(scale, x1, y1, x2, y2, down, offset, size) {
|
|
59207
|
+
const cp = TieGlyph._computeBezierControlPoints(scale, x1, y1, x2, y2, down, offset, size);
|
|
59208
|
+
if (cp.length === 0) {
|
|
59209
|
+
return new Bounds(x1, y1, x2 - x1, y2 - y1);
|
|
59210
|
+
}
|
|
59211
|
+
// For a musical tie/slur, the extrema occur predictably near the midpoint
|
|
59212
|
+
// Evaluate at midpoint (t=0.5) and check endpoints
|
|
59213
|
+
const p0x = cp[0];
|
|
59214
|
+
const p0y = cp[1];
|
|
59215
|
+
const c1x = cp[2];
|
|
59216
|
+
const c1y = cp[3];
|
|
59217
|
+
const c2x = cp[4];
|
|
59218
|
+
const c2y = cp[5];
|
|
59219
|
+
const p1x = cp[6];
|
|
59220
|
+
const p1y = cp[7];
|
|
59221
|
+
// Evaluate at t=0.5 for midpoint
|
|
59222
|
+
const midX = 0.125 * p0x + 0.375 * c1x + 0.375 * c2x + 0.125 * p1x;
|
|
59223
|
+
const midY = 0.125 * p0y + 0.375 * c1y + 0.375 * c2y + 0.125 * p1y;
|
|
59224
|
+
// Bounds are simply min/max of start, end, and midpoint
|
|
59225
|
+
const xMin = Math.min(p0x, p1x, midX);
|
|
59226
|
+
const xMax = Math.max(p0x, p1x, midX);
|
|
59227
|
+
let yMin = Math.min(p0y, p1y, midY);
|
|
59228
|
+
let yMax = Math.max(p0y, p1y, midY);
|
|
59229
|
+
// Account for thickness of the tie/slur
|
|
59230
|
+
if (down) {
|
|
59231
|
+
yMax += size;
|
|
59232
|
+
}
|
|
59233
|
+
else {
|
|
59234
|
+
yMin -= size;
|
|
59235
|
+
}
|
|
59236
|
+
const b = new Bounds();
|
|
59237
|
+
b.x = xMin;
|
|
59238
|
+
b.y = yMin;
|
|
59239
|
+
b.w = xMax - xMin;
|
|
59240
|
+
b.h = yMax - yMin;
|
|
59241
|
+
return b;
|
|
59242
|
+
}
|
|
59243
|
+
static _computeBezierControlPoints(scale, x1, y1, x2, y2, down, offset, size) {
|
|
59244
|
+
if (x1 === x2 && y1 === y2) {
|
|
59245
|
+
return [];
|
|
59246
|
+
}
|
|
59247
|
+
// ensure endX > startX
|
|
59248
|
+
if (x2 < x1) {
|
|
59249
|
+
let t = x1;
|
|
59250
|
+
x1 = x2;
|
|
59251
|
+
x2 = t;
|
|
59252
|
+
t = y1;
|
|
59253
|
+
y1 = y2;
|
|
59254
|
+
y2 = t;
|
|
59255
|
+
}
|
|
59256
|
+
//
|
|
59257
|
+
// calculate control points
|
|
59258
|
+
//
|
|
59259
|
+
offset *= scale;
|
|
59260
|
+
size *= scale;
|
|
59261
|
+
if (down) {
|
|
59262
|
+
offset *= -1;
|
|
59263
|
+
size *= -1;
|
|
59264
|
+
}
|
|
59265
|
+
if (scale >= 1) {
|
|
59266
|
+
size *= 1.2;
|
|
59267
|
+
}
|
|
59268
|
+
// calculate control points on horizontal axis then rotate:
|
|
59269
|
+
/*
|
|
59270
|
+
cp1x/cpy1 cp2x/cpy2
|
|
59271
|
+
*----------------*
|
|
59272
|
+
/ \
|
|
59273
|
+
/ \
|
|
59274
|
+
x1/y1 * * x2/y2
|
|
59275
|
+
|
|
59276
|
+
cp3 and cp4 are simply with lower height
|
|
59277
|
+
*/
|
|
59278
|
+
const dY = y2 - y1;
|
|
59279
|
+
const dX = x2 - x1;
|
|
59280
|
+
const length = Math.sqrt(dX * dX + dY * dY);
|
|
59281
|
+
let cp1x = x1 + length * 0.25;
|
|
59282
|
+
let cp1y = y1 - offset;
|
|
59283
|
+
let cp2x = x1 + length * 0.75;
|
|
59284
|
+
let cp2y = y1 - offset;
|
|
59285
|
+
let cp3x = x1 + length * 0.75;
|
|
59286
|
+
let cp3y = y1 - offset - size;
|
|
59287
|
+
let cp4x = x1 + length * 0.25;
|
|
59288
|
+
let cp4y = y1 - offset - size;
|
|
59289
|
+
const angle = Math.atan2(dY, dX);
|
|
59290
|
+
[cp1x, cp1y] = TieGlyph._rotate(cp1x, cp1y, x1, y1, angle);
|
|
59291
|
+
[cp2x, cp2y] = TieGlyph._rotate(cp2x, cp2y, x1, y1, angle);
|
|
59292
|
+
[cp3x, cp3y] = TieGlyph._rotate(cp3x, cp3y, x1, y1, angle);
|
|
59293
|
+
[cp4x, cp4y] = TieGlyph._rotate(cp4x, cp4y, x1, y1, angle);
|
|
59294
|
+
return [x1, y1, cp1x, cp1y, cp2x, cp2y, x2, y2, cp3x, cp3y, cp4x, cp4y, x1, y1];
|
|
59295
|
+
}
|
|
59296
|
+
static _rotate(x, y, rotateX, rotateY, angle) {
|
|
59297
|
+
const dx = x - rotateX;
|
|
59298
|
+
const dy = y - rotateY;
|
|
59299
|
+
const rx = dx * Math.cos(angle) - dy * Math.sin(angle);
|
|
59300
|
+
const ry = dx * Math.sin(angle) + dy * Math.cos(angle);
|
|
59301
|
+
return [rotateX + rx, rotateY + ry];
|
|
59302
|
+
}
|
|
59303
|
+
static paintTie(canvas, scale, x1, y1, x2, y2, down /*= false*/, offset /*= 22*/, size /*= 4*/) {
|
|
59304
|
+
const cps = TieGlyph._computeBezierControlPoints(scale, x1, y1, x2, y2, down, offset, size);
|
|
59305
|
+
canvas.beginPath();
|
|
59306
|
+
canvas.moveTo(cps[0], cps[1]);
|
|
59307
|
+
canvas.bezierCurveTo(cps[2], cps[3], cps[4], cps[5], cps[6], cps[7]);
|
|
59308
|
+
canvas.bezierCurveTo(cps[8], cps[9], cps[10], cps[11], cps[12], cps[13]);
|
|
59309
|
+
canvas.closePath();
|
|
59310
|
+
canvas.fill();
|
|
59311
|
+
}
|
|
59312
|
+
static calculateBendSlurTopY(x1, y1, x2, y2, down, scale, bendSlurHeight) {
|
|
59313
|
+
let normalVectorX = y2 - y1;
|
|
59314
|
+
let normalVectorY = x2 - x1;
|
|
59315
|
+
const length = Math.sqrt(normalVectorX * normalVectorX + normalVectorY * normalVectorY);
|
|
59316
|
+
if (down) {
|
|
59317
|
+
normalVectorX *= -1;
|
|
59318
|
+
}
|
|
59319
|
+
else {
|
|
59320
|
+
normalVectorY *= -1;
|
|
59321
|
+
}
|
|
59322
|
+
// make to unit vector
|
|
59323
|
+
normalVectorX /= length;
|
|
59324
|
+
normalVectorY /= length;
|
|
59325
|
+
let offset = bendSlurHeight * scale;
|
|
59326
|
+
if (x2 - x1 < 20) {
|
|
59327
|
+
offset /= 2;
|
|
59328
|
+
}
|
|
59329
|
+
const centerY = (y2 + y1) / 2;
|
|
59330
|
+
const cp1Y = centerY + offset * normalVectorY;
|
|
59331
|
+
return cp1Y;
|
|
59332
|
+
}
|
|
59333
|
+
static drawBendSlur(canvas, x1, y1, x2, y2, down, scale, bendSlurHeight, slurText) {
|
|
59334
|
+
let normalVectorX = y2 - y1;
|
|
59335
|
+
let normalVectorY = x2 - x1;
|
|
59336
|
+
const length = Math.sqrt(normalVectorX * normalVectorX + normalVectorY * normalVectorY);
|
|
59337
|
+
if (down) {
|
|
59338
|
+
normalVectorX *= -1;
|
|
59339
|
+
}
|
|
59340
|
+
else {
|
|
59341
|
+
normalVectorY *= -1;
|
|
59342
|
+
}
|
|
59343
|
+
// make to unit vector
|
|
59344
|
+
normalVectorX /= length;
|
|
59345
|
+
normalVectorY /= length;
|
|
59346
|
+
// center of connection
|
|
59347
|
+
// TODO: should be 1/3
|
|
59348
|
+
const centerX = (x2 + x1) / 2;
|
|
59349
|
+
const centerY = (y2 + y1) / 2;
|
|
59350
|
+
let offset = bendSlurHeight * scale;
|
|
59351
|
+
if (x2 - x1 < 20) {
|
|
59352
|
+
offset /= 2;
|
|
59353
|
+
}
|
|
59354
|
+
const cp1X = centerX + offset * normalVectorX;
|
|
59355
|
+
const cp1Y = centerY + offset * normalVectorY;
|
|
59356
|
+
canvas.beginPath();
|
|
59357
|
+
canvas.moveTo(x1, y1);
|
|
59358
|
+
canvas.lineTo(cp1X, cp1Y);
|
|
59359
|
+
canvas.lineTo(x2, y2);
|
|
59360
|
+
canvas.stroke();
|
|
59361
|
+
if (slurText) {
|
|
59362
|
+
const w = canvas.measureText(slurText).width;
|
|
59363
|
+
const textOffset = down ? 0 : -canvas.font.size;
|
|
59364
|
+
canvas.fillText(slurText, cp1X - w / 2, cp1Y + textOffset);
|
|
59365
|
+
}
|
|
59366
|
+
}
|
|
59367
|
+
}
|
|
59368
|
+
/**
|
|
59369
|
+
* A common tie implementation using note details for positioning
|
|
59370
|
+
* @internal
|
|
59371
|
+
*/
|
|
59372
|
+
class NoteTieGlyph extends TieGlyph {
|
|
59373
|
+
startNote;
|
|
59374
|
+
endNote;
|
|
59375
|
+
startNoteRenderer = null;
|
|
59376
|
+
endNoteRenderer = null;
|
|
59377
|
+
constructor(slurEffectId, startNote, endNote, forEnd) {
|
|
59378
|
+
super(slurEffectId, forEnd);
|
|
59379
|
+
this.startNote = startNote;
|
|
59380
|
+
this.endNote = endNote;
|
|
59381
|
+
}
|
|
59382
|
+
get isLeftHandTap() {
|
|
59383
|
+
return this.startNote === this.endNote;
|
|
59384
|
+
}
|
|
59385
|
+
getTieHeight(startX, startY, endX, endY) {
|
|
59386
|
+
if (this.isLeftHandTap) {
|
|
59387
|
+
return this.renderer.smuflMetrics.tieHeight;
|
|
59388
|
+
}
|
|
59389
|
+
return super.getTieHeight(startX, startY, endX, endY);
|
|
59390
|
+
}
|
|
59391
|
+
calculateTieDirection() {
|
|
59392
|
+
// invert direction (if stems go up, ties go down to not cross them)
|
|
59393
|
+
switch (this.lookupStartBeatRenderer().getBeatDirection(this.startNote.beat)) {
|
|
59394
|
+
case BeamDirection.Up:
|
|
59395
|
+
return BeamDirection.Down;
|
|
59396
|
+
default:
|
|
59397
|
+
return BeamDirection.Up;
|
|
59398
|
+
}
|
|
59399
|
+
}
|
|
59400
|
+
calculateStartX() {
|
|
59401
|
+
const startNoteRenderer = this.lookupStartBeatRenderer();
|
|
59402
|
+
if (this.isLeftHandTap) {
|
|
59403
|
+
return this.calculateEndX() - startNoteRenderer.smuflMetrics.leftHandTabTieWidth;
|
|
59404
|
+
}
|
|
59405
|
+
return startNoteRenderer.x + startNoteRenderer.getNoteX(this.startNote, this.getStartNotePosition());
|
|
59406
|
+
}
|
|
59407
|
+
getStartNotePosition() {
|
|
59408
|
+
return NoteXPosition.Center;
|
|
59409
|
+
}
|
|
59410
|
+
calculateStartY() {
|
|
59411
|
+
const startNoteRenderer = this.lookupStartBeatRenderer();
|
|
59412
|
+
if (this.isLeftHandTap) {
|
|
59413
|
+
return startNoteRenderer.y + startNoteRenderer.getNoteY(this.startNote, NoteYPosition.Center);
|
|
59414
|
+
}
|
|
59415
|
+
switch (this.tieDirection) {
|
|
59416
|
+
case BeamDirection.Up:
|
|
59417
|
+
return startNoteRenderer.y + startNoteRenderer.getNoteY(this.startNote, NoteYPosition.Top);
|
|
59418
|
+
default:
|
|
59419
|
+
return startNoteRenderer.y + startNoteRenderer.getNoteY(this.startNote, NoteYPosition.Bottom);
|
|
59420
|
+
}
|
|
59421
|
+
}
|
|
59422
|
+
calculateEndX() {
|
|
59423
|
+
const endNoteRenderer = this.lookupEndBeatRenderer();
|
|
59424
|
+
if (!endNoteRenderer) {
|
|
59425
|
+
return this.calculateStartY() + this.renderer.smuflMetrics.leftHandTabTieWidth;
|
|
59426
|
+
}
|
|
59427
|
+
if (this.isLeftHandTap) {
|
|
59428
|
+
return endNoteRenderer.x + endNoteRenderer.getNoteX(this.endNote, NoteXPosition.Left);
|
|
59429
|
+
}
|
|
59430
|
+
return endNoteRenderer.x + endNoteRenderer.getNoteX(this.endNote, NoteXPosition.Center);
|
|
59431
|
+
}
|
|
59432
|
+
getEndNotePosition() {
|
|
59433
|
+
return NoteXPosition.Center;
|
|
59434
|
+
}
|
|
59435
|
+
caclculateEndY() {
|
|
59436
|
+
const endNoteRenderer = this.lookupEndBeatRenderer();
|
|
59437
|
+
if (!endNoteRenderer) {
|
|
59438
|
+
return this.calculateStartY();
|
|
59439
|
+
}
|
|
59440
|
+
if (this.isLeftHandTap) {
|
|
59441
|
+
return endNoteRenderer.y + endNoteRenderer.getNoteY(this.endNote, NoteYPosition.Center);
|
|
59442
|
+
}
|
|
59443
|
+
switch (this.tieDirection) {
|
|
59444
|
+
case BeamDirection.Up:
|
|
59445
|
+
return endNoteRenderer.y + endNoteRenderer.getNoteY(this.endNote, NoteYPosition.Top);
|
|
59446
|
+
default:
|
|
59447
|
+
return endNoteRenderer.y + endNoteRenderer.getNoteY(this.endNote, NoteYPosition.Bottom);
|
|
59448
|
+
}
|
|
59449
|
+
}
|
|
59450
|
+
lookupEndBeatRenderer() {
|
|
59451
|
+
if (!this.endNoteRenderer) {
|
|
59452
|
+
this.endNoteRenderer = this.renderer.scoreRenderer.layout.getRendererForBar(this.renderer.staff.staffId, this.endNote.beat.voice.bar);
|
|
59453
|
+
}
|
|
59454
|
+
return this.endNoteRenderer;
|
|
59455
|
+
}
|
|
59456
|
+
lookupStartBeatRenderer() {
|
|
59457
|
+
if (!this.startNoteRenderer) {
|
|
59458
|
+
this.startNoteRenderer = this.renderer.scoreRenderer.layout.getRendererForBar(this.renderer.staff.staffId, this.startNote.beat.voice.bar);
|
|
59459
|
+
}
|
|
59460
|
+
return this.startNoteRenderer;
|
|
59461
|
+
}
|
|
59462
|
+
shouldDrawBendSlur() {
|
|
59463
|
+
return false;
|
|
59464
|
+
}
|
|
59465
|
+
}
|
|
59466
|
+
/**
|
|
59467
|
+
* A tie glyph for continued multi-system ties/slurs
|
|
59468
|
+
* @internal
|
|
59469
|
+
*/
|
|
59470
|
+
class ContinuationTieGlyph extends TieGlyph {
|
|
59471
|
+
_startTie;
|
|
59472
|
+
constructor(startTie) {
|
|
59473
|
+
super(startTie.slurEffectId, false);
|
|
59474
|
+
this._startTie = startTie;
|
|
59475
|
+
}
|
|
59476
|
+
lookupStartBeatRenderer() {
|
|
59477
|
+
return this.renderer;
|
|
59478
|
+
}
|
|
59479
|
+
lookupEndBeatRenderer() {
|
|
59480
|
+
return this.renderer;
|
|
59481
|
+
}
|
|
59482
|
+
shouldDrawBendSlur() {
|
|
59483
|
+
return false;
|
|
59484
|
+
}
|
|
59485
|
+
calculateTieDirection() {
|
|
59486
|
+
return this._startTie.tieDirection;
|
|
59487
|
+
}
|
|
59488
|
+
calculateStartY() {
|
|
59489
|
+
return this._startTie.calculateMultiSystemSlurY(this.renderer);
|
|
59490
|
+
}
|
|
59491
|
+
caclculateEndY() {
|
|
59492
|
+
return this.calculateStartY();
|
|
59493
|
+
}
|
|
59494
|
+
calculateStartX() {
|
|
59495
|
+
return this.renderer.staff.barRenderers[0].x;
|
|
59496
|
+
}
|
|
59497
|
+
calculateEndX() {
|
|
59498
|
+
const last = this.renderer.staff.barRenderers[this.renderer.staff.barRenderers.length - 1];
|
|
59499
|
+
return last.x + last.width;
|
|
59500
|
+
}
|
|
59501
|
+
}
|
|
59502
|
+
|
|
59066
59503
|
/**
|
|
59067
59504
|
* This glyph acts as container for handling
|
|
59068
59505
|
* multiple voice rendering
|
|
@@ -59533,6 +59970,63 @@
|
|
|
59533
59970
|
}
|
|
59534
59971
|
}
|
|
59535
59972
|
|
|
59973
|
+
/**
|
|
59974
|
+
* This registry keeps track of which slurs and ties were started and needs completion.
|
|
59975
|
+
* Slurs might span multiple systems, and in such cases we need to create additional
|
|
59976
|
+
* slur/ties in the intermediate and end system.
|
|
59977
|
+
*
|
|
59978
|
+
* @internal
|
|
59979
|
+
*
|
|
59980
|
+
*/
|
|
59981
|
+
class SlurRegistry {
|
|
59982
|
+
_staffLookup = new Map();
|
|
59983
|
+
clear() {
|
|
59984
|
+
this._staffLookup.clear();
|
|
59985
|
+
}
|
|
59986
|
+
startMultiSystemSlur(startGlyph) {
|
|
59987
|
+
const staffId = SlurRegistry._staffId(startGlyph.renderer.staff);
|
|
59988
|
+
let container;
|
|
59989
|
+
if (!this._staffLookup.has(staffId)) {
|
|
59990
|
+
container = {
|
|
59991
|
+
startedSlurs: new Map()
|
|
59992
|
+
};
|
|
59993
|
+
this._staffLookup.set(staffId, container);
|
|
59994
|
+
}
|
|
59995
|
+
else {
|
|
59996
|
+
container = this._staffLookup.get(staffId);
|
|
59997
|
+
}
|
|
59998
|
+
container.startedSlurs.set(startGlyph.slurEffectId, { startGlyph });
|
|
59999
|
+
}
|
|
60000
|
+
static _staffId(staff) {
|
|
60001
|
+
return `${staff.modelStaff.index}.${staff.modelStaff.track.index}.${staff.staffId}`;
|
|
60002
|
+
}
|
|
60003
|
+
completeMultiSystemSlur(endGlyph) {
|
|
60004
|
+
const staffId = SlurRegistry._staffId(endGlyph.renderer.staff);
|
|
60005
|
+
if (!this._staffLookup.has(staffId)) {
|
|
60006
|
+
return undefined;
|
|
60007
|
+
}
|
|
60008
|
+
const container = this._staffLookup.get(staffId);
|
|
60009
|
+
if (container.startedSlurs.has(endGlyph.slurEffectId)) {
|
|
60010
|
+
const info = container.startedSlurs.get(endGlyph.slurEffectId);
|
|
60011
|
+
info.endGlyph = endGlyph;
|
|
60012
|
+
return info.startGlyph;
|
|
60013
|
+
}
|
|
60014
|
+
return undefined;
|
|
60015
|
+
}
|
|
60016
|
+
*getAllContinuations(renderer) {
|
|
60017
|
+
const staffId = SlurRegistry._staffId(renderer.staff);
|
|
60018
|
+
if (!this._staffLookup.has(staffId) || renderer.index > 0) {
|
|
60019
|
+
return;
|
|
60020
|
+
}
|
|
60021
|
+
const container = this._staffLookup.get(staffId);
|
|
60022
|
+
for (const g of container.startedSlurs.values()) {
|
|
60023
|
+
if (g.startGlyph.shouldCreateMultiSystemSlur(renderer)) {
|
|
60024
|
+
yield g.startGlyph;
|
|
60025
|
+
}
|
|
60026
|
+
}
|
|
60027
|
+
}
|
|
60028
|
+
}
|
|
60029
|
+
|
|
59536
60030
|
/**
|
|
59537
60031
|
* A Staff represents a single line within a StaffSystem.
|
|
59538
60032
|
* It stores BarRenderer instances created from a given factory.
|
|
@@ -59654,7 +60148,6 @@
|
|
|
59654
60148
|
this._sharedLayoutData = new Map();
|
|
59655
60149
|
const lastBar = this.barRenderers[this.barRenderers.length - 1];
|
|
59656
60150
|
this.barRenderers.splice(this.barRenderers.length - 1, 1);
|
|
59657
|
-
this.system.layout.unregisterBarRenderer(this.staffId, lastBar);
|
|
59658
60151
|
this.topOverflow = 0;
|
|
59659
60152
|
this.bottomOverflow = 0;
|
|
59660
60153
|
for (const r of this.barRenderers) {
|
|
@@ -59747,23 +60240,23 @@
|
|
|
59747
60240
|
// changes in the overflows
|
|
59748
60241
|
let needsSecondPass = false;
|
|
59749
60242
|
let topOverflow = this.topOverflow;
|
|
59750
|
-
for (
|
|
59751
|
-
this.
|
|
59752
|
-
if (
|
|
60243
|
+
for (const renderer of this.barRenderers) {
|
|
60244
|
+
renderer.registerMultiSystemSlurs(this.system.layout.slurRegistry.getAllContinuations(renderer));
|
|
60245
|
+
if (renderer.finalizeRenderer()) {
|
|
59753
60246
|
needsSecondPass = true;
|
|
59754
60247
|
}
|
|
59755
|
-
this.height = Math.max(this.height,
|
|
60248
|
+
this.height = Math.max(this.height, renderer.height);
|
|
59756
60249
|
}
|
|
59757
60250
|
// 2nd pass: move renderers to correct position respecting the new overflows
|
|
59758
60251
|
if (needsSecondPass) {
|
|
59759
60252
|
topOverflow = this.topOverflow;
|
|
59760
60253
|
// shift all the renderers to the new position to match required spacing
|
|
59761
|
-
for (
|
|
59762
|
-
|
|
60254
|
+
for (const renderer of this.barRenderers) {
|
|
60255
|
+
renderer.y = this.topPadding + topOverflow;
|
|
59763
60256
|
}
|
|
59764
60257
|
// finalize again (to align ties)
|
|
59765
|
-
for (
|
|
59766
|
-
|
|
60258
|
+
for (const renderer of this.barRenderers) {
|
|
60259
|
+
renderer.finalizeRenderer();
|
|
59767
60260
|
}
|
|
59768
60261
|
}
|
|
59769
60262
|
if (this.height > 0) {
|
|
@@ -60369,6 +60862,7 @@
|
|
|
60369
60862
|
if (newBarDisplayScale > barDisplayScale) {
|
|
60370
60863
|
barDisplayScale = newBarDisplayScale;
|
|
60371
60864
|
}
|
|
60865
|
+
lastBar.afterReverted();
|
|
60372
60866
|
}
|
|
60373
60867
|
this.width -= width;
|
|
60374
60868
|
this.computedWidth -= width;
|
|
@@ -60888,12 +61382,16 @@
|
|
|
60888
61382
|
constructor(renderer) {
|
|
60889
61383
|
this.renderer = renderer;
|
|
60890
61384
|
}
|
|
61385
|
+
slurRegistry = new SlurRegistry();
|
|
60891
61386
|
resize() {
|
|
60892
61387
|
this._lazyPartials.clear();
|
|
61388
|
+
this.slurRegistry.clear();
|
|
60893
61389
|
this.doResize();
|
|
60894
61390
|
}
|
|
60895
61391
|
layoutAndRender() {
|
|
60896
61392
|
this._lazyPartials.clear();
|
|
61393
|
+
this.slurRegistry.clear();
|
|
61394
|
+
this._barRendererLookup.clear();
|
|
60897
61395
|
this.profile = Environment.staveProfiles.get(this.renderer.settings.display.staveProfile);
|
|
60898
61396
|
const score = this.renderer.score;
|
|
60899
61397
|
this.firstBarIndex = ModelUtils.computeFirstDisplayedBarIndex(score, this.renderer.settings);
|
|
@@ -61162,17 +61660,6 @@
|
|
|
61162
61660
|
}
|
|
61163
61661
|
}
|
|
61164
61662
|
}
|
|
61165
|
-
unregisterBarRenderer(key, renderer) {
|
|
61166
|
-
if (this._barRendererLookup.has(key)) {
|
|
61167
|
-
const lookup = this._barRendererLookup.get(key);
|
|
61168
|
-
lookup.delete(renderer.bar.id);
|
|
61169
|
-
if (renderer.additionalMultiRestBars) {
|
|
61170
|
-
for (const b of renderer.additionalMultiRestBars) {
|
|
61171
|
-
lookup.delete(b.id);
|
|
61172
|
-
}
|
|
61173
|
-
}
|
|
61174
|
-
}
|
|
61175
|
-
}
|
|
61176
61663
|
getRendererForBar(key, bar) {
|
|
61177
61664
|
const barRendererId = bar.id;
|
|
61178
61665
|
if (this._barRendererLookup.has(key) && this._barRendererLookup.get(key).has(barRendererId)) {
|
|
@@ -61338,7 +61825,8 @@
|
|
|
61338
61825
|
*/
|
|
61339
61826
|
class BeatOnNoteGlyphBase extends BeatGlyphBase {
|
|
61340
61827
|
beamingHelper;
|
|
61341
|
-
|
|
61828
|
+
onTimeX = 0;
|
|
61829
|
+
middleX = 0;
|
|
61342
61830
|
updateBeamingHelper() {
|
|
61343
61831
|
}
|
|
61344
61832
|
buildBoundingsLookup(_beatBounds, _cx, _cy) {
|
|
@@ -62161,6 +62649,7 @@
|
|
|
62161
62649
|
_voiceContainers = new Map();
|
|
62162
62650
|
_postBeatGlyphs = new LeftToRightLayoutingGlyphGroup();
|
|
62163
62651
|
_ties = [];
|
|
62652
|
+
_multiSystemSlurs;
|
|
62164
62653
|
topEffects;
|
|
62165
62654
|
bottomEffects;
|
|
62166
62655
|
get nextRenderer() {
|
|
@@ -62313,6 +62802,11 @@
|
|
|
62313
62802
|
}
|
|
62314
62803
|
}
|
|
62315
62804
|
_appliedLayoutingInfo = 0;
|
|
62805
|
+
afterReverted() {
|
|
62806
|
+
this.staff = undefined;
|
|
62807
|
+
this.registerMultiSystemSlurs(undefined);
|
|
62808
|
+
this.isFinalized = false;
|
|
62809
|
+
}
|
|
62316
62810
|
afterStaffBarReverted() {
|
|
62317
62811
|
this.topEffects.afterStaffBarReverted();
|
|
62318
62812
|
this.bottomEffects.afterStaffBarReverted();
|
|
@@ -62358,13 +62852,26 @@
|
|
|
62358
62852
|
return true;
|
|
62359
62853
|
}
|
|
62360
62854
|
isFinalized = false;
|
|
62361
|
-
|
|
62362
|
-
|
|
62855
|
+
registerMultiSystemSlurs(startedTies) {
|
|
62856
|
+
if (!startedTies) {
|
|
62857
|
+
this._multiSystemSlurs = undefined;
|
|
62858
|
+
return;
|
|
62859
|
+
}
|
|
62860
|
+
let ties = undefined;
|
|
62861
|
+
for (const g of startedTies) {
|
|
62862
|
+
const continuation = new ContinuationTieGlyph(g);
|
|
62863
|
+
continuation.renderer = this;
|
|
62864
|
+
continuation.tieDirection = g.tieDirection;
|
|
62865
|
+
if (!ties) {
|
|
62866
|
+
ties = [];
|
|
62867
|
+
}
|
|
62868
|
+
ties.push(continuation);
|
|
62869
|
+
}
|
|
62870
|
+
this._multiSystemSlurs = ties;
|
|
62871
|
+
}
|
|
62872
|
+
_finalizeTies(ties, barTop, barBottom) {
|
|
62363
62873
|
let didChangeOverflows = false;
|
|
62364
|
-
|
|
62365
|
-
const barTop = this.y;
|
|
62366
|
-
const barBottom = this.y + this.height;
|
|
62367
|
-
for (const t of this._ties) {
|
|
62874
|
+
for (const t of ties) {
|
|
62368
62875
|
const tie = t;
|
|
62369
62876
|
tie.doLayout();
|
|
62370
62877
|
if (t.checkForOverflow) {
|
|
@@ -62385,6 +62892,21 @@
|
|
|
62385
62892
|
}
|
|
62386
62893
|
}
|
|
62387
62894
|
}
|
|
62895
|
+
return didChangeOverflows;
|
|
62896
|
+
}
|
|
62897
|
+
finalizeRenderer() {
|
|
62898
|
+
this.isFinalized = true;
|
|
62899
|
+
let didChangeOverflows = false;
|
|
62900
|
+
// allow spacing to be used for tie overflows
|
|
62901
|
+
const barTop = this.y;
|
|
62902
|
+
const barBottom = this.y + this.height;
|
|
62903
|
+
if (this._finalizeTies(this._ties, barTop, barBottom)) {
|
|
62904
|
+
didChangeOverflows = true;
|
|
62905
|
+
}
|
|
62906
|
+
const multiSystemSlurs = this._multiSystemSlurs;
|
|
62907
|
+
if (multiSystemSlurs && this._finalizeTies(multiSystemSlurs, barTop, barBottom)) {
|
|
62908
|
+
didChangeOverflows = true;
|
|
62909
|
+
}
|
|
62388
62910
|
const topHeightChanged = this.topEffects.finalizeEffects();
|
|
62389
62911
|
const bottomHeightChanged = this.bottomEffects.finalizeEffects();
|
|
62390
62912
|
if (topHeightChanged || bottomHeightChanged) {
|
|
@@ -62565,6 +63087,16 @@
|
|
|
62565
63087
|
}
|
|
62566
63088
|
canvas.color = this.resources.mainGlyphColor;
|
|
62567
63089
|
this._postBeatGlyphs.paint(cx + this.x, cy + this.y, canvas);
|
|
63090
|
+
this._paintMultiSystemSlurs(cx, cy, canvas);
|
|
63091
|
+
}
|
|
63092
|
+
_paintMultiSystemSlurs(cx, cy, canvas) {
|
|
63093
|
+
const multiSystemSlurs = this._multiSystemSlurs;
|
|
63094
|
+
if (!multiSystemSlurs) {
|
|
63095
|
+
return;
|
|
63096
|
+
}
|
|
63097
|
+
for (const slur of multiSystemSlurs) {
|
|
63098
|
+
slur.paint(cx, cy, canvas);
|
|
63099
|
+
}
|
|
62568
63100
|
}
|
|
62569
63101
|
paintBackground(cx, cy, canvas) {
|
|
62570
63102
|
this.layoutingInfo.paint(cx + this.x + this._preBeatGlyphs.x + this._preBeatGlyphs.width, cy + this.y + this.height, canvas);
|
|
@@ -62630,7 +63162,7 @@
|
|
|
62630
63162
|
case BeatXPosition.OnNotes:
|
|
62631
63163
|
return container.voiceContainer.x + container.x + container.onNotes.x;
|
|
62632
63164
|
case BeatXPosition.MiddleNotes:
|
|
62633
|
-
return container.voiceContainer.x + container.x + container.
|
|
63165
|
+
return container.voiceContainer.x + container.x + container.onNotes.x + container.onNotes.middleX;
|
|
62634
63166
|
case BeatXPosition.Stem:
|
|
62635
63167
|
const offset = container.onNotes.beamingHelper
|
|
62636
63168
|
? container.onNotes.beamingHelper.getBeatLineX(beat)
|
|
@@ -64643,6 +65175,13 @@
|
|
|
64643
65175
|
}
|
|
64644
65176
|
}
|
|
64645
65177
|
else {
|
|
65178
|
+
// clear out staves during re-layout, this info is outdated during
|
|
65179
|
+
// re-layout of the bars
|
|
65180
|
+
for (const r of this._allMasterBarRenderers) {
|
|
65181
|
+
for (const b of r.renderers) {
|
|
65182
|
+
b.afterReverted();
|
|
65183
|
+
}
|
|
65184
|
+
}
|
|
64646
65185
|
this._systems = [];
|
|
64647
65186
|
let currentIndex = 0;
|
|
64648
65187
|
const maxWidth = this._maxWidth;
|
|
@@ -65104,7 +65643,7 @@
|
|
|
65104
65643
|
// as during layout things are still moving
|
|
65105
65644
|
let actualLineHeight = this.height;
|
|
65106
65645
|
const thisStaff = renderer.staff;
|
|
65107
|
-
const allStaves =
|
|
65646
|
+
const allStaves = thisStaff.system.allStaves;
|
|
65108
65647
|
let isExtended = false;
|
|
65109
65648
|
if (this._extendToNextStaff && thisStaff.index < allStaves.length - 1) {
|
|
65110
65649
|
const nextStaff = allStaves[thisStaff.index + 1];
|
|
@@ -65286,7 +65825,7 @@
|
|
|
65286
65825
|
}
|
|
65287
65826
|
// during system fitting it can happen that we have fraction widths
|
|
65288
65827
|
// but to have lines until the full end-pixel we round up.
|
|
65289
|
-
// this way we avoid holes,
|
|
65828
|
+
// this way we avoid holes,
|
|
65290
65829
|
const lineWidth = this.width;
|
|
65291
65830
|
// we want the lines to be exactly virtually aligned with the respective Y-position
|
|
65292
65831
|
// for note heads to align correctly
|
|
@@ -66052,375 +66591,23 @@
|
|
|
66052
66591
|
/**
|
|
66053
66592
|
* @internal
|
|
66054
66593
|
*/
|
|
66055
|
-
class
|
|
66056
|
-
startBeat;
|
|
66057
|
-
endBeat;
|
|
66058
|
-
yOffset = 0;
|
|
66059
|
-
forEnd;
|
|
66060
|
-
startNoteRenderer = null;
|
|
66061
|
-
endNoteRenderer = null;
|
|
66062
|
-
tieDirection = BeamDirection.Up;
|
|
66063
|
-
constructor(startBeat, endBeat, forEnd) {
|
|
66064
|
-
super(0, 0);
|
|
66065
|
-
this.startBeat = startBeat;
|
|
66066
|
-
this.endBeat = endBeat;
|
|
66067
|
-
this.forEnd = forEnd;
|
|
66068
|
-
}
|
|
66069
|
-
_startX = 0;
|
|
66070
|
-
_startY = 0;
|
|
66071
|
-
_endX = 0;
|
|
66072
|
-
_endY = 0;
|
|
66073
|
-
_tieHeight = 0;
|
|
66074
|
-
_shouldDraw = false;
|
|
66075
|
-
_boundingBox;
|
|
66076
|
-
get checkForOverflow() {
|
|
66077
|
-
return this._boundingBox !== undefined;
|
|
66078
|
-
}
|
|
66079
|
-
getBoundingBoxTop() {
|
|
66080
|
-
if (this._boundingBox) {
|
|
66081
|
-
return this._boundingBox.y;
|
|
66082
|
-
}
|
|
66083
|
-
return this._startY;
|
|
66084
|
-
}
|
|
66085
|
-
getBoundingBoxBottom() {
|
|
66086
|
-
if (this._boundingBox) {
|
|
66087
|
-
return this._boundingBox.y + this._boundingBox.h;
|
|
66088
|
-
}
|
|
66089
|
-
return this._startY;
|
|
66090
|
-
}
|
|
66091
|
-
doLayout() {
|
|
66092
|
-
this.width = 0;
|
|
66093
|
-
// TODO fix nullability of start/end beat,
|
|
66094
|
-
if (!this.endBeat) {
|
|
66095
|
-
this._shouldDraw = false;
|
|
66096
|
-
return;
|
|
66097
|
-
}
|
|
66098
|
-
const startNoteRenderer = this.renderer.scoreRenderer.layout.getRendererForBar(this.renderer.staff.staffId, this.startBeat.voice.bar);
|
|
66099
|
-
this.startNoteRenderer = startNoteRenderer;
|
|
66100
|
-
const endNoteRenderer = this.renderer.scoreRenderer.layout.getRendererForBar(this.renderer.staff.staffId, this.endBeat.voice.bar);
|
|
66101
|
-
this.endNoteRenderer = endNoteRenderer;
|
|
66102
|
-
this._startX = 0;
|
|
66103
|
-
this._endX = 0;
|
|
66104
|
-
this._startY = 0;
|
|
66105
|
-
this._endY = 0;
|
|
66106
|
-
this.height = 0;
|
|
66107
|
-
this._shouldDraw = false;
|
|
66108
|
-
// if we are on the tie start, we check if we
|
|
66109
|
-
// either can draw till the end note, or we just can draw till the bar end
|
|
66110
|
-
this.tieDirection = !startNoteRenderer
|
|
66111
|
-
? this.getBeamDirection(this.endBeat, endNoteRenderer)
|
|
66112
|
-
: this.getBeamDirection(this.startBeat, startNoteRenderer);
|
|
66113
|
-
if (!this.forEnd && startNoteRenderer) {
|
|
66114
|
-
// line break or bar break
|
|
66115
|
-
if (startNoteRenderer !== endNoteRenderer) {
|
|
66116
|
-
this._startX = startNoteRenderer.x + this.getStartX();
|
|
66117
|
-
this._startY = startNoteRenderer.y + this.getStartY() + this.yOffset;
|
|
66118
|
-
// line break: to bar end
|
|
66119
|
-
if (!endNoteRenderer || startNoteRenderer.staff !== endNoteRenderer.staff) {
|
|
66120
|
-
this._endX = startNoteRenderer.x + startNoteRenderer.width;
|
|
66121
|
-
this._endY = this._startY;
|
|
66122
|
-
}
|
|
66123
|
-
else {
|
|
66124
|
-
this._endX = endNoteRenderer.x + this.getEndX();
|
|
66125
|
-
this._endY = endNoteRenderer.y + this.getEndY() + this.yOffset;
|
|
66126
|
-
}
|
|
66127
|
-
}
|
|
66128
|
-
else {
|
|
66129
|
-
this._startX = startNoteRenderer.x + this.getStartX();
|
|
66130
|
-
this._endX = endNoteRenderer.x + this.getEndX();
|
|
66131
|
-
this._startY = startNoteRenderer.y + this.getStartY() + this.yOffset;
|
|
66132
|
-
this._endY = endNoteRenderer.y + this.getEndY() + this.yOffset;
|
|
66133
|
-
}
|
|
66134
|
-
this._shouldDraw = true;
|
|
66135
|
-
}
|
|
66136
|
-
else if (!startNoteRenderer || startNoteRenderer.staff !== endNoteRenderer.staff) {
|
|
66137
|
-
this._startX = endNoteRenderer.x;
|
|
66138
|
-
this._endX = endNoteRenderer.x + this.getEndX();
|
|
66139
|
-
this._startY = endNoteRenderer.y + this.getEndY() + this.yOffset;
|
|
66140
|
-
this._endY = this._startY;
|
|
66141
|
-
this._shouldDraw = true;
|
|
66142
|
-
}
|
|
66143
|
-
this._boundingBox = undefined;
|
|
66144
|
-
if (this._shouldDraw) {
|
|
66145
|
-
this.y = Math.min(this._startY, this._endY);
|
|
66146
|
-
if (this.shouldDrawBendSlur()) {
|
|
66147
|
-
this._tieHeight = 0; // TODO: Bend slur height to be considered?
|
|
66148
|
-
}
|
|
66149
|
-
else {
|
|
66150
|
-
this._tieHeight = this.getTieHeight(this._startX, this._startY, this._endX, this._endY);
|
|
66151
|
-
const tieBoundingBox = TieGlyph.calculateActualTieHeight(1, this._startX, this._startY, this._endX, this._endY, this.tieDirection === BeamDirection.Down, this._tieHeight, this.renderer.smuflMetrics.tieMidpointThickness);
|
|
66152
|
-
this._boundingBox = tieBoundingBox;
|
|
66153
|
-
this.height = tieBoundingBox.h;
|
|
66154
|
-
if (this.tieDirection === BeamDirection.Up) {
|
|
66155
|
-
// the tie might go above `this.y` due to its shape
|
|
66156
|
-
// here we calculate how much this is so we can consider the
|
|
66157
|
-
// respective overflow
|
|
66158
|
-
const overlap = this.y - tieBoundingBox.y;
|
|
66159
|
-
if (overlap > 0) {
|
|
66160
|
-
this.y -= overlap;
|
|
66161
|
-
}
|
|
66162
|
-
}
|
|
66163
|
-
}
|
|
66164
|
-
}
|
|
66165
|
-
}
|
|
66166
|
-
paint(cx, cy, canvas) {
|
|
66167
|
-
if (this._shouldDraw) {
|
|
66168
|
-
if (this.shouldDrawBendSlur()) {
|
|
66169
|
-
TieGlyph.drawBendSlur(canvas, cx + this._startX, cy + this._startY, cx + this._endX, cy + this._endY, this.tieDirection === BeamDirection.Down, 1, this.renderer.smuflMetrics.tieHeight);
|
|
66170
|
-
}
|
|
66171
|
-
else {
|
|
66172
|
-
TieGlyph.paintTie(canvas, 1, cx + this._startX, cy + this._startY, cx + this._endX, cy + this._endY, this.tieDirection === BeamDirection.Down, this._tieHeight, this.renderer.smuflMetrics.tieMidpointThickness);
|
|
66173
|
-
}
|
|
66174
|
-
}
|
|
66175
|
-
}
|
|
66176
|
-
shouldDrawBendSlur() {
|
|
66177
|
-
return false;
|
|
66178
|
-
}
|
|
66179
|
-
getTieHeight(_startX, _startY, _endX, _endY) {
|
|
66180
|
-
return this.renderer.smuflMetrics.tieHeight;
|
|
66181
|
-
}
|
|
66182
|
-
getBeamDirection(_beat, _noteRenderer) {
|
|
66183
|
-
return BeamDirection.Down;
|
|
66184
|
-
}
|
|
66185
|
-
getStartY() {
|
|
66186
|
-
return 0;
|
|
66187
|
-
}
|
|
66188
|
-
getEndY() {
|
|
66189
|
-
return 0;
|
|
66190
|
-
}
|
|
66191
|
-
getStartX() {
|
|
66192
|
-
return 0;
|
|
66193
|
-
}
|
|
66194
|
-
getEndX() {
|
|
66195
|
-
return 0;
|
|
66196
|
-
}
|
|
66197
|
-
static calculateActualTieHeight(scale, x1, y1, x2, y2, down, offset, size) {
|
|
66198
|
-
const cp = TieGlyph._computeBezierControlPoints(scale, x1, y1, x2, y2, down, offset, size);
|
|
66199
|
-
// For a musical tie/slur, the extrema occur predictably near the midpoint
|
|
66200
|
-
// Evaluate at midpoint (t=0.5) and check endpoints
|
|
66201
|
-
const p0x = cp[0];
|
|
66202
|
-
const p0y = cp[1];
|
|
66203
|
-
const c1x = cp[2];
|
|
66204
|
-
const c1y = cp[3];
|
|
66205
|
-
const c2x = cp[4];
|
|
66206
|
-
const c2y = cp[5];
|
|
66207
|
-
const p1x = cp[6];
|
|
66208
|
-
const p1y = cp[7];
|
|
66209
|
-
// Evaluate at t=0.5 for midpoint
|
|
66210
|
-
const midX = 0.125 * p0x + 0.375 * c1x + 0.375 * c2x + 0.125 * p1x;
|
|
66211
|
-
const midY = 0.125 * p0y + 0.375 * c1y + 0.375 * c2y + 0.125 * p1y;
|
|
66212
|
-
// Bounds are simply min/max of start, end, and midpoint
|
|
66213
|
-
const xMin = Math.min(p0x, p1x, midX);
|
|
66214
|
-
const xMax = Math.max(p0x, p1x, midX);
|
|
66215
|
-
let yMin = Math.min(p0y, p1y, midY);
|
|
66216
|
-
let yMax = Math.max(p0y, p1y, midY);
|
|
66217
|
-
// Account for thickness of the tie/slur
|
|
66218
|
-
if (down) {
|
|
66219
|
-
yMax += size;
|
|
66220
|
-
}
|
|
66221
|
-
else {
|
|
66222
|
-
yMin -= size;
|
|
66223
|
-
}
|
|
66224
|
-
const b = new Bounds();
|
|
66225
|
-
b.x = xMin;
|
|
66226
|
-
b.y = yMin;
|
|
66227
|
-
b.w = xMax - xMin;
|
|
66228
|
-
b.h = yMax - yMin;
|
|
66229
|
-
return b;
|
|
66230
|
-
}
|
|
66231
|
-
static _computeBezierControlPoints(scale, x1, y1, x2, y2, down, offset, size) {
|
|
66232
|
-
if (x1 === x2 && y1 === y2) {
|
|
66233
|
-
return [];
|
|
66234
|
-
}
|
|
66235
|
-
// ensure endX > startX
|
|
66236
|
-
if (x2 < x1) {
|
|
66237
|
-
let t = x1;
|
|
66238
|
-
x1 = x2;
|
|
66239
|
-
x2 = t;
|
|
66240
|
-
t = y1;
|
|
66241
|
-
y1 = y2;
|
|
66242
|
-
y2 = t;
|
|
66243
|
-
}
|
|
66244
|
-
//
|
|
66245
|
-
// calculate control points
|
|
66246
|
-
//
|
|
66247
|
-
offset *= scale;
|
|
66248
|
-
size *= scale;
|
|
66249
|
-
if (down) {
|
|
66250
|
-
offset *= -1;
|
|
66251
|
-
size *= -1;
|
|
66252
|
-
}
|
|
66253
|
-
if (scale >= 1) {
|
|
66254
|
-
size *= 1.2;
|
|
66255
|
-
}
|
|
66256
|
-
// calculate control points on horizontal axis then rotate:
|
|
66257
|
-
/*
|
|
66258
|
-
cp1x/cpy1 cp2x/cpy2
|
|
66259
|
-
*----------------*
|
|
66260
|
-
/ \
|
|
66261
|
-
/ \
|
|
66262
|
-
x1/y1 * * x2/y2
|
|
66263
|
-
|
|
66264
|
-
cp3 and cp4 are simply with lower height
|
|
66265
|
-
*/
|
|
66266
|
-
const dY = y2 - y1;
|
|
66267
|
-
const dX = x2 - x1;
|
|
66268
|
-
const length = Math.sqrt(dX * dX + dY * dY);
|
|
66269
|
-
let cp1x = x1 + length * 0.25;
|
|
66270
|
-
let cp1y = y1 - offset;
|
|
66271
|
-
let cp2x = x1 + length * 0.75;
|
|
66272
|
-
let cp2y = y1 - offset;
|
|
66273
|
-
let cp3x = x1 + length * 0.75;
|
|
66274
|
-
let cp3y = y1 - offset - size;
|
|
66275
|
-
let cp4x = x1 + length * 0.25;
|
|
66276
|
-
let cp4y = y1 - offset - size;
|
|
66277
|
-
const angle = Math.atan2(dY, dX);
|
|
66278
|
-
[cp1x, cp1y] = TieGlyph._rotate(cp1x, cp1y, x1, y1, angle);
|
|
66279
|
-
[cp2x, cp2y] = TieGlyph._rotate(cp2x, cp2y, x1, y1, angle);
|
|
66280
|
-
[cp3x, cp3y] = TieGlyph._rotate(cp3x, cp3y, x1, y1, angle);
|
|
66281
|
-
[cp4x, cp4y] = TieGlyph._rotate(cp4x, cp4y, x1, y1, angle);
|
|
66282
|
-
return [x1, y1, cp1x, cp1y, cp2x, cp2y, x2, y2, cp3x, cp3y, cp4x, cp4y, x1, y1];
|
|
66283
|
-
}
|
|
66284
|
-
static _rotate(x, y, rotateX, rotateY, angle) {
|
|
66285
|
-
const dx = x - rotateX;
|
|
66286
|
-
const dy = y - rotateY;
|
|
66287
|
-
const rx = dx * Math.cos(angle) - dy * Math.sin(angle);
|
|
66288
|
-
const ry = dx * Math.sin(angle) + dy * Math.cos(angle);
|
|
66289
|
-
return [rotateX + rx, rotateY + ry];
|
|
66290
|
-
}
|
|
66291
|
-
static paintTie(canvas, scale, x1, y1, x2, y2, down /*= false*/, offset /*= 22*/, size /*= 4*/) {
|
|
66292
|
-
const cps = TieGlyph._computeBezierControlPoints(scale, x1, y1, x2, y2, down, offset, size);
|
|
66293
|
-
canvas.beginPath();
|
|
66294
|
-
canvas.moveTo(cps[0], cps[1]);
|
|
66295
|
-
canvas.bezierCurveTo(cps[2], cps[3], cps[4], cps[5], cps[6], cps[7]);
|
|
66296
|
-
canvas.bezierCurveTo(cps[8], cps[9], cps[10], cps[11], cps[12], cps[13]);
|
|
66297
|
-
canvas.closePath();
|
|
66298
|
-
canvas.fill();
|
|
66299
|
-
}
|
|
66300
|
-
static calculateBendSlurTopY(x1, y1, x2, y2, down, scale, bendSlurHeight) {
|
|
66301
|
-
let normalVectorX = y2 - y1;
|
|
66302
|
-
let normalVectorY = x2 - x1;
|
|
66303
|
-
const length = Math.sqrt(normalVectorX * normalVectorX + normalVectorY * normalVectorY);
|
|
66304
|
-
if (down) {
|
|
66305
|
-
normalVectorX *= -1;
|
|
66306
|
-
}
|
|
66307
|
-
else {
|
|
66308
|
-
normalVectorY *= -1;
|
|
66309
|
-
}
|
|
66310
|
-
// make to unit vector
|
|
66311
|
-
normalVectorX /= length;
|
|
66312
|
-
normalVectorY /= length;
|
|
66313
|
-
let offset = bendSlurHeight * scale;
|
|
66314
|
-
if (x2 - x1 < 20) {
|
|
66315
|
-
offset /= 2;
|
|
66316
|
-
}
|
|
66317
|
-
const centerY = (y2 + y1) / 2;
|
|
66318
|
-
const cp1Y = centerY + offset * normalVectorY;
|
|
66319
|
-
return cp1Y;
|
|
66320
|
-
}
|
|
66321
|
-
static drawBendSlur(canvas, x1, y1, x2, y2, down, scale, bendSlurHeight, slurText) {
|
|
66322
|
-
let normalVectorX = y2 - y1;
|
|
66323
|
-
let normalVectorY = x2 - x1;
|
|
66324
|
-
const length = Math.sqrt(normalVectorX * normalVectorX + normalVectorY * normalVectorY);
|
|
66325
|
-
if (down) {
|
|
66326
|
-
normalVectorX *= -1;
|
|
66327
|
-
}
|
|
66328
|
-
else {
|
|
66329
|
-
normalVectorY *= -1;
|
|
66330
|
-
}
|
|
66331
|
-
// make to unit vector
|
|
66332
|
-
normalVectorX /= length;
|
|
66333
|
-
normalVectorY /= length;
|
|
66334
|
-
// center of connection
|
|
66335
|
-
// TODO: should be 1/3
|
|
66336
|
-
const centerX = (x2 + x1) / 2;
|
|
66337
|
-
const centerY = (y2 + y1) / 2;
|
|
66338
|
-
let offset = bendSlurHeight * scale;
|
|
66339
|
-
if (x2 - x1 < 20) {
|
|
66340
|
-
offset /= 2;
|
|
66341
|
-
}
|
|
66342
|
-
const cp1X = centerX + offset * normalVectorX;
|
|
66343
|
-
const cp1Y = centerY + offset * normalVectorY;
|
|
66344
|
-
canvas.beginPath();
|
|
66345
|
-
canvas.moveTo(x1, y1);
|
|
66346
|
-
canvas.lineTo(cp1X, cp1Y);
|
|
66347
|
-
canvas.lineTo(x2, y2);
|
|
66348
|
-
canvas.stroke();
|
|
66349
|
-
if (slurText) {
|
|
66350
|
-
const w = canvas.measureText(slurText).width;
|
|
66351
|
-
const textOffset = down ? 0 : -canvas.font.size;
|
|
66352
|
-
canvas.fillText(slurText, cp1X - w / 2, cp1Y + textOffset);
|
|
66353
|
-
}
|
|
66354
|
-
}
|
|
66355
|
-
}
|
|
66356
|
-
|
|
66357
|
-
/**
|
|
66358
|
-
* @internal
|
|
66359
|
-
*/
|
|
66360
|
-
class NumberedTieGlyph extends TieGlyph {
|
|
66361
|
-
startNote;
|
|
66362
|
-
endNote;
|
|
66363
|
-
constructor(startNote, endNote, forEnd = false) {
|
|
66364
|
-
super(!startNote ? null : startNote.beat, !endNote ? null : endNote.beat, forEnd);
|
|
66365
|
-
this.startNote = startNote;
|
|
66366
|
-
this.endNote = endNote;
|
|
66367
|
-
}
|
|
66368
|
-
get _isLeftHandTap() {
|
|
66369
|
-
return this.startNote === this.endNote;
|
|
66370
|
-
}
|
|
66594
|
+
class NumberedTieGlyph extends NoteTieGlyph {
|
|
66371
66595
|
shouldDrawBendSlur() {
|
|
66372
66596
|
return (this.renderer.settings.notation.extendBendArrowsOnTiedNotes &&
|
|
66373
66597
|
!!this.startNote.bendOrigin &&
|
|
66374
66598
|
this.startNote.isTieOrigin);
|
|
66375
66599
|
}
|
|
66376
|
-
|
|
66377
|
-
super.doLayout();
|
|
66378
|
-
}
|
|
66379
|
-
getBeamDirection(_beat, _noteRenderer) {
|
|
66600
|
+
calculateTieDirection() {
|
|
66380
66601
|
return BeamDirection.Up;
|
|
66381
66602
|
}
|
|
66382
|
-
getStartY() {
|
|
66383
|
-
return this.startNoteRenderer.getNoteY(this.startNote, NoteYPosition.Top);
|
|
66384
|
-
}
|
|
66385
|
-
getEndY() {
|
|
66386
|
-
return this.getStartY();
|
|
66387
|
-
}
|
|
66388
|
-
getStartX() {
|
|
66389
|
-
if (this._isLeftHandTap) {
|
|
66390
|
-
return this.getEndX() - this.startNoteRenderer.smuflMetrics.leftHandTabTieWidth;
|
|
66391
|
-
}
|
|
66392
|
-
return this.startNoteRenderer.getNoteX(this.startNote, NoteXPosition.Center);
|
|
66393
|
-
}
|
|
66394
|
-
getEndX() {
|
|
66395
|
-
if (this._isLeftHandTap) {
|
|
66396
|
-
return this.endNoteRenderer.getNoteX(this.endNote, NoteXPosition.Left);
|
|
66397
|
-
}
|
|
66398
|
-
return this.endNoteRenderer.getNoteX(this.endNote, NoteXPosition.Center);
|
|
66399
|
-
}
|
|
66400
66603
|
}
|
|
66401
66604
|
|
|
66402
66605
|
/**
|
|
66403
66606
|
* @internal
|
|
66404
66607
|
*/
|
|
66405
|
-
class TabTieGlyph extends
|
|
66406
|
-
|
|
66407
|
-
|
|
66408
|
-
constructor(startNote, endNote, forEnd = false) {
|
|
66409
|
-
super(startNote.beat, endNote.beat, forEnd);
|
|
66410
|
-
this.startNote = startNote;
|
|
66411
|
-
this.endNote = endNote;
|
|
66412
|
-
}
|
|
66413
|
-
get _isLeftHandTap() {
|
|
66414
|
-
return this.startNote === this.endNote;
|
|
66415
|
-
}
|
|
66416
|
-
getTieHeight(startX, startY, endX, endY) {
|
|
66417
|
-
if (this._isLeftHandTap) {
|
|
66418
|
-
return this.startNoteRenderer.smuflMetrics.tieHeight;
|
|
66419
|
-
}
|
|
66420
|
-
return super.getTieHeight(startX, startY, endX, endY);
|
|
66421
|
-
}
|
|
66422
|
-
getBeamDirection(_beat, _noteRenderer) {
|
|
66423
|
-
if (this._isLeftHandTap) {
|
|
66608
|
+
class TabTieGlyph extends NoteTieGlyph {
|
|
66609
|
+
calculateTieDirection() {
|
|
66610
|
+
if (this.isLeftHandTap) {
|
|
66424
66611
|
return BeamDirection.Up;
|
|
66425
66612
|
}
|
|
66426
66613
|
return TabTieGlyph.getBeamDirectionForNote(this.startNote);
|
|
@@ -66428,54 +66615,25 @@
|
|
|
66428
66615
|
static getBeamDirectionForNote(note) {
|
|
66429
66616
|
return note.string > 3 ? BeamDirection.Up : BeamDirection.Down;
|
|
66430
66617
|
}
|
|
66431
|
-
getStartY() {
|
|
66432
|
-
if (this._isLeftHandTap) {
|
|
66433
|
-
return this.startNoteRenderer.getNoteY(this.startNote, NoteYPosition.Center);
|
|
66434
|
-
}
|
|
66435
|
-
if (this.tieDirection === BeamDirection.Up) {
|
|
66436
|
-
return this.startNoteRenderer.getNoteY(this.startNote, NoteYPosition.Top);
|
|
66437
|
-
}
|
|
66438
|
-
return this.startNoteRenderer.getNoteY(this.startNote, NoteYPosition.Bottom);
|
|
66439
|
-
}
|
|
66440
|
-
getEndY() {
|
|
66441
|
-
return this.getStartY();
|
|
66442
|
-
}
|
|
66443
|
-
getStartX() {
|
|
66444
|
-
if (this._isLeftHandTap) {
|
|
66445
|
-
return this.getEndX() - this.renderer.smuflMetrics.leftHandTabTieWidth;
|
|
66446
|
-
}
|
|
66447
|
-
return this.startNoteRenderer.getNoteX(this.startNote, NoteXPosition.Center);
|
|
66448
|
-
}
|
|
66449
|
-
getEndX() {
|
|
66450
|
-
if (this._isLeftHandTap) {
|
|
66451
|
-
return this.endNoteRenderer.getNoteX(this.endNote, NoteXPosition.Left);
|
|
66452
|
-
}
|
|
66453
|
-
return this.endNoteRenderer.getNoteX(this.endNote, NoteXPosition.Center);
|
|
66454
|
-
}
|
|
66455
66618
|
}
|
|
66456
66619
|
|
|
66457
66620
|
/**
|
|
66458
66621
|
* @internal
|
|
66459
66622
|
*/
|
|
66460
|
-
class
|
|
66461
|
-
_direction;
|
|
66623
|
+
class TabSlurGlyph extends TabTieGlyph {
|
|
66462
66624
|
_forSlide;
|
|
66463
|
-
constructor(startNote, endNote, forSlide, forEnd
|
|
66464
|
-
super(startNote, endNote, forEnd);
|
|
66465
|
-
this._direction = BeamDirection.Up;
|
|
66625
|
+
constructor(slurEffectId, startNote, endNote, forSlide, forEnd) {
|
|
66626
|
+
super(slurEffectId, startNote, endNote, forEnd);
|
|
66466
66627
|
this._forSlide = forSlide;
|
|
66467
66628
|
}
|
|
66468
66629
|
getTieHeight(startX, _startY, endX, _endY) {
|
|
66469
|
-
return Math.log(endX - startX + 1) * this.renderer.settings.notation.slurHeight / 2;
|
|
66630
|
+
return (Math.log(endX - startX + 1) * this.renderer.settings.notation.slurHeight) / 2;
|
|
66470
66631
|
}
|
|
66471
66632
|
tryExpand(startNote, endNote, forSlide, forEnd) {
|
|
66472
66633
|
// same type required
|
|
66473
66634
|
if (this._forSlide !== forSlide) {
|
|
66474
66635
|
return false;
|
|
66475
66636
|
}
|
|
66476
|
-
if (this.forEnd !== forEnd) {
|
|
66477
|
-
return false;
|
|
66478
|
-
}
|
|
66479
66637
|
// same start and endbeat
|
|
66480
66638
|
if (this.startNote.beat.id !== startNote.beat.id) {
|
|
66481
66639
|
return false;
|
|
@@ -66483,41 +66641,43 @@
|
|
|
66483
66641
|
if (this.endNote.beat.id !== endNote.beat.id) {
|
|
66484
66642
|
return false;
|
|
66485
66643
|
}
|
|
66644
|
+
const isForEnd = this.renderer === this.lookupEndBeatRenderer();
|
|
66645
|
+
if (isForEnd !== forEnd) {
|
|
66646
|
+
return false;
|
|
66647
|
+
}
|
|
66648
|
+
// same draw direction
|
|
66649
|
+
if (this.tieDirection !== TabTieGlyph.getBeamDirectionForNote(startNote)) {
|
|
66650
|
+
return false;
|
|
66651
|
+
}
|
|
66486
66652
|
// if we can expand, expand in correct direction
|
|
66487
|
-
switch (this.
|
|
66653
|
+
switch (this.tieDirection) {
|
|
66488
66654
|
case BeamDirection.Up:
|
|
66489
66655
|
if (startNote.realValue > this.startNote.realValue) {
|
|
66490
66656
|
this.startNote = startNote;
|
|
66491
|
-
this.startBeat = startNote.beat;
|
|
66492
66657
|
}
|
|
66493
66658
|
if (endNote.realValue > this.endNote.realValue) {
|
|
66494
66659
|
this.endNote = endNote;
|
|
66495
|
-
this.endBeat = endNote.beat;
|
|
66496
66660
|
}
|
|
66497
66661
|
break;
|
|
66498
66662
|
case BeamDirection.Down:
|
|
66499
66663
|
if (startNote.realValue < this.startNote.realValue) {
|
|
66500
66664
|
this.startNote = startNote;
|
|
66501
|
-
this.startBeat = startNote.beat;
|
|
66502
66665
|
}
|
|
66503
66666
|
if (endNote.realValue < this.endNote.realValue) {
|
|
66504
66667
|
this.endNote = endNote;
|
|
66505
|
-
this.endBeat = endNote.beat;
|
|
66506
66668
|
}
|
|
66507
66669
|
break;
|
|
66508
66670
|
}
|
|
66509
66671
|
return true;
|
|
66510
66672
|
}
|
|
66511
|
-
|
|
66512
|
-
|
|
66513
|
-
|
|
66514
|
-
|
|
66515
|
-
|
|
66516
|
-
|
|
66517
|
-
|
|
66518
|
-
|
|
66519
|
-
super.paint(cx, cy, canvas);
|
|
66520
|
-
}
|
|
66673
|
+
}
|
|
66674
|
+
|
|
66675
|
+
/**
|
|
66676
|
+
* @internal
|
|
66677
|
+
*/
|
|
66678
|
+
class NumberedSlurGlyph extends TabSlurGlyph {
|
|
66679
|
+
calculateTieDirection() {
|
|
66680
|
+
return BeamDirection.Up;
|
|
66521
66681
|
}
|
|
66522
66682
|
}
|
|
66523
66683
|
|
|
@@ -66525,23 +66685,31 @@
|
|
|
66525
66685
|
* @internal
|
|
66526
66686
|
*/
|
|
66527
66687
|
class NumberedBeatContainerGlyph extends BeatContainerGlyph {
|
|
66688
|
+
_slurs = new Map();
|
|
66528
66689
|
_effectSlurs = [];
|
|
66690
|
+
doLayout() {
|
|
66691
|
+
this._slurs.clear();
|
|
66692
|
+
this._effectSlurs = [];
|
|
66693
|
+
super.doLayout();
|
|
66694
|
+
}
|
|
66529
66695
|
createTies(n) {
|
|
66530
66696
|
// create a tie if any effect requires it
|
|
66531
66697
|
if (!n.isVisible) {
|
|
66532
66698
|
return;
|
|
66533
66699
|
}
|
|
66534
|
-
if (n.isTieOrigin && n.tieDestination.isVisible) {
|
|
66535
|
-
const tie = new NumberedTieGlyph(n, n.tieDestination, false);
|
|
66700
|
+
if (n.isTieOrigin && n.tieDestination.isVisible && !this._slurs.has('numbered.tie')) {
|
|
66701
|
+
const tie = new NumberedTieGlyph(`numbered.tie.${n.beat.id}`, n, n.tieDestination, false);
|
|
66536
66702
|
this.addTie(tie);
|
|
66703
|
+
this._slurs.set(tie.slurEffectId, tie);
|
|
66537
66704
|
}
|
|
66538
66705
|
if (n.isTieDestination) {
|
|
66539
|
-
const tie = new NumberedTieGlyph(n.tieOrigin, n, true);
|
|
66706
|
+
const tie = new NumberedTieGlyph(`numbered.tie.${n.tieOrigin.beat.id}`, n.tieOrigin, n, true);
|
|
66540
66707
|
this.addTie(tie);
|
|
66541
66708
|
}
|
|
66542
|
-
if (n.isLeftHandTapped && !n.isHammerPullDestination) {
|
|
66543
|
-
const tapSlur = new NumberedTieGlyph(n, n, false);
|
|
66709
|
+
if (n.isLeftHandTapped && !n.isHammerPullDestination && !this._slurs.has(`numbered.tie.leftHandTap.${n.beat.id}`)) {
|
|
66710
|
+
const tapSlur = new NumberedTieGlyph(`numbered.tie.leftHandTap.${n.beat.id}`, n, n, false);
|
|
66544
66711
|
this.addTie(tapSlur);
|
|
66712
|
+
this._slurs.set(tapSlur.slurEffectId, tapSlur);
|
|
66545
66713
|
}
|
|
66546
66714
|
// start effect slur on first beat
|
|
66547
66715
|
if (n.isEffectSlurOrigin && n.effectSlurDestination) {
|
|
@@ -66553,9 +66721,11 @@
|
|
|
66553
66721
|
}
|
|
66554
66722
|
}
|
|
66555
66723
|
if (!expanded) {
|
|
66556
|
-
const effectSlur = new NumberedSlurGlyph(n, n.effectSlurDestination, false, false);
|
|
66724
|
+
const effectSlur = new NumberedSlurGlyph(`numbered.slur.effect`, n, n.effectSlurDestination, false, false);
|
|
66557
66725
|
this._effectSlurs.push(effectSlur);
|
|
66558
66726
|
this.addTie(effectSlur);
|
|
66727
|
+
this._slurs.set(effectSlur.slurEffectId, effectSlur);
|
|
66728
|
+
this._slurs.set('numbered.slur.effect', effectSlur);
|
|
66559
66729
|
}
|
|
66560
66730
|
}
|
|
66561
66731
|
// end effect slur on last beat
|
|
@@ -66568,9 +66738,11 @@
|
|
|
66568
66738
|
}
|
|
66569
66739
|
}
|
|
66570
66740
|
if (!expanded) {
|
|
66571
|
-
const effectSlur = new NumberedSlurGlyph(n.effectSlurOrigin, n, false, true);
|
|
66741
|
+
const effectSlur = new NumberedSlurGlyph(`numbered.slur.effect`, n.effectSlurOrigin, n, false, true);
|
|
66572
66742
|
this._effectSlurs.push(effectSlur);
|
|
66573
66743
|
this.addTie(effectSlur);
|
|
66744
|
+
this._slurs.set(effectSlur.slurEffectId, effectSlur);
|
|
66745
|
+
this._slurs.set('numbered.slur.effect', effectSlur);
|
|
66574
66746
|
}
|
|
66575
66747
|
}
|
|
66576
66748
|
}
|
|
@@ -66963,10 +67135,11 @@
|
|
|
66963
67135
|
if (sr.shortestDuration < this.container.beat.duration) {
|
|
66964
67136
|
sr.shortestDuration = this.container.beat.duration;
|
|
66965
67137
|
}
|
|
66966
|
-
const glyphY = sr.getLineY(sr.getNoteLine());
|
|
66967
67138
|
if (!this.container.beat.isEmpty) {
|
|
67139
|
+
const glyphY = sr.getLineY(0);
|
|
66968
67140
|
let numberWithinOctave = '0';
|
|
66969
67141
|
if (this.container.beat.notes.length > 0) {
|
|
67142
|
+
const note = this.container.beat.notes[0];
|
|
66970
67143
|
const kst = this.renderer.bar.keySignatureType;
|
|
66971
67144
|
const ks = this.renderer.bar.keySignature;
|
|
66972
67145
|
const ksi = ks + 7;
|
|
@@ -66974,7 +67147,6 @@
|
|
|
66974
67147
|
? NumberedBeatGlyph.minorKeySignatureOneValues
|
|
66975
67148
|
: NumberedBeatGlyph.majorKeySignatureOneValues;
|
|
66976
67149
|
const oneNoteValue = oneNoteValues[ksi];
|
|
66977
|
-
const note = this.container.beat.notes[0];
|
|
66978
67150
|
if (note.isDead) {
|
|
66979
67151
|
numberWithinOctave = 'X';
|
|
66980
67152
|
}
|
|
@@ -67021,7 +67193,7 @@
|
|
|
67021
67193
|
// Note dots
|
|
67022
67194
|
if (this.container.beat.dots > 0 && this.container.beat.duration >= Duration.Quarter) {
|
|
67023
67195
|
for (let i = 0; i < this.container.beat.dots; i++) {
|
|
67024
|
-
const dot = new AugmentationDotGlyph(0,
|
|
67196
|
+
const dot = new AugmentationDotGlyph(0, glyphY);
|
|
67025
67197
|
dot.renderer = this.renderer;
|
|
67026
67198
|
this.addEffect(dot);
|
|
67027
67199
|
}
|
|
@@ -67049,21 +67221,22 @@
|
|
|
67049
67221
|
numberOfQuarterNotes += numberOfAddedQuarters;
|
|
67050
67222
|
}
|
|
67051
67223
|
for (let i = 0; i < numberOfQuarterNotes - 1; i++) {
|
|
67052
|
-
const dash = new NumberedDashGlyph(0,
|
|
67224
|
+
const dash = new NumberedDashGlyph(0, glyphY, this.container.beat);
|
|
67053
67225
|
dash.renderer = this.renderer;
|
|
67054
67226
|
this.addNormal(dash);
|
|
67055
67227
|
}
|
|
67056
67228
|
}
|
|
67057
67229
|
super.doLayout();
|
|
67058
67230
|
if (this.container.beat.isEmpty) {
|
|
67059
|
-
this.
|
|
67231
|
+
this.onTimeX = this.width / 2;
|
|
67060
67232
|
}
|
|
67061
67233
|
else if (this.noteHeads) {
|
|
67062
|
-
this.
|
|
67234
|
+
this.onTimeX = this.noteHeads.x + this.noteHeads.width / 2;
|
|
67063
67235
|
}
|
|
67064
67236
|
else if (this.deadSlapped) {
|
|
67065
|
-
this.
|
|
67237
|
+
this.onTimeX = this.deadSlapped.x + this.deadSlapped.width / 2;
|
|
67066
67238
|
}
|
|
67239
|
+
this.middleX = this.onTimeX;
|
|
67067
67240
|
}
|
|
67068
67241
|
}
|
|
67069
67242
|
|
|
@@ -67519,7 +67692,7 @@
|
|
|
67519
67692
|
}
|
|
67520
67693
|
}
|
|
67521
67694
|
}
|
|
67522
|
-
getNoteLine() {
|
|
67695
|
+
getNoteLine(_note) {
|
|
67523
67696
|
return 0;
|
|
67524
67697
|
}
|
|
67525
67698
|
get tupletOffset() {
|
|
@@ -67929,6 +68102,7 @@
|
|
|
67929
68102
|
upLineX = 0;
|
|
67930
68103
|
downLineX = 0;
|
|
67931
68104
|
noteStartX = 0;
|
|
68105
|
+
onTimeX = 0;
|
|
67932
68106
|
constructor() {
|
|
67933
68107
|
super(0, 0);
|
|
67934
68108
|
}
|
|
@@ -68015,6 +68189,8 @@
|
|
|
68015
68189
|
// align all notes so that they align with the stem positions
|
|
68016
68190
|
const stemPosition = anyDisplaced || direction === BeamDirection.Up ? stemUpX : stemDownX;
|
|
68017
68191
|
let w = 0;
|
|
68192
|
+
let displacedWidth = 0;
|
|
68193
|
+
let nonDisplacedWidth = 0;
|
|
68018
68194
|
for (let i = 0, j = this._infos.length; i < j; i++) {
|
|
68019
68195
|
const g = this._infos[i].glyph;
|
|
68020
68196
|
const alignDisplaced = displaced.get(i);
|
|
@@ -68030,7 +68206,14 @@
|
|
|
68030
68206
|
}
|
|
68031
68207
|
}
|
|
68032
68208
|
g.x += this.noteStartX;
|
|
68033
|
-
|
|
68209
|
+
const gw = g.x + g.width;
|
|
68210
|
+
w = Math.max(w, gw);
|
|
68211
|
+
if (alignDisplaced) {
|
|
68212
|
+
displacedWidth = Math.max(displacedWidth, gw);
|
|
68213
|
+
}
|
|
68214
|
+
else {
|
|
68215
|
+
nonDisplacedWidth = Math.max(nonDisplacedWidth, gw);
|
|
68216
|
+
}
|
|
68034
68217
|
// after size calculation, re-align glyph to stem if needed
|
|
68035
68218
|
if (g instanceof NoteHeadGlyph && g.centerOnStem) {
|
|
68036
68219
|
g.x = stemPosition;
|
|
@@ -68044,6 +68227,23 @@
|
|
|
68044
68227
|
this.upLineX = stemUpX;
|
|
68045
68228
|
this.downLineX = stemDownX;
|
|
68046
68229
|
}
|
|
68230
|
+
// the center of score notes, (used for aligning the beat to the right on-time position)
|
|
68231
|
+
// is always the center of the "correct note" position.
|
|
68232
|
+
// * If the stem is upwards, the center is the middle of the left hand side note head
|
|
68233
|
+
// * If the stem is downards, the center is the middle of the right-hand-side note head
|
|
68234
|
+
if (anyDisplaced) {
|
|
68235
|
+
if (direction === BeamDirection.Up) {
|
|
68236
|
+
this.onTimeX = nonDisplacedWidth / 2;
|
|
68237
|
+
}
|
|
68238
|
+
else {
|
|
68239
|
+
const displacedRawWith = displacedWidth - stemPosition;
|
|
68240
|
+
this.onTimeX = stemPosition + (displacedRawWith / 2);
|
|
68241
|
+
}
|
|
68242
|
+
}
|
|
68243
|
+
else {
|
|
68244
|
+
// for no displaced notes it is simply the center
|
|
68245
|
+
this.onTimeX = w / 2;
|
|
68246
|
+
}
|
|
68047
68247
|
this.width = w;
|
|
68048
68248
|
}
|
|
68049
68249
|
paint(cx, cy, canvas) {
|
|
@@ -68220,6 +68420,7 @@
|
|
|
68220
68420
|
this._deadSlapped.renderer = this.renderer;
|
|
68221
68421
|
this._deadSlapped.doLayout();
|
|
68222
68422
|
this.width = this._deadSlapped.width;
|
|
68423
|
+
this.onTimeX = this.width / 2;
|
|
68223
68424
|
}
|
|
68224
68425
|
let aboveBeatEffectsY = 0;
|
|
68225
68426
|
let belowBeatEffectsY = 0;
|
|
@@ -69118,13 +69319,16 @@
|
|
|
69118
69319
|
}
|
|
69119
69320
|
super.doLayout();
|
|
69120
69321
|
if (this.container.beat.isEmpty) {
|
|
69121
|
-
this.
|
|
69322
|
+
this.onTimeX = this.width / 2;
|
|
69323
|
+
this.middleX = this.onTimeX;
|
|
69122
69324
|
}
|
|
69123
69325
|
else if (this.restGlyph) {
|
|
69124
|
-
this.
|
|
69326
|
+
this.onTimeX = this.restGlyph.x + this.restGlyph.width / 2;
|
|
69327
|
+
this.middleX = this.onTimeX;
|
|
69125
69328
|
}
|
|
69126
69329
|
else if (this.noteHeads) {
|
|
69127
|
-
this.
|
|
69330
|
+
this.onTimeX = this.noteHeads.x + this.noteHeads.onTimeX;
|
|
69331
|
+
this.middleX = this.noteHeads.x + this.noteHeads.width / 2;
|
|
69128
69332
|
}
|
|
69129
69333
|
}
|
|
69130
69334
|
_createBeatDot(line, group) {
|
|
@@ -69734,87 +69938,128 @@
|
|
|
69734
69938
|
* @internal
|
|
69735
69939
|
*/
|
|
69736
69940
|
class ScoreLegatoGlyph extends TieGlyph {
|
|
69737
|
-
|
|
69738
|
-
|
|
69941
|
+
startBeat;
|
|
69942
|
+
endBeat;
|
|
69943
|
+
startBeatRenderer = null;
|
|
69944
|
+
endBeatRenderer = null;
|
|
69945
|
+
constructor(slurEffectId, startBeat, endBeat, forEnd) {
|
|
69946
|
+
super(slurEffectId, forEnd);
|
|
69947
|
+
this.startBeat = startBeat;
|
|
69948
|
+
this.endBeat = endBeat;
|
|
69739
69949
|
}
|
|
69740
69950
|
doLayout() {
|
|
69741
69951
|
super.doLayout();
|
|
69742
69952
|
}
|
|
69743
|
-
|
|
69744
|
-
if (
|
|
69953
|
+
lookupStartBeatRenderer() {
|
|
69954
|
+
if (!this.startBeatRenderer) {
|
|
69955
|
+
this.startBeatRenderer = this.renderer.scoreRenderer.layout.getRendererForBar(this.renderer.staff.staffId, this.startBeat.voice.bar);
|
|
69956
|
+
}
|
|
69957
|
+
return this.startBeatRenderer;
|
|
69958
|
+
}
|
|
69959
|
+
lookupEndBeatRenderer() {
|
|
69960
|
+
if (!this.endBeatRenderer) {
|
|
69961
|
+
this.endBeatRenderer = this.renderer.scoreRenderer.layout.getRendererForBar(this.renderer.staff.staffId, this.endBeat.voice.bar);
|
|
69962
|
+
}
|
|
69963
|
+
return this.endBeatRenderer;
|
|
69964
|
+
}
|
|
69965
|
+
shouldDrawBendSlur() {
|
|
69966
|
+
return false;
|
|
69967
|
+
}
|
|
69968
|
+
calculateTieDirection() {
|
|
69969
|
+
if (this.startBeat.isRest) {
|
|
69745
69970
|
return BeamDirection.Up;
|
|
69746
69971
|
}
|
|
69747
69972
|
// invert direction (if stems go up, ties go down to not cross them)
|
|
69748
|
-
switch (
|
|
69973
|
+
switch (this.lookupStartBeatRenderer().getBeatDirection(this.startBeat)) {
|
|
69749
69974
|
case BeamDirection.Up:
|
|
69750
69975
|
return BeamDirection.Down;
|
|
69751
69976
|
default:
|
|
69752
69977
|
return BeamDirection.Up;
|
|
69753
69978
|
}
|
|
69754
69979
|
}
|
|
69755
|
-
|
|
69980
|
+
calculateStartX() {
|
|
69981
|
+
const startBeatRenderer = this.lookupStartBeatRenderer();
|
|
69982
|
+
return startBeatRenderer.x + startBeatRenderer.getBeatX(this.startBeat, BeatXPosition.MiddleNotes);
|
|
69983
|
+
}
|
|
69984
|
+
calculateStartY() {
|
|
69985
|
+
const startBeatRenderer = this.lookupStartBeatRenderer();
|
|
69756
69986
|
if (this.startBeat.isRest) {
|
|
69757
|
-
|
|
69758
|
-
|
|
69987
|
+
switch (this.tieDirection) {
|
|
69988
|
+
case BeamDirection.Up:
|
|
69989
|
+
return (startBeatRenderer.y +
|
|
69990
|
+
startBeatRenderer.getBeatContainer(this.startBeat).onNotes.getBoundingBoxTop());
|
|
69991
|
+
default:
|
|
69992
|
+
return (startBeatRenderer.y +
|
|
69993
|
+
startBeatRenderer.getBeatContainer(this.startBeat).onNotes.getBoundingBoxBottom());
|
|
69994
|
+
}
|
|
69759
69995
|
}
|
|
69760
69996
|
switch (this.tieDirection) {
|
|
69761
69997
|
case BeamDirection.Up:
|
|
69762
69998
|
// below lowest note
|
|
69763
|
-
return
|
|
69999
|
+
return startBeatRenderer.y + startBeatRenderer.getNoteY(this.startBeat.maxNote, NoteYPosition.Top);
|
|
69764
70000
|
default:
|
|
69765
|
-
return
|
|
70001
|
+
return startBeatRenderer.y + startBeatRenderer.getNoteY(this.startBeat.minNote, NoteYPosition.Bottom);
|
|
70002
|
+
}
|
|
70003
|
+
}
|
|
70004
|
+
calculateEndX() {
|
|
70005
|
+
const endBeatRenderer = this.lookupEndBeatRenderer();
|
|
70006
|
+
if (!endBeatRenderer) {
|
|
70007
|
+
return this.calculateStartX() + this.renderer.smuflMetrics.leftHandTabTieWidth;
|
|
69766
70008
|
}
|
|
70009
|
+
const endBeamDirection = endBeatRenderer.getBeatDirection(this.endBeat);
|
|
70010
|
+
return (endBeatRenderer.x +
|
|
70011
|
+
endBeatRenderer.getBeatX(this.endBeat, this.endBeat.duration > Duration.Whole && endBeamDirection === this.tieDirection
|
|
70012
|
+
? BeatXPosition.Stem
|
|
70013
|
+
: BeatXPosition.MiddleNotes));
|
|
69767
70014
|
}
|
|
69768
|
-
|
|
69769
|
-
const
|
|
70015
|
+
caclculateEndY() {
|
|
70016
|
+
const endBeatRenderer = this.lookupEndBeatRenderer();
|
|
70017
|
+
if (!endBeatRenderer) {
|
|
70018
|
+
return this.calculateStartY();
|
|
70019
|
+
}
|
|
69770
70020
|
if (this.endBeat.isRest) {
|
|
69771
70021
|
switch (this.tieDirection) {
|
|
69772
70022
|
case BeamDirection.Up:
|
|
69773
|
-
return
|
|
70023
|
+
return (endBeatRenderer.y + endBeatRenderer.getBeatContainer(this.endBeat).onNotes.getBoundingBoxTop());
|
|
69774
70024
|
default:
|
|
69775
|
-
return
|
|
70025
|
+
return (endBeatRenderer.y +
|
|
70026
|
+
endBeatRenderer.getBeatContainer(this.endBeat).onNotes.getBoundingBoxBottom());
|
|
69776
70027
|
}
|
|
69777
70028
|
}
|
|
69778
|
-
const startBeamDirection = this.
|
|
69779
|
-
const endBeamDirection =
|
|
70029
|
+
const startBeamDirection = this.lookupStartBeatRenderer().getBeatDirection(this.startBeat);
|
|
70030
|
+
const endBeamDirection = endBeatRenderer.getBeatDirection(this.endBeat);
|
|
69780
70031
|
if (startBeamDirection !== endBeamDirection && this.startBeat.graceType === GraceType.None) {
|
|
69781
70032
|
if (endBeamDirection === this.tieDirection) {
|
|
69782
70033
|
switch (this.tieDirection) {
|
|
69783
70034
|
case BeamDirection.Up:
|
|
69784
70035
|
// stem upper end
|
|
69785
|
-
return
|
|
70036
|
+
return (endBeatRenderer.y +
|
|
70037
|
+
endBeatRenderer.getNoteY(this.endBeat.maxNote, NoteYPosition.TopWithStem));
|
|
69786
70038
|
default:
|
|
69787
70039
|
// stem lower end
|
|
69788
|
-
return
|
|
70040
|
+
return (endBeatRenderer.y +
|
|
70041
|
+
endBeatRenderer.getNoteY(this.endBeat.minNote, NoteYPosition.BottomWithStem));
|
|
69789
70042
|
}
|
|
69790
70043
|
}
|
|
69791
70044
|
switch (this.tieDirection) {
|
|
69792
70045
|
case BeamDirection.Up:
|
|
69793
70046
|
// stem upper end
|
|
69794
|
-
return
|
|
70047
|
+
return (endBeatRenderer.y +
|
|
70048
|
+
endBeatRenderer.getNoteY(this.endBeat.maxNote, NoteYPosition.BottomWithStem));
|
|
69795
70049
|
default:
|
|
69796
70050
|
// stem lower end
|
|
69797
|
-
return
|
|
70051
|
+
return (endBeatRenderer.y + endBeatRenderer.getNoteY(this.endBeat.minNote, NoteYPosition.TopWithStem));
|
|
69798
70052
|
}
|
|
69799
70053
|
}
|
|
69800
70054
|
switch (this.tieDirection) {
|
|
69801
70055
|
case BeamDirection.Up:
|
|
69802
70056
|
// below lowest note
|
|
69803
|
-
return
|
|
70057
|
+
return endBeatRenderer.y + endBeatRenderer.getNoteY(this.endBeat.maxNote, NoteYPosition.Top);
|
|
69804
70058
|
default:
|
|
69805
70059
|
// above highest note
|
|
69806
|
-
return
|
|
70060
|
+
return endBeatRenderer.y + endBeatRenderer.getNoteY(this.endBeat.minNote, NoteYPosition.Bottom);
|
|
69807
70061
|
}
|
|
69808
70062
|
}
|
|
69809
|
-
getStartX() {
|
|
69810
|
-
return this.startNoteRenderer.getBeatX(this.startBeat, BeatXPosition.MiddleNotes);
|
|
69811
|
-
}
|
|
69812
|
-
getEndX() {
|
|
69813
|
-
const endBeamDirection = this.endNoteRenderer.getBeatDirection(this.endBeat);
|
|
69814
|
-
return this.endNoteRenderer.getBeatX(this.endBeat, this.endBeat.duration > Duration.Whole && endBeamDirection === this.tieDirection
|
|
69815
|
-
? BeatXPosition.Stem
|
|
69816
|
-
: BeatXPosition.MiddleNotes);
|
|
69817
|
-
}
|
|
69818
70063
|
}
|
|
69819
70064
|
|
|
69820
70065
|
/**
|
|
@@ -70014,142 +70259,106 @@
|
|
|
70014
70259
|
/**
|
|
70015
70260
|
* @internal
|
|
70016
70261
|
*/
|
|
70017
|
-
class
|
|
70018
|
-
|
|
70019
|
-
|
|
70020
|
-
|
|
70021
|
-
|
|
70022
|
-
|
|
70023
|
-
|
|
70262
|
+
class ScoreTieGlyph extends NoteTieGlyph {
|
|
70263
|
+
shouldDrawBendSlur() {
|
|
70264
|
+
return (this.renderer.settings.notation.extendBendArrowsOnTiedNotes &&
|
|
70265
|
+
!!this.startNote.bendOrigin &&
|
|
70266
|
+
this.startNote.isTieOrigin);
|
|
70267
|
+
}
|
|
70268
|
+
calculateStartX() {
|
|
70269
|
+
if (this.isLeftHandTap) {
|
|
70270
|
+
return this.calculateEndX() - this.renderer.smuflMetrics.leftHandTabTieWidth;
|
|
70271
|
+
}
|
|
70272
|
+
return this.renderer.x + this.renderer.getBeatX(this.startNote.beat, BeatXPosition.PostNotes);
|
|
70024
70273
|
}
|
|
70274
|
+
calculateEndX() {
|
|
70275
|
+
const endNoteRenderer = this.lookupEndBeatRenderer();
|
|
70276
|
+
if (!endNoteRenderer) {
|
|
70277
|
+
return this.calculateStartX() + this.renderer.smuflMetrics.leftHandTabTieWidth;
|
|
70278
|
+
}
|
|
70279
|
+
if (this.isLeftHandTap) {
|
|
70280
|
+
return endNoteRenderer.x + endNoteRenderer.getNoteX(this.endNote, NoteXPosition.Left);
|
|
70281
|
+
}
|
|
70282
|
+
return endNoteRenderer.x + endNoteRenderer.getBeatX(this.endNote.beat, BeatXPosition.PreNotes);
|
|
70283
|
+
}
|
|
70284
|
+
}
|
|
70285
|
+
|
|
70286
|
+
/**
|
|
70287
|
+
* @internal
|
|
70288
|
+
*/
|
|
70289
|
+
class ScoreSlurGlyph extends ScoreTieGlyph {
|
|
70025
70290
|
getTieHeight(startX, _startY, endX, _endY) {
|
|
70026
|
-
return Math.log2(endX - startX + 1) * this.renderer.settings.notation.slurHeight / 2;
|
|
70291
|
+
return (Math.log2(endX - startX + 1) * this.renderer.settings.notation.slurHeight) / 2;
|
|
70292
|
+
}
|
|
70293
|
+
calculateStartX() {
|
|
70294
|
+
return (this.renderer.x +
|
|
70295
|
+
(this._isStartCentered()
|
|
70296
|
+
? this.renderer.getBeatX(this.startNote.beat, BeatXPosition.MiddleNotes)
|
|
70297
|
+
: this.renderer.getNoteX(this.startNote, NoteXPosition.Right)));
|
|
70027
70298
|
}
|
|
70028
|
-
|
|
70299
|
+
calculateStartY() {
|
|
70029
70300
|
if (this._isStartCentered()) {
|
|
70030
70301
|
switch (this.tieDirection) {
|
|
70031
70302
|
case BeamDirection.Up:
|
|
70032
|
-
|
|
70033
|
-
return this.startNoteRenderer.getNoteY(this._startNote, NoteYPosition.Top);
|
|
70303
|
+
return this.renderer.y + this.renderer.getNoteY(this.startNote, NoteYPosition.Top);
|
|
70034
70304
|
default:
|
|
70035
|
-
return this.
|
|
70305
|
+
return this.renderer.y + this.renderer.getNoteY(this.startNote, NoteYPosition.Bottom);
|
|
70036
70306
|
}
|
|
70037
70307
|
}
|
|
70038
|
-
return this.
|
|
70308
|
+
return this.renderer.y + this.renderer.getNoteY(this.startNote, NoteYPosition.Center);
|
|
70039
70309
|
}
|
|
70040
|
-
|
|
70310
|
+
calculateEndX() {
|
|
70311
|
+
const endNoteRenderer = this.lookupEndBeatRenderer();
|
|
70312
|
+
if (!endNoteRenderer) {
|
|
70313
|
+
return this.calculateStartX() + this.renderer.smuflMetrics.leftHandTabTieWidth;
|
|
70314
|
+
}
|
|
70315
|
+
if (this._isEndCentered()) {
|
|
70316
|
+
if (this._isEndOnStem()) {
|
|
70317
|
+
return endNoteRenderer.x + endNoteRenderer.getBeatX(this.endNote.beat, BeatXPosition.Stem);
|
|
70318
|
+
}
|
|
70319
|
+
return endNoteRenderer.x + endNoteRenderer.getNoteX(this.endNote, NoteXPosition.Center);
|
|
70320
|
+
}
|
|
70321
|
+
return endNoteRenderer.x + endNoteRenderer.getBeatX(this.endNote.beat, BeatXPosition.PreNotes);
|
|
70322
|
+
}
|
|
70323
|
+
caclculateEndY() {
|
|
70324
|
+
const endNoteRenderer = this.lookupEndBeatRenderer();
|
|
70325
|
+
if (!endNoteRenderer) {
|
|
70326
|
+
return this.calculateStartY();
|
|
70327
|
+
}
|
|
70041
70328
|
if (this._isEndCentered()) {
|
|
70042
70329
|
if (this._isEndOnStem()) {
|
|
70043
70330
|
switch (this.tieDirection) {
|
|
70044
70331
|
case BeamDirection.Up:
|
|
70045
|
-
return
|
|
70332
|
+
return endNoteRenderer.y + endNoteRenderer.getNoteY(this.endNote, NoteYPosition.TopWithStem);
|
|
70046
70333
|
default:
|
|
70047
|
-
return
|
|
70334
|
+
return endNoteRenderer.y + endNoteRenderer.getNoteY(this.endNote, NoteYPosition.BottomWithStem);
|
|
70048
70335
|
}
|
|
70049
70336
|
}
|
|
70050
70337
|
switch (this.tieDirection) {
|
|
70051
70338
|
case BeamDirection.Up:
|
|
70052
|
-
return
|
|
70339
|
+
return endNoteRenderer.y + endNoteRenderer.getNoteY(this.endNote, NoteYPosition.Top);
|
|
70053
70340
|
default:
|
|
70054
|
-
return
|
|
70341
|
+
return endNoteRenderer.y + endNoteRenderer.getNoteY(this.endNote, NoteYPosition.Bottom);
|
|
70055
70342
|
}
|
|
70056
70343
|
}
|
|
70057
|
-
return
|
|
70344
|
+
return endNoteRenderer.y + endNoteRenderer.getNoteY(this.endNote, NoteYPosition.Center);
|
|
70058
70345
|
}
|
|
70059
70346
|
_isStartCentered() {
|
|
70060
|
-
return ((this.
|
|
70061
|
-
(this.
|
|
70347
|
+
return ((this.startNote === this.startNote.beat.maxNote && this.tieDirection === BeamDirection.Up) ||
|
|
70348
|
+
(this.startNote === this.startNote.beat.minNote && this.tieDirection === BeamDirection.Down));
|
|
70062
70349
|
}
|
|
70063
70350
|
_isEndCentered() {
|
|
70064
|
-
return (this.
|
|
70065
|
-
((this.
|
|
70066
|
-
(this.
|
|
70351
|
+
return (this.startNote.beat.graceType === GraceType.None &&
|
|
70352
|
+
((this.endNote === this.endNote.beat.maxNote && this.tieDirection === BeamDirection.Up) ||
|
|
70353
|
+
(this.endNote === this.endNote.beat.minNote && this.tieDirection === BeamDirection.Down)));
|
|
70067
70354
|
}
|
|
70068
70355
|
_isEndOnStem() {
|
|
70069
|
-
const
|
|
70070
|
-
const
|
|
70071
|
-
const endBeamDirection =
|
|
70072
|
-
|
|
70073
|
-
|
|
70074
|
-
|
|
70075
|
-
return this._isStartCentered()
|
|
70076
|
-
? this.startNoteRenderer.getBeatX(this._startNote.beat, BeatXPosition.MiddleNotes)
|
|
70077
|
-
: this.startNoteRenderer.getNoteX(this._startNote, NoteXPosition.Right);
|
|
70078
|
-
}
|
|
70079
|
-
getEndX() {
|
|
70080
|
-
if (this._isEndCentered()) {
|
|
70081
|
-
if (this._isEndOnStem()) {
|
|
70082
|
-
return this.endNoteRenderer.getBeatX(this._endNote.beat, BeatXPosition.Stem);
|
|
70083
|
-
}
|
|
70084
|
-
return this.endNoteRenderer.getNoteX(this._endNote, NoteXPosition.Center);
|
|
70085
|
-
}
|
|
70086
|
-
return this.endNoteRenderer.getBeatX(this._endNote.beat, BeatXPosition.PreNotes);
|
|
70087
|
-
}
|
|
70088
|
-
}
|
|
70089
|
-
|
|
70090
|
-
/**
|
|
70091
|
-
* @internal
|
|
70092
|
-
*/
|
|
70093
|
-
class ScoreTieGlyph extends TieGlyph {
|
|
70094
|
-
startNote;
|
|
70095
|
-
endNote;
|
|
70096
|
-
constructor(startNote, endNote, forEnd = false) {
|
|
70097
|
-
super(!startNote ? null : startNote.beat, !endNote ? null : endNote.beat, forEnd);
|
|
70098
|
-
this.startNote = startNote;
|
|
70099
|
-
this.endNote = endNote;
|
|
70100
|
-
}
|
|
70101
|
-
shouldDrawBendSlur() {
|
|
70102
|
-
return (this.renderer.settings.notation.extendBendArrowsOnTiedNotes &&
|
|
70103
|
-
!!this.startNote.bendOrigin &&
|
|
70104
|
-
this.startNote.isTieOrigin);
|
|
70105
|
-
}
|
|
70106
|
-
doLayout() {
|
|
70107
|
-
super.doLayout();
|
|
70108
|
-
}
|
|
70109
|
-
getBeamDirection(beat, noteRenderer) {
|
|
70110
|
-
// invert direction (if stems go up, ties go down to not cross them)
|
|
70111
|
-
switch (noteRenderer.getBeatDirection(beat)) {
|
|
70112
|
-
case BeamDirection.Up:
|
|
70113
|
-
return BeamDirection.Down;
|
|
70114
|
-
default:
|
|
70115
|
-
return BeamDirection.Up;
|
|
70116
|
-
}
|
|
70117
|
-
}
|
|
70118
|
-
getStartY() {
|
|
70119
|
-
if (this.startBeat.isRest) {
|
|
70120
|
-
// below all lines
|
|
70121
|
-
return this.startNoteRenderer.getScoreY(9);
|
|
70122
|
-
}
|
|
70123
|
-
switch (this.tieDirection) {
|
|
70124
|
-
case BeamDirection.Up:
|
|
70125
|
-
// below lowest note
|
|
70126
|
-
return this.startNoteRenderer.getNoteY(this.startNote, NoteYPosition.Top);
|
|
70127
|
-
default:
|
|
70128
|
-
return this.startNoteRenderer.getNoteY(this.startNote, NoteYPosition.Bottom);
|
|
70129
|
-
}
|
|
70130
|
-
}
|
|
70131
|
-
getEndY() {
|
|
70132
|
-
const endNoteScoreRenderer = this.endNoteRenderer;
|
|
70133
|
-
if (this.endBeat.isRest) {
|
|
70134
|
-
switch (this.tieDirection) {
|
|
70135
|
-
case BeamDirection.Up:
|
|
70136
|
-
return endNoteScoreRenderer.getScoreY(9);
|
|
70137
|
-
default:
|
|
70138
|
-
return endNoteScoreRenderer.getScoreY(0);
|
|
70139
|
-
}
|
|
70140
|
-
}
|
|
70141
|
-
switch (this.tieDirection) {
|
|
70142
|
-
case BeamDirection.Up:
|
|
70143
|
-
return endNoteScoreRenderer.getNoteY(this.endNote, NoteYPosition.Top);
|
|
70144
|
-
default:
|
|
70145
|
-
return endNoteScoreRenderer.getNoteY(this.endNote, NoteYPosition.Bottom);
|
|
70146
|
-
}
|
|
70147
|
-
}
|
|
70148
|
-
getStartX() {
|
|
70149
|
-
return this.startNoteRenderer.getBeatX(this.startNote.beat, BeatXPosition.PostNotes);
|
|
70150
|
-
}
|
|
70151
|
-
getEndX() {
|
|
70152
|
-
return this.endNoteRenderer.getBeatX(this.endNote.beat, BeatXPosition.PreNotes);
|
|
70356
|
+
const startBeamDirection = this.lookupStartBeatRenderer().getBeatDirection(this.startNote.beat);
|
|
70357
|
+
const endBeatRenderer = this.lookupEndBeatRenderer();
|
|
70358
|
+
const endBeamDirection = endBeatRenderer
|
|
70359
|
+
? endBeatRenderer.getBeatDirection(this.endNote.beat)
|
|
70360
|
+
: startBeamDirection;
|
|
70361
|
+
return startBeamDirection !== endBeamDirection && this.startNote.beat.graceType === GraceType.None;
|
|
70153
70362
|
}
|
|
70154
70363
|
}
|
|
70155
70364
|
|
|
@@ -70199,12 +70408,11 @@
|
|
|
70199
70408
|
n.beat.graceType !== GraceType.BendGrace &&
|
|
70200
70409
|
n.tieDestination &&
|
|
70201
70410
|
n.tieDestination.isVisible) {
|
|
70202
|
-
|
|
70203
|
-
const tie = new ScoreTieGlyph(n, n.tieDestination, false);
|
|
70411
|
+
const tie = new ScoreTieGlyph(`score.tie.${n.id}`, n, n.tieDestination, false);
|
|
70204
70412
|
this.addTie(tie);
|
|
70205
70413
|
}
|
|
70206
70414
|
if (n.isTieDestination && !n.tieOrigin.hasBend && !n.beat.hasWhammyBar) {
|
|
70207
|
-
const tie = new ScoreTieGlyph(n.tieOrigin, n, true);
|
|
70415
|
+
const tie = new ScoreTieGlyph(`score.tie.${n.tieOrigin.id}`, n.tieOrigin, n, true);
|
|
70208
70416
|
this.addTie(tie);
|
|
70209
70417
|
}
|
|
70210
70418
|
// TODO: depending on the type we have other positioning
|
|
@@ -70214,17 +70422,16 @@
|
|
|
70214
70422
|
this.addTie(l);
|
|
70215
70423
|
}
|
|
70216
70424
|
if (n.isSlurOrigin && n.slurDestination && n.slurDestination.isVisible) {
|
|
70217
|
-
|
|
70218
|
-
const tie = new ScoreSlurGlyph(n, n.slurDestination, false);
|
|
70425
|
+
const tie = new ScoreSlurGlyph(`score.slur.${n.id}`, n, n.slurDestination, false);
|
|
70219
70426
|
this.addTie(tie);
|
|
70220
70427
|
}
|
|
70221
70428
|
if (n.isSlurDestination) {
|
|
70222
|
-
const tie = new ScoreSlurGlyph(n.slurOrigin, n, true);
|
|
70429
|
+
const tie = new ScoreSlurGlyph(`score.slur.${n.slurOrigin.id}`, n.slurOrigin, n, true);
|
|
70223
70430
|
this.addTie(tie);
|
|
70224
70431
|
}
|
|
70225
70432
|
// start effect slur on first beat
|
|
70226
70433
|
if (!this._effectSlur && n.isEffectSlurOrigin && n.effectSlurDestination) {
|
|
70227
|
-
const effectSlur = new ScoreSlurGlyph(n, n.effectSlurDestination, false);
|
|
70434
|
+
const effectSlur = new ScoreSlurGlyph(`score.slur.effect.${n.beat.id}`, n, n.effectSlurDestination, false);
|
|
70228
70435
|
this._effectSlur = effectSlur;
|
|
70229
70436
|
this.addTie(effectSlur);
|
|
70230
70437
|
}
|
|
@@ -70233,7 +70440,7 @@
|
|
|
70233
70440
|
const direction = this.onNotes.beamingHelper.direction;
|
|
70234
70441
|
const startNote = direction === BeamDirection.Up ? n.beat.effectSlurOrigin.minNote : n.beat.effectSlurOrigin.maxNote;
|
|
70235
70442
|
const endNote = direction === BeamDirection.Up ? n.beat.minNote : n.beat.maxNote;
|
|
70236
|
-
const effectEndSlur = new ScoreSlurGlyph(startNote, endNote, true);
|
|
70443
|
+
const effectEndSlur = new ScoreSlurGlyph(`score.slur.effect.${startNote.beat.id}`, startNote, endNote, true);
|
|
70237
70444
|
this._effectEndSlur = effectEndSlur;
|
|
70238
70445
|
this.addTie(effectEndSlur);
|
|
70239
70446
|
}
|
|
@@ -70255,7 +70462,7 @@
|
|
|
70255
70462
|
while (destination.nextBeat && destination.nextBeat.isLegatoDestination) {
|
|
70256
70463
|
destination = destination.nextBeat;
|
|
70257
70464
|
}
|
|
70258
|
-
this.addTie(new ScoreLegatoGlyph(this.beat, destination, false));
|
|
70465
|
+
this.addTie(new ScoreLegatoGlyph(`score.legato.${this.beat.id}`, this.beat, destination, false));
|
|
70259
70466
|
}
|
|
70260
70467
|
}
|
|
70261
70468
|
else if (this.beat.isLegatoDestination) {
|
|
@@ -70265,7 +70472,7 @@
|
|
|
70265
70472
|
while (origin.previousBeat && origin.previousBeat.isLegatoOrigin) {
|
|
70266
70473
|
origin = origin.previousBeat;
|
|
70267
70474
|
}
|
|
70268
|
-
this.addTie(new ScoreLegatoGlyph(origin, this.beat, true));
|
|
70475
|
+
this.addTie(new ScoreLegatoGlyph(`score.legato.${origin.id}`, origin, this.beat, true));
|
|
70269
70476
|
}
|
|
70270
70477
|
}
|
|
70271
70478
|
}
|
|
@@ -70645,6 +70852,9 @@
|
|
|
70645
70852
|
this.addBeatGlyph(container);
|
|
70646
70853
|
}
|
|
70647
70854
|
}
|
|
70855
|
+
getNoteLine(note) {
|
|
70856
|
+
return this.accidentalHelper.getNoteSteps(note) / 2;
|
|
70857
|
+
}
|
|
70648
70858
|
getNoteSteps(n) {
|
|
70649
70859
|
return this.accidentalHelper.getNoteSteps(n);
|
|
70650
70860
|
}
|
|
@@ -70701,43 +70911,15 @@
|
|
|
70701
70911
|
/**
|
|
70702
70912
|
* @internal
|
|
70703
70913
|
*/
|
|
70704
|
-
class SlashTieGlyph extends
|
|
70705
|
-
|
|
70706
|
-
endNote;
|
|
70707
|
-
constructor(startNote, endNote, forEnd = false) {
|
|
70708
|
-
super(startNote.beat, endNote.beat, forEnd);
|
|
70709
|
-
this.startNote = startNote;
|
|
70710
|
-
this.endNote = endNote;
|
|
70711
|
-
}
|
|
70712
|
-
get _isLeftHandTap() {
|
|
70713
|
-
return this.startNote === this.endNote;
|
|
70714
|
-
}
|
|
70715
|
-
getTieHeight(startX, startY, endX, endY) {
|
|
70716
|
-
if (this._isLeftHandTap) {
|
|
70717
|
-
return this.startNoteRenderer.smuflMetrics.tieHeight;
|
|
70718
|
-
}
|
|
70719
|
-
return super.getTieHeight(startX, startY, endX, endY);
|
|
70720
|
-
}
|
|
70721
|
-
getBeamDirection(_beat, _noteRenderer) {
|
|
70914
|
+
class SlashTieGlyph extends NoteTieGlyph {
|
|
70915
|
+
calculateTieDirection() {
|
|
70722
70916
|
return BeamDirection.Down;
|
|
70723
70917
|
}
|
|
70724
|
-
|
|
70725
|
-
return
|
|
70726
|
-
}
|
|
70727
|
-
getStartY() {
|
|
70728
|
-
return this.startNoteRenderer.getNoteY(this.startNote, NoteYPosition.Center);
|
|
70729
|
-
}
|
|
70730
|
-
getEndY() {
|
|
70731
|
-
return this.getStartY();
|
|
70732
|
-
}
|
|
70733
|
-
getStartX() {
|
|
70734
|
-
if (this._isLeftHandTap) {
|
|
70735
|
-
return this.getEndX() - this.renderer.smuflMetrics.leftHandTabTieWidth;
|
|
70736
|
-
}
|
|
70737
|
-
return this.startNoteRenderer.getNoteX(this.startNote, NoteXPosition.Right);
|
|
70918
|
+
getStartNotePosition() {
|
|
70919
|
+
return NoteXPosition.Right;
|
|
70738
70920
|
}
|
|
70739
|
-
|
|
70740
|
-
return
|
|
70921
|
+
getEndNotePosition() {
|
|
70922
|
+
return NoteXPosition.Left;
|
|
70741
70923
|
}
|
|
70742
70924
|
}
|
|
70743
70925
|
|
|
@@ -70752,12 +70934,12 @@
|
|
|
70752
70934
|
return;
|
|
70753
70935
|
}
|
|
70754
70936
|
if (!this._tiedNoteTie && n.isTieOrigin && n.tieDestination.isVisible) {
|
|
70755
|
-
const tie = new SlashTieGlyph(n, n.tieDestination, false);
|
|
70937
|
+
const tie = new SlashTieGlyph('slash.tie', n, n.tieDestination, false);
|
|
70756
70938
|
this._tiedNoteTie = tie;
|
|
70757
70939
|
this.addTie(tie);
|
|
70758
70940
|
}
|
|
70759
70941
|
if (!this._tiedNoteTie && n.isTieDestination) {
|
|
70760
|
-
const tie = new SlashTieGlyph(n.tieOrigin, n, true);
|
|
70942
|
+
const tie = new SlashTieGlyph('slash.tie', n.tieOrigin, n, true);
|
|
70761
70943
|
this._tiedNoteTie = tie;
|
|
70762
70944
|
this.addTie(tie);
|
|
70763
70945
|
}
|
|
@@ -70884,8 +71066,7 @@
|
|
|
70884
71066
|
doLayout() {
|
|
70885
71067
|
// create glyphs
|
|
70886
71068
|
const sr = this.renderer;
|
|
70887
|
-
const
|
|
70888
|
-
const glyphY = sr.getLineY(line);
|
|
71069
|
+
const glyphY = sr.getLineY(0);
|
|
70889
71070
|
if (this.container.beat.deadSlapped) {
|
|
70890
71071
|
const deadSlapped = new DeadSlappedBeatGlyph();
|
|
70891
71072
|
deadSlapped.renderer = this.renderer;
|
|
@@ -70918,22 +71099,23 @@
|
|
|
70918
71099
|
//
|
|
70919
71100
|
if (this.container.beat.dots > 0) {
|
|
70920
71101
|
for (let i = 0; i < this.container.beat.dots; i++) {
|
|
70921
|
-
this.addEffect(new AugmentationDotGlyph(0,
|
|
71102
|
+
this.addEffect(new AugmentationDotGlyph(0, glyphY - sr.getLineHeight(0.5)));
|
|
70922
71103
|
}
|
|
70923
71104
|
}
|
|
70924
71105
|
super.doLayout();
|
|
70925
71106
|
if (this.container.beat.isEmpty) {
|
|
70926
|
-
this.
|
|
71107
|
+
this.onTimeX = this.width / 2;
|
|
70927
71108
|
}
|
|
70928
71109
|
else if (this.restGlyph) {
|
|
70929
|
-
this.
|
|
71110
|
+
this.onTimeX = this.restGlyph.x + this.restGlyph.width / 2;
|
|
70930
71111
|
}
|
|
70931
71112
|
else if (this.noteHeads) {
|
|
70932
|
-
this.
|
|
71113
|
+
this.onTimeX = this.noteHeads.x + this.noteHeads.width / 2;
|
|
70933
71114
|
}
|
|
70934
71115
|
else if (this.deadSlapped) {
|
|
70935
|
-
this.
|
|
71116
|
+
this.onTimeX = this.deadSlapped.x + this.deadSlapped.width / 2;
|
|
70936
71117
|
}
|
|
71118
|
+
this.middleX = this.onTimeX;
|
|
70937
71119
|
}
|
|
70938
71120
|
}
|
|
70939
71121
|
|
|
@@ -71000,7 +71182,7 @@
|
|
|
71000
71182
|
this.registerOverflowTop(this.tupletSize);
|
|
71001
71183
|
}
|
|
71002
71184
|
}
|
|
71003
|
-
getNoteLine() {
|
|
71185
|
+
getNoteLine(_note) {
|
|
71004
71186
|
return 0;
|
|
71005
71187
|
}
|
|
71006
71188
|
getFlagTopY(beat, _direction) {
|
|
@@ -71337,77 +71519,6 @@
|
|
|
71337
71519
|
}
|
|
71338
71520
|
}
|
|
71339
71521
|
|
|
71340
|
-
/**
|
|
71341
|
-
* @internal
|
|
71342
|
-
*/
|
|
71343
|
-
class TabSlurGlyph extends TabTieGlyph {
|
|
71344
|
-
_direction;
|
|
71345
|
-
_forSlide;
|
|
71346
|
-
constructor(startNote, endNote, forSlide, forEnd = false) {
|
|
71347
|
-
super(startNote, endNote, forEnd);
|
|
71348
|
-
this._direction = TabTieGlyph.getBeamDirectionForNote(startNote);
|
|
71349
|
-
this._forSlide = forSlide;
|
|
71350
|
-
}
|
|
71351
|
-
getTieHeight(startX, _startY, endX, _endY) {
|
|
71352
|
-
return Math.log(endX - startX + 1) * this.renderer.settings.notation.slurHeight / 2;
|
|
71353
|
-
}
|
|
71354
|
-
tryExpand(startNote, endNote, forSlide, forEnd) {
|
|
71355
|
-
// same type required
|
|
71356
|
-
if (this._forSlide !== forSlide) {
|
|
71357
|
-
return false;
|
|
71358
|
-
}
|
|
71359
|
-
if (this.forEnd !== forEnd) {
|
|
71360
|
-
return false;
|
|
71361
|
-
}
|
|
71362
|
-
// same start and endbeat
|
|
71363
|
-
if (this.startNote.beat.id !== startNote.beat.id) {
|
|
71364
|
-
return false;
|
|
71365
|
-
}
|
|
71366
|
-
if (this.endNote.beat.id !== endNote.beat.id) {
|
|
71367
|
-
return false;
|
|
71368
|
-
}
|
|
71369
|
-
// same draw direction
|
|
71370
|
-
if (this._direction !== TabTieGlyph.getBeamDirectionForNote(startNote)) {
|
|
71371
|
-
return false;
|
|
71372
|
-
}
|
|
71373
|
-
// if we can expand, expand in correct direction
|
|
71374
|
-
switch (this._direction) {
|
|
71375
|
-
case BeamDirection.Up:
|
|
71376
|
-
if (startNote.realValue > this.startNote.realValue) {
|
|
71377
|
-
this.startNote = startNote;
|
|
71378
|
-
this.startBeat = startNote.beat;
|
|
71379
|
-
}
|
|
71380
|
-
if (endNote.realValue > this.endNote.realValue) {
|
|
71381
|
-
this.endNote = endNote;
|
|
71382
|
-
this.endBeat = endNote.beat;
|
|
71383
|
-
}
|
|
71384
|
-
break;
|
|
71385
|
-
case BeamDirection.Down:
|
|
71386
|
-
if (startNote.realValue < this.startNote.realValue) {
|
|
71387
|
-
this.startNote = startNote;
|
|
71388
|
-
this.startBeat = startNote.beat;
|
|
71389
|
-
}
|
|
71390
|
-
if (endNote.realValue < this.endNote.realValue) {
|
|
71391
|
-
this.endNote = endNote;
|
|
71392
|
-
this.endBeat = endNote.beat;
|
|
71393
|
-
}
|
|
71394
|
-
break;
|
|
71395
|
-
}
|
|
71396
|
-
return true;
|
|
71397
|
-
}
|
|
71398
|
-
paint(cx, cy, canvas) {
|
|
71399
|
-
const startNoteRenderer = this.renderer.scoreRenderer.layout.getRendererForBar(this.renderer.staff.staffId, this.startBeat.voice.bar);
|
|
71400
|
-
const direction = this.getBeamDirection(this.startBeat, startNoteRenderer);
|
|
71401
|
-
const slurId = `tab.slur.${this.startNote.beat.id}.${this.endNote.beat.id}.${direction}`;
|
|
71402
|
-
const renderer = this.renderer;
|
|
71403
|
-
const isSlurRendered = renderer.staff.getSharedLayoutData(slurId, false);
|
|
71404
|
-
if (!isSlurRendered) {
|
|
71405
|
-
renderer.staff.setSharedLayoutData(slurId, true);
|
|
71406
|
-
super.paint(cx, cy, canvas);
|
|
71407
|
-
}
|
|
71408
|
-
}
|
|
71409
|
-
}
|
|
71410
|
-
|
|
71411
71522
|
/**
|
|
71412
71523
|
* @internal
|
|
71413
71524
|
*/
|
|
@@ -71432,15 +71543,15 @@
|
|
|
71432
71543
|
}
|
|
71433
71544
|
const renderer = this.renderer;
|
|
71434
71545
|
if (n.isTieOrigin && renderer.showTiedNotes && n.tieDestination.isVisible) {
|
|
71435
|
-
const tie = new TabTieGlyph(n, n.tieDestination, false);
|
|
71546
|
+
const tie = new TabTieGlyph(`tab.tie.${n.id}`, n, n.tieDestination, false);
|
|
71436
71547
|
this.addTie(tie);
|
|
71437
71548
|
}
|
|
71438
71549
|
if (n.isTieDestination && renderer.showTiedNotes) {
|
|
71439
|
-
const tie = new TabTieGlyph(n.tieOrigin, n, true);
|
|
71550
|
+
const tie = new TabTieGlyph(`tab.tie.${n.tieOrigin.id}`, n.tieOrigin, n, true);
|
|
71440
71551
|
this.addTie(tie);
|
|
71441
71552
|
}
|
|
71442
71553
|
if (n.isLeftHandTapped && !n.isHammerPullDestination) {
|
|
71443
|
-
const tapSlur = new TabTieGlyph(n, n, false);
|
|
71554
|
+
const tapSlur = new TabTieGlyph(`tab.tie.leftHandTap.${n.id}`, n, n, false);
|
|
71444
71555
|
this.addTie(tapSlur);
|
|
71445
71556
|
}
|
|
71446
71557
|
// start effect slur on first beat
|
|
@@ -71453,7 +71564,7 @@
|
|
|
71453
71564
|
}
|
|
71454
71565
|
}
|
|
71455
71566
|
if (!expanded) {
|
|
71456
|
-
const effectSlur = new TabSlurGlyph(n, n.effectSlurDestination, false, false);
|
|
71567
|
+
const effectSlur = new TabSlurGlyph(`tab.slur.effect.${n.id}`, n, n.effectSlurDestination, false, false);
|
|
71457
71568
|
this._effectSlurs.push(effectSlur);
|
|
71458
71569
|
this.addTie(effectSlur);
|
|
71459
71570
|
}
|
|
@@ -71468,7 +71579,7 @@
|
|
|
71468
71579
|
}
|
|
71469
71580
|
}
|
|
71470
71581
|
if (!expanded) {
|
|
71471
|
-
const effectSlur = new TabSlurGlyph(n.effectSlurOrigin, n, false, true);
|
|
71582
|
+
const effectSlur = new TabSlurGlyph(`tab.slur.effect.${n.effectSlurOrigin.id}`, n.effectSlurOrigin, n, false, true);
|
|
71472
71583
|
this._effectSlurs.push(effectSlur);
|
|
71473
71584
|
this.addTie(effectSlur);
|
|
71474
71585
|
}
|
|
@@ -71887,7 +71998,7 @@
|
|
|
71887
71998
|
}
|
|
71888
71999
|
else {
|
|
71889
72000
|
const line = Math.floor((this.renderer.bar.staff.tuning.length - 1) / 2);
|
|
71890
|
-
const y = tabRenderer.
|
|
72001
|
+
const y = tabRenderer.getLineY(line);
|
|
71891
72002
|
const restGlyph = new TabRestGlyph(0, y, tabRenderer.showRests, this.container.beat.duration);
|
|
71892
72003
|
this.restGlyph = restGlyph;
|
|
71893
72004
|
restGlyph.beat = this.container.beat;
|
|
@@ -71917,19 +72028,20 @@
|
|
|
71917
72028
|
this.width = w;
|
|
71918
72029
|
this.computedWidth = w;
|
|
71919
72030
|
if (this.container.beat.isEmpty) {
|
|
71920
|
-
this.
|
|
72031
|
+
this.onTimeX = this.width / 2;
|
|
71921
72032
|
}
|
|
71922
72033
|
else if (this.restGlyph) {
|
|
71923
|
-
this.
|
|
72034
|
+
this.onTimeX = this.restGlyph.x + this.restGlyph.width / 2;
|
|
71924
72035
|
}
|
|
71925
72036
|
else if (this.noteNumbers) {
|
|
71926
|
-
this.
|
|
72037
|
+
this.onTimeX = this.noteNumbers.x + this.noteNumbers.noteStringWidth / 2;
|
|
71927
72038
|
}
|
|
71928
72039
|
else if (this.slash) {
|
|
71929
|
-
this.
|
|
72040
|
+
this.onTimeX = this.slash.x + this.slash.width / 2;
|
|
71930
72041
|
}
|
|
72042
|
+
this.middleX = this.onTimeX;
|
|
71931
72043
|
for (const g of centeredEffectGlyphs) {
|
|
71932
|
-
g.x = this.
|
|
72044
|
+
g.x = this.onTimeX;
|
|
71933
72045
|
}
|
|
71934
72046
|
}
|
|
71935
72047
|
updateBeamingHelper() {
|
|
@@ -71946,8 +72058,8 @@
|
|
|
71946
72058
|
_createNoteGlyph(n) {
|
|
71947
72059
|
const tr = this.renderer;
|
|
71948
72060
|
const noteNumberGlyph = new NoteNumberGlyph(0, 0, n);
|
|
71949
|
-
const l =
|
|
71950
|
-
noteNumberGlyph.y = tr.
|
|
72061
|
+
const l = tr.getNoteLine(n);
|
|
72062
|
+
noteNumberGlyph.y = tr.getLineY(l);
|
|
71951
72063
|
noteNumberGlyph.renderer = this.renderer;
|
|
71952
72064
|
noteNumberGlyph.doLayout();
|
|
71953
72065
|
this.noteNumbers.addNoteGlyph(noteNumberGlyph, n);
|
|
@@ -72138,17 +72250,8 @@
|
|
|
72138
72250
|
}
|
|
72139
72251
|
return mode;
|
|
72140
72252
|
}
|
|
72141
|
-
|
|
72142
|
-
|
|
72143
|
-
* @param line the line of the particular string where 0 is the most top line
|
|
72144
|
-
* @param correction
|
|
72145
|
-
* @returns
|
|
72146
|
-
*/
|
|
72147
|
-
getTabY(line) {
|
|
72148
|
-
return super.getLineY(line);
|
|
72149
|
-
}
|
|
72150
|
-
getTabHeight(line) {
|
|
72151
|
-
return super.getLineHeight(line);
|
|
72253
|
+
getNoteLine(note) {
|
|
72254
|
+
return this.bar.staff.tuning.length - note.string;
|
|
72152
72255
|
}
|
|
72153
72256
|
minString = Number.NaN;
|
|
72154
72257
|
maxString = Number.NaN;
|
|
@@ -72237,7 +72340,7 @@
|
|
|
72237
72340
|
if (this.isFirstOfLine) {
|
|
72238
72341
|
const center = (this.bar.staff.tuning.length - 1) / 2;
|
|
72239
72342
|
this.createStartSpacing();
|
|
72240
|
-
this.addPreBeatGlyph(new TabClefGlyph(0, this.
|
|
72343
|
+
this.addPreBeatGlyph(new TabClefGlyph(0, this.getLineY(center)));
|
|
72241
72344
|
}
|
|
72242
72345
|
// Time Signature
|
|
72243
72346
|
if (this.showTimeSignature &&
|
|
@@ -72258,7 +72361,7 @@
|
|
|
72258
72361
|
_createTimeSignatureGlyphs() {
|
|
72259
72362
|
this.addPreBeatGlyph(new SpacingGlyph(0, 0, this.smuflMetrics.oneStaffSpace));
|
|
72260
72363
|
const lines = (this.bar.staff.tuning.length + 1) / 2 - 1;
|
|
72261
|
-
this.addPreBeatGlyph(new TabTimeSignatureGlyph(0, this.
|
|
72364
|
+
this.addPreBeatGlyph(new TabTimeSignatureGlyph(0, this.getLineY(lines), this.bar.masterBar.timeSignatureNumerator, this.bar.masterBar.timeSignatureDenominator, this.bar.masterBar.timeSignatureCommon, this.bar.masterBar.isFreeTime));
|
|
72262
72365
|
}
|
|
72263
72366
|
createVoiceGlyphs(v) {
|
|
72264
72367
|
super.createVoiceGlyphs(v);
|