@coderline/alphatab 1.8.0-alpha.1637 → 1.8.0-alpha.1639
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 +794 -732
- package/dist/alphaTab.js +794 -732
- 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.core.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* alphaTab v1.8.0-alpha.
|
|
2
|
+
* alphaTab v1.8.0-alpha.1639 (develop, build 1639)
|
|
3
3
|
*
|
|
4
4
|
* Copyright © 2025, Daniel Kuschny and Contributors, All rights reserved.
|
|
5
5
|
*
|
|
@@ -203,9 +203,9 @@ class AlphaTabError extends Error {
|
|
|
203
203
|
* @internal
|
|
204
204
|
*/
|
|
205
205
|
class VersionInfo {
|
|
206
|
-
static version = '1.8.0-alpha.
|
|
207
|
-
static date = '2025-12-
|
|
208
|
-
static commit = '
|
|
206
|
+
static version = '1.8.0-alpha.1639';
|
|
207
|
+
static date = '2025-12-09T02:16:01.440Z';
|
|
208
|
+
static commit = 'af86866e4f9d89a3ccc34006d01473a549dbbe7f';
|
|
209
209
|
static print(print) {
|
|
210
210
|
print(`alphaTab ${VersionInfo.version}`);
|
|
211
211
|
print(`commit: ${VersionInfo.commit}`);
|
|
@@ -56664,12 +56664,12 @@ class GroupedEffectGlyph extends EffectGlyph {
|
|
|
56664
56664
|
this.endPosition = endPosition;
|
|
56665
56665
|
}
|
|
56666
56666
|
get isLinkedWithPrevious() {
|
|
56667
|
-
return !!this.previousGlyph && this.previousGlyph.renderer.staff
|
|
56667
|
+
return !!this.previousGlyph && this.previousGlyph.renderer.staff?.system === this.renderer.staff.system;
|
|
56668
56668
|
}
|
|
56669
56669
|
get isLinkedWithNext() {
|
|
56670
56670
|
return (!!this.nextGlyph &&
|
|
56671
56671
|
this.nextGlyph.renderer.isFinalized &&
|
|
56672
|
-
this.nextGlyph.renderer.staff
|
|
56672
|
+
this.nextGlyph.renderer.staff?.system === this.renderer.staff.system);
|
|
56673
56673
|
}
|
|
56674
56674
|
paint(cx, cy, canvas) {
|
|
56675
56675
|
// if we are linked with the previous, the first glyph of the group will also render this one.
|
|
@@ -59057,6 +59057,437 @@ class LeftToRightLayoutingGlyphGroup extends GlyphGroup {
|
|
|
59057
59057
|
}
|
|
59058
59058
|
}
|
|
59059
59059
|
|
|
59060
|
+
/**
|
|
59061
|
+
* @internal
|
|
59062
|
+
*/
|
|
59063
|
+
class TieGlyph extends Glyph {
|
|
59064
|
+
tieDirection = BeamDirection.Up;
|
|
59065
|
+
slurEffectId;
|
|
59066
|
+
isForEnd;
|
|
59067
|
+
constructor(slurEffectId, forEnd) {
|
|
59068
|
+
super(0, 0);
|
|
59069
|
+
this.slurEffectId = slurEffectId;
|
|
59070
|
+
this.isForEnd = forEnd;
|
|
59071
|
+
}
|
|
59072
|
+
_startX = 0;
|
|
59073
|
+
_startY = 0;
|
|
59074
|
+
_endX = 0;
|
|
59075
|
+
_endY = 0;
|
|
59076
|
+
_tieHeight = 0;
|
|
59077
|
+
_boundingBox;
|
|
59078
|
+
_shouldPaint = false;
|
|
59079
|
+
get checkForOverflow() {
|
|
59080
|
+
return this._shouldPaint && this._boundingBox !== undefined;
|
|
59081
|
+
}
|
|
59082
|
+
getBoundingBoxTop() {
|
|
59083
|
+
if (this._boundingBox) {
|
|
59084
|
+
return this._boundingBox.y;
|
|
59085
|
+
}
|
|
59086
|
+
return this._startY;
|
|
59087
|
+
}
|
|
59088
|
+
getBoundingBoxBottom() {
|
|
59089
|
+
if (this._boundingBox) {
|
|
59090
|
+
return this._boundingBox.y + this._boundingBox.h;
|
|
59091
|
+
}
|
|
59092
|
+
return this._startY;
|
|
59093
|
+
}
|
|
59094
|
+
doLayout() {
|
|
59095
|
+
this.width = 0;
|
|
59096
|
+
const startNoteRenderer = this.lookupStartBeatRenderer();
|
|
59097
|
+
const endNoteRenderer = this.lookupEndBeatRenderer();
|
|
59098
|
+
this._startX = 0;
|
|
59099
|
+
this._endX = 0;
|
|
59100
|
+
this._startY = 0;
|
|
59101
|
+
this._endY = 0;
|
|
59102
|
+
this.height = 0;
|
|
59103
|
+
// if we are on the tie start, we check if we
|
|
59104
|
+
// either can draw till the end note, or we just can draw till the bar end
|
|
59105
|
+
this.tieDirection = this.calculateTieDirection();
|
|
59106
|
+
const forEnd = this.isForEnd;
|
|
59107
|
+
this._shouldPaint = false;
|
|
59108
|
+
if (!forEnd) {
|
|
59109
|
+
if (startNoteRenderer !== endNoteRenderer) {
|
|
59110
|
+
this._startX = this.calculateStartX();
|
|
59111
|
+
this._startY = this.calculateStartY();
|
|
59112
|
+
if (!endNoteRenderer || startNoteRenderer.staff !== endNoteRenderer.staff) {
|
|
59113
|
+
const lastRendererInStaff = startNoteRenderer.staff.barRenderers[startNoteRenderer.staff.barRenderers.length - 1];
|
|
59114
|
+
this._endX = lastRendererInStaff.x + lastRendererInStaff.width;
|
|
59115
|
+
this._endY = this._startY;
|
|
59116
|
+
startNoteRenderer.scoreRenderer.layout.slurRegistry.startMultiSystemSlur(this);
|
|
59117
|
+
}
|
|
59118
|
+
else {
|
|
59119
|
+
this._endX = this.calculateEndX();
|
|
59120
|
+
this._endY = this.caclculateEndY();
|
|
59121
|
+
}
|
|
59122
|
+
}
|
|
59123
|
+
else {
|
|
59124
|
+
this._shouldPaint = true;
|
|
59125
|
+
this._startX = this.calculateStartX();
|
|
59126
|
+
this._endX = this.calculateEndX();
|
|
59127
|
+
this._startY = this.calculateStartY();
|
|
59128
|
+
this._endY = this.caclculateEndY();
|
|
59129
|
+
}
|
|
59130
|
+
this._shouldPaint = true;
|
|
59131
|
+
}
|
|
59132
|
+
else if (startNoteRenderer.staff !== endNoteRenderer.staff) {
|
|
59133
|
+
const firstRendererInStaff = startNoteRenderer.staff.barRenderers[0];
|
|
59134
|
+
this._startX = firstRendererInStaff.x;
|
|
59135
|
+
this._endX = this.calculateEndX();
|
|
59136
|
+
const startGlyph = startNoteRenderer.scoreRenderer.layout.slurRegistry.completeMultiSystemSlur(this);
|
|
59137
|
+
if (startGlyph) {
|
|
59138
|
+
this._startY = startGlyph.calculateMultiSystemSlurY(endNoteRenderer);
|
|
59139
|
+
}
|
|
59140
|
+
else {
|
|
59141
|
+
this._startY = this.caclculateEndY();
|
|
59142
|
+
}
|
|
59143
|
+
this._endY = this.caclculateEndY();
|
|
59144
|
+
this._shouldPaint = startNoteRenderer.staff !== endNoteRenderer.staff;
|
|
59145
|
+
}
|
|
59146
|
+
this._boundingBox = undefined;
|
|
59147
|
+
this.y = Math.min(this._startY, this._endY);
|
|
59148
|
+
if (this.shouldDrawBendSlur()) {
|
|
59149
|
+
this._tieHeight = 0; // TODO: Bend slur height to be considered?
|
|
59150
|
+
}
|
|
59151
|
+
else {
|
|
59152
|
+
this._tieHeight = this.getTieHeight(this._startX, this._startY, this._endX, this._endY);
|
|
59153
|
+
const tieBoundingBox = TieGlyph.calculateActualTieHeight(1, this._startX, this._startY, this._endX, this._endY, this.tieDirection === BeamDirection.Down, this._tieHeight, this.renderer.smuflMetrics.tieMidpointThickness);
|
|
59154
|
+
this._boundingBox = tieBoundingBox;
|
|
59155
|
+
this.height = tieBoundingBox.h;
|
|
59156
|
+
if (this.tieDirection === BeamDirection.Up) {
|
|
59157
|
+
// the tie might go above `this.y` due to its shape
|
|
59158
|
+
// here we calculate how much this is so we can consider the
|
|
59159
|
+
// respective overflow
|
|
59160
|
+
const overlap = this.y - tieBoundingBox.y;
|
|
59161
|
+
if (overlap > 0) {
|
|
59162
|
+
this.y -= overlap;
|
|
59163
|
+
}
|
|
59164
|
+
}
|
|
59165
|
+
}
|
|
59166
|
+
}
|
|
59167
|
+
paint(cx, cy, canvas) {
|
|
59168
|
+
if (!this._shouldPaint) {
|
|
59169
|
+
return;
|
|
59170
|
+
}
|
|
59171
|
+
if (this.shouldDrawBendSlur()) {
|
|
59172
|
+
TieGlyph.drawBendSlur(canvas, cx + this._startX, cy + this._startY, cx + this._endX, cy + this._endY, this.tieDirection === BeamDirection.Down, 1, this.renderer.smuflMetrics.tieHeight);
|
|
59173
|
+
}
|
|
59174
|
+
else {
|
|
59175
|
+
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);
|
|
59176
|
+
}
|
|
59177
|
+
}
|
|
59178
|
+
getTieHeight(_startX, _startY, _endX, _endY) {
|
|
59179
|
+
return this.renderer.smuflMetrics.tieHeight;
|
|
59180
|
+
}
|
|
59181
|
+
calculateMultiSystemSlurY(renderer) {
|
|
59182
|
+
const startRenderer = this.lookupStartBeatRenderer();
|
|
59183
|
+
const startY = this.calculateStartY();
|
|
59184
|
+
const relY = startY - startRenderer.y;
|
|
59185
|
+
return renderer.y + relY;
|
|
59186
|
+
}
|
|
59187
|
+
shouldCreateMultiSystemSlur(renderer) {
|
|
59188
|
+
const endStaff = this.lookupEndBeatRenderer()?.staff;
|
|
59189
|
+
if (!endStaff) {
|
|
59190
|
+
return true;
|
|
59191
|
+
}
|
|
59192
|
+
return renderer.staff.system.index < endStaff.system.index;
|
|
59193
|
+
}
|
|
59194
|
+
static calculateActualTieHeight(scale, x1, y1, x2, y2, down, offset, size) {
|
|
59195
|
+
const cp = TieGlyph._computeBezierControlPoints(scale, x1, y1, x2, y2, down, offset, size);
|
|
59196
|
+
if (cp.length === 0) {
|
|
59197
|
+
return new Bounds(x1, y1, x2 - x1, y2 - y1);
|
|
59198
|
+
}
|
|
59199
|
+
// For a musical tie/slur, the extrema occur predictably near the midpoint
|
|
59200
|
+
// Evaluate at midpoint (t=0.5) and check endpoints
|
|
59201
|
+
const p0x = cp[0];
|
|
59202
|
+
const p0y = cp[1];
|
|
59203
|
+
const c1x = cp[2];
|
|
59204
|
+
const c1y = cp[3];
|
|
59205
|
+
const c2x = cp[4];
|
|
59206
|
+
const c2y = cp[5];
|
|
59207
|
+
const p1x = cp[6];
|
|
59208
|
+
const p1y = cp[7];
|
|
59209
|
+
// Evaluate at t=0.5 for midpoint
|
|
59210
|
+
const midX = 0.125 * p0x + 0.375 * c1x + 0.375 * c2x + 0.125 * p1x;
|
|
59211
|
+
const midY = 0.125 * p0y + 0.375 * c1y + 0.375 * c2y + 0.125 * p1y;
|
|
59212
|
+
// Bounds are simply min/max of start, end, and midpoint
|
|
59213
|
+
const xMin = Math.min(p0x, p1x, midX);
|
|
59214
|
+
const xMax = Math.max(p0x, p1x, midX);
|
|
59215
|
+
let yMin = Math.min(p0y, p1y, midY);
|
|
59216
|
+
let yMax = Math.max(p0y, p1y, midY);
|
|
59217
|
+
// Account for thickness of the tie/slur
|
|
59218
|
+
if (down) {
|
|
59219
|
+
yMax += size;
|
|
59220
|
+
}
|
|
59221
|
+
else {
|
|
59222
|
+
yMin -= size;
|
|
59223
|
+
}
|
|
59224
|
+
const b = new Bounds();
|
|
59225
|
+
b.x = xMin;
|
|
59226
|
+
b.y = yMin;
|
|
59227
|
+
b.w = xMax - xMin;
|
|
59228
|
+
b.h = yMax - yMin;
|
|
59229
|
+
return b;
|
|
59230
|
+
}
|
|
59231
|
+
static _computeBezierControlPoints(scale, x1, y1, x2, y2, down, offset, size) {
|
|
59232
|
+
if (x1 === x2 && y1 === y2) {
|
|
59233
|
+
return [];
|
|
59234
|
+
}
|
|
59235
|
+
// ensure endX > startX
|
|
59236
|
+
if (x2 < x1) {
|
|
59237
|
+
let t = x1;
|
|
59238
|
+
x1 = x2;
|
|
59239
|
+
x2 = t;
|
|
59240
|
+
t = y1;
|
|
59241
|
+
y1 = y2;
|
|
59242
|
+
y2 = t;
|
|
59243
|
+
}
|
|
59244
|
+
//
|
|
59245
|
+
// calculate control points
|
|
59246
|
+
//
|
|
59247
|
+
offset *= scale;
|
|
59248
|
+
size *= scale;
|
|
59249
|
+
if (down) {
|
|
59250
|
+
offset *= -1;
|
|
59251
|
+
size *= -1;
|
|
59252
|
+
}
|
|
59253
|
+
if (scale >= 1) {
|
|
59254
|
+
size *= 1.2;
|
|
59255
|
+
}
|
|
59256
|
+
// calculate control points on horizontal axis then rotate:
|
|
59257
|
+
/*
|
|
59258
|
+
cp1x/cpy1 cp2x/cpy2
|
|
59259
|
+
*----------------*
|
|
59260
|
+
/ \
|
|
59261
|
+
/ \
|
|
59262
|
+
x1/y1 * * x2/y2
|
|
59263
|
+
|
|
59264
|
+
cp3 and cp4 are simply with lower height
|
|
59265
|
+
*/
|
|
59266
|
+
const dY = y2 - y1;
|
|
59267
|
+
const dX = x2 - x1;
|
|
59268
|
+
const length = Math.sqrt(dX * dX + dY * dY);
|
|
59269
|
+
let cp1x = x1 + length * 0.25;
|
|
59270
|
+
let cp1y = y1 - offset;
|
|
59271
|
+
let cp2x = x1 + length * 0.75;
|
|
59272
|
+
let cp2y = y1 - offset;
|
|
59273
|
+
let cp3x = x1 + length * 0.75;
|
|
59274
|
+
let cp3y = y1 - offset - size;
|
|
59275
|
+
let cp4x = x1 + length * 0.25;
|
|
59276
|
+
let cp4y = y1 - offset - size;
|
|
59277
|
+
const angle = Math.atan2(dY, dX);
|
|
59278
|
+
[cp1x, cp1y] = TieGlyph._rotate(cp1x, cp1y, x1, y1, angle);
|
|
59279
|
+
[cp2x, cp2y] = TieGlyph._rotate(cp2x, cp2y, x1, y1, angle);
|
|
59280
|
+
[cp3x, cp3y] = TieGlyph._rotate(cp3x, cp3y, x1, y1, angle);
|
|
59281
|
+
[cp4x, cp4y] = TieGlyph._rotate(cp4x, cp4y, x1, y1, angle);
|
|
59282
|
+
return [x1, y1, cp1x, cp1y, cp2x, cp2y, x2, y2, cp3x, cp3y, cp4x, cp4y, x1, y1];
|
|
59283
|
+
}
|
|
59284
|
+
static _rotate(x, y, rotateX, rotateY, angle) {
|
|
59285
|
+
const dx = x - rotateX;
|
|
59286
|
+
const dy = y - rotateY;
|
|
59287
|
+
const rx = dx * Math.cos(angle) - dy * Math.sin(angle);
|
|
59288
|
+
const ry = dx * Math.sin(angle) + dy * Math.cos(angle);
|
|
59289
|
+
return [rotateX + rx, rotateY + ry];
|
|
59290
|
+
}
|
|
59291
|
+
static paintTie(canvas, scale, x1, y1, x2, y2, down /*= false*/, offset /*= 22*/, size /*= 4*/) {
|
|
59292
|
+
const cps = TieGlyph._computeBezierControlPoints(scale, x1, y1, x2, y2, down, offset, size);
|
|
59293
|
+
canvas.beginPath();
|
|
59294
|
+
canvas.moveTo(cps[0], cps[1]);
|
|
59295
|
+
canvas.bezierCurveTo(cps[2], cps[3], cps[4], cps[5], cps[6], cps[7]);
|
|
59296
|
+
canvas.bezierCurveTo(cps[8], cps[9], cps[10], cps[11], cps[12], cps[13]);
|
|
59297
|
+
canvas.closePath();
|
|
59298
|
+
canvas.fill();
|
|
59299
|
+
}
|
|
59300
|
+
static calculateBendSlurTopY(x1, y1, x2, y2, down, scale, bendSlurHeight) {
|
|
59301
|
+
let normalVectorX = y2 - y1;
|
|
59302
|
+
let normalVectorY = x2 - x1;
|
|
59303
|
+
const length = Math.sqrt(normalVectorX * normalVectorX + normalVectorY * normalVectorY);
|
|
59304
|
+
if (down) {
|
|
59305
|
+
normalVectorX *= -1;
|
|
59306
|
+
}
|
|
59307
|
+
else {
|
|
59308
|
+
normalVectorY *= -1;
|
|
59309
|
+
}
|
|
59310
|
+
// make to unit vector
|
|
59311
|
+
normalVectorX /= length;
|
|
59312
|
+
normalVectorY /= length;
|
|
59313
|
+
let offset = bendSlurHeight * scale;
|
|
59314
|
+
if (x2 - x1 < 20) {
|
|
59315
|
+
offset /= 2;
|
|
59316
|
+
}
|
|
59317
|
+
const centerY = (y2 + y1) / 2;
|
|
59318
|
+
const cp1Y = centerY + offset * normalVectorY;
|
|
59319
|
+
return cp1Y;
|
|
59320
|
+
}
|
|
59321
|
+
static drawBendSlur(canvas, x1, y1, x2, y2, down, scale, bendSlurHeight, slurText) {
|
|
59322
|
+
let normalVectorX = y2 - y1;
|
|
59323
|
+
let normalVectorY = x2 - x1;
|
|
59324
|
+
const length = Math.sqrt(normalVectorX * normalVectorX + normalVectorY * normalVectorY);
|
|
59325
|
+
if (down) {
|
|
59326
|
+
normalVectorX *= -1;
|
|
59327
|
+
}
|
|
59328
|
+
else {
|
|
59329
|
+
normalVectorY *= -1;
|
|
59330
|
+
}
|
|
59331
|
+
// make to unit vector
|
|
59332
|
+
normalVectorX /= length;
|
|
59333
|
+
normalVectorY /= length;
|
|
59334
|
+
// center of connection
|
|
59335
|
+
// TODO: should be 1/3
|
|
59336
|
+
const centerX = (x2 + x1) / 2;
|
|
59337
|
+
const centerY = (y2 + y1) / 2;
|
|
59338
|
+
let offset = bendSlurHeight * scale;
|
|
59339
|
+
if (x2 - x1 < 20) {
|
|
59340
|
+
offset /= 2;
|
|
59341
|
+
}
|
|
59342
|
+
const cp1X = centerX + offset * normalVectorX;
|
|
59343
|
+
const cp1Y = centerY + offset * normalVectorY;
|
|
59344
|
+
canvas.beginPath();
|
|
59345
|
+
canvas.moveTo(x1, y1);
|
|
59346
|
+
canvas.lineTo(cp1X, cp1Y);
|
|
59347
|
+
canvas.lineTo(x2, y2);
|
|
59348
|
+
canvas.stroke();
|
|
59349
|
+
if (slurText) {
|
|
59350
|
+
const w = canvas.measureText(slurText).width;
|
|
59351
|
+
const textOffset = down ? 0 : -canvas.font.size;
|
|
59352
|
+
canvas.fillText(slurText, cp1X - w / 2, cp1Y + textOffset);
|
|
59353
|
+
}
|
|
59354
|
+
}
|
|
59355
|
+
}
|
|
59356
|
+
/**
|
|
59357
|
+
* A common tie implementation using note details for positioning
|
|
59358
|
+
* @internal
|
|
59359
|
+
*/
|
|
59360
|
+
class NoteTieGlyph extends TieGlyph {
|
|
59361
|
+
startNote;
|
|
59362
|
+
endNote;
|
|
59363
|
+
startNoteRenderer = null;
|
|
59364
|
+
endNoteRenderer = null;
|
|
59365
|
+
constructor(slurEffectId, startNote, endNote, forEnd) {
|
|
59366
|
+
super(slurEffectId, forEnd);
|
|
59367
|
+
this.startNote = startNote;
|
|
59368
|
+
this.endNote = endNote;
|
|
59369
|
+
}
|
|
59370
|
+
get isLeftHandTap() {
|
|
59371
|
+
return this.startNote === this.endNote;
|
|
59372
|
+
}
|
|
59373
|
+
getTieHeight(startX, startY, endX, endY) {
|
|
59374
|
+
if (this.isLeftHandTap) {
|
|
59375
|
+
return this.renderer.smuflMetrics.tieHeight;
|
|
59376
|
+
}
|
|
59377
|
+
return super.getTieHeight(startX, startY, endX, endY);
|
|
59378
|
+
}
|
|
59379
|
+
calculateTieDirection() {
|
|
59380
|
+
// invert direction (if stems go up, ties go down to not cross them)
|
|
59381
|
+
switch (this.lookupStartBeatRenderer().getBeatDirection(this.startNote.beat)) {
|
|
59382
|
+
case BeamDirection.Up:
|
|
59383
|
+
return BeamDirection.Down;
|
|
59384
|
+
default:
|
|
59385
|
+
return BeamDirection.Up;
|
|
59386
|
+
}
|
|
59387
|
+
}
|
|
59388
|
+
calculateStartX() {
|
|
59389
|
+
const startNoteRenderer = this.lookupStartBeatRenderer();
|
|
59390
|
+
if (this.isLeftHandTap) {
|
|
59391
|
+
return this.calculateEndX() - startNoteRenderer.smuflMetrics.leftHandTabTieWidth;
|
|
59392
|
+
}
|
|
59393
|
+
return startNoteRenderer.x + startNoteRenderer.getNoteX(this.startNote, this.getStartNotePosition());
|
|
59394
|
+
}
|
|
59395
|
+
getStartNotePosition() {
|
|
59396
|
+
return NoteXPosition.Center;
|
|
59397
|
+
}
|
|
59398
|
+
calculateStartY() {
|
|
59399
|
+
const startNoteRenderer = this.lookupStartBeatRenderer();
|
|
59400
|
+
if (this.isLeftHandTap) {
|
|
59401
|
+
return startNoteRenderer.y + startNoteRenderer.getNoteY(this.startNote, NoteYPosition.Center);
|
|
59402
|
+
}
|
|
59403
|
+
switch (this.tieDirection) {
|
|
59404
|
+
case BeamDirection.Up:
|
|
59405
|
+
return startNoteRenderer.y + startNoteRenderer.getNoteY(this.startNote, NoteYPosition.Top);
|
|
59406
|
+
default:
|
|
59407
|
+
return startNoteRenderer.y + startNoteRenderer.getNoteY(this.startNote, NoteYPosition.Bottom);
|
|
59408
|
+
}
|
|
59409
|
+
}
|
|
59410
|
+
calculateEndX() {
|
|
59411
|
+
const endNoteRenderer = this.lookupEndBeatRenderer();
|
|
59412
|
+
if (!endNoteRenderer) {
|
|
59413
|
+
return this.calculateStartY() + this.renderer.smuflMetrics.leftHandTabTieWidth;
|
|
59414
|
+
}
|
|
59415
|
+
if (this.isLeftHandTap) {
|
|
59416
|
+
return endNoteRenderer.x + endNoteRenderer.getNoteX(this.endNote, NoteXPosition.Left);
|
|
59417
|
+
}
|
|
59418
|
+
return endNoteRenderer.x + endNoteRenderer.getNoteX(this.endNote, NoteXPosition.Center);
|
|
59419
|
+
}
|
|
59420
|
+
getEndNotePosition() {
|
|
59421
|
+
return NoteXPosition.Center;
|
|
59422
|
+
}
|
|
59423
|
+
caclculateEndY() {
|
|
59424
|
+
const endNoteRenderer = this.lookupEndBeatRenderer();
|
|
59425
|
+
if (!endNoteRenderer) {
|
|
59426
|
+
return this.calculateStartY();
|
|
59427
|
+
}
|
|
59428
|
+
if (this.isLeftHandTap) {
|
|
59429
|
+
return endNoteRenderer.y + endNoteRenderer.getNoteY(this.endNote, NoteYPosition.Center);
|
|
59430
|
+
}
|
|
59431
|
+
switch (this.tieDirection) {
|
|
59432
|
+
case BeamDirection.Up:
|
|
59433
|
+
return endNoteRenderer.y + endNoteRenderer.getNoteY(this.endNote, NoteYPosition.Top);
|
|
59434
|
+
default:
|
|
59435
|
+
return endNoteRenderer.y + endNoteRenderer.getNoteY(this.endNote, NoteYPosition.Bottom);
|
|
59436
|
+
}
|
|
59437
|
+
}
|
|
59438
|
+
lookupEndBeatRenderer() {
|
|
59439
|
+
if (!this.endNoteRenderer) {
|
|
59440
|
+
this.endNoteRenderer = this.renderer.scoreRenderer.layout.getRendererForBar(this.renderer.staff.staffId, this.endNote.beat.voice.bar);
|
|
59441
|
+
}
|
|
59442
|
+
return this.endNoteRenderer;
|
|
59443
|
+
}
|
|
59444
|
+
lookupStartBeatRenderer() {
|
|
59445
|
+
if (!this.startNoteRenderer) {
|
|
59446
|
+
this.startNoteRenderer = this.renderer.scoreRenderer.layout.getRendererForBar(this.renderer.staff.staffId, this.startNote.beat.voice.bar);
|
|
59447
|
+
}
|
|
59448
|
+
return this.startNoteRenderer;
|
|
59449
|
+
}
|
|
59450
|
+
shouldDrawBendSlur() {
|
|
59451
|
+
return false;
|
|
59452
|
+
}
|
|
59453
|
+
}
|
|
59454
|
+
/**
|
|
59455
|
+
* A tie glyph for continued multi-system ties/slurs
|
|
59456
|
+
* @internal
|
|
59457
|
+
*/
|
|
59458
|
+
class ContinuationTieGlyph extends TieGlyph {
|
|
59459
|
+
_startTie;
|
|
59460
|
+
constructor(startTie) {
|
|
59461
|
+
super(startTie.slurEffectId, false);
|
|
59462
|
+
this._startTie = startTie;
|
|
59463
|
+
}
|
|
59464
|
+
lookupStartBeatRenderer() {
|
|
59465
|
+
return this.renderer;
|
|
59466
|
+
}
|
|
59467
|
+
lookupEndBeatRenderer() {
|
|
59468
|
+
return this.renderer;
|
|
59469
|
+
}
|
|
59470
|
+
shouldDrawBendSlur() {
|
|
59471
|
+
return false;
|
|
59472
|
+
}
|
|
59473
|
+
calculateTieDirection() {
|
|
59474
|
+
return this._startTie.tieDirection;
|
|
59475
|
+
}
|
|
59476
|
+
calculateStartY() {
|
|
59477
|
+
return this._startTie.calculateMultiSystemSlurY(this.renderer);
|
|
59478
|
+
}
|
|
59479
|
+
caclculateEndY() {
|
|
59480
|
+
return this.calculateStartY();
|
|
59481
|
+
}
|
|
59482
|
+
calculateStartX() {
|
|
59483
|
+
return this.renderer.staff.barRenderers[0].x;
|
|
59484
|
+
}
|
|
59485
|
+
calculateEndX() {
|
|
59486
|
+
const last = this.renderer.staff.barRenderers[this.renderer.staff.barRenderers.length - 1];
|
|
59487
|
+
return last.x + last.width;
|
|
59488
|
+
}
|
|
59489
|
+
}
|
|
59490
|
+
|
|
59060
59491
|
/**
|
|
59061
59492
|
* This glyph acts as container for handling
|
|
59062
59493
|
* multiple voice rendering
|
|
@@ -59527,6 +59958,63 @@ class TuningGlyph extends GlyphGroup {
|
|
|
59527
59958
|
}
|
|
59528
59959
|
}
|
|
59529
59960
|
|
|
59961
|
+
/**
|
|
59962
|
+
* This registry keeps track of which slurs and ties were started and needs completion.
|
|
59963
|
+
* Slurs might span multiple systems, and in such cases we need to create additional
|
|
59964
|
+
* slur/ties in the intermediate and end system.
|
|
59965
|
+
*
|
|
59966
|
+
* @internal
|
|
59967
|
+
*
|
|
59968
|
+
*/
|
|
59969
|
+
class SlurRegistry {
|
|
59970
|
+
_staffLookup = new Map();
|
|
59971
|
+
clear() {
|
|
59972
|
+
this._staffLookup.clear();
|
|
59973
|
+
}
|
|
59974
|
+
startMultiSystemSlur(startGlyph) {
|
|
59975
|
+
const staffId = SlurRegistry._staffId(startGlyph.renderer.staff);
|
|
59976
|
+
let container;
|
|
59977
|
+
if (!this._staffLookup.has(staffId)) {
|
|
59978
|
+
container = {
|
|
59979
|
+
startedSlurs: new Map()
|
|
59980
|
+
};
|
|
59981
|
+
this._staffLookup.set(staffId, container);
|
|
59982
|
+
}
|
|
59983
|
+
else {
|
|
59984
|
+
container = this._staffLookup.get(staffId);
|
|
59985
|
+
}
|
|
59986
|
+
container.startedSlurs.set(startGlyph.slurEffectId, { startGlyph });
|
|
59987
|
+
}
|
|
59988
|
+
static _staffId(staff) {
|
|
59989
|
+
return `${staff.modelStaff.index}.${staff.modelStaff.track.index}.${staff.staffId}`;
|
|
59990
|
+
}
|
|
59991
|
+
completeMultiSystemSlur(endGlyph) {
|
|
59992
|
+
const staffId = SlurRegistry._staffId(endGlyph.renderer.staff);
|
|
59993
|
+
if (!this._staffLookup.has(staffId)) {
|
|
59994
|
+
return undefined;
|
|
59995
|
+
}
|
|
59996
|
+
const container = this._staffLookup.get(staffId);
|
|
59997
|
+
if (container.startedSlurs.has(endGlyph.slurEffectId)) {
|
|
59998
|
+
const info = container.startedSlurs.get(endGlyph.slurEffectId);
|
|
59999
|
+
info.endGlyph = endGlyph;
|
|
60000
|
+
return info.startGlyph;
|
|
60001
|
+
}
|
|
60002
|
+
return undefined;
|
|
60003
|
+
}
|
|
60004
|
+
*getAllContinuations(renderer) {
|
|
60005
|
+
const staffId = SlurRegistry._staffId(renderer.staff);
|
|
60006
|
+
if (!this._staffLookup.has(staffId) || renderer.index > 0) {
|
|
60007
|
+
return;
|
|
60008
|
+
}
|
|
60009
|
+
const container = this._staffLookup.get(staffId);
|
|
60010
|
+
for (const g of container.startedSlurs.values()) {
|
|
60011
|
+
if (g.startGlyph.shouldCreateMultiSystemSlur(renderer)) {
|
|
60012
|
+
yield g.startGlyph;
|
|
60013
|
+
}
|
|
60014
|
+
}
|
|
60015
|
+
}
|
|
60016
|
+
}
|
|
60017
|
+
|
|
59530
60018
|
/**
|
|
59531
60019
|
* A Staff represents a single line within a StaffSystem.
|
|
59532
60020
|
* It stores BarRenderer instances created from a given factory.
|
|
@@ -59648,7 +60136,6 @@ class RenderStaff {
|
|
|
59648
60136
|
this._sharedLayoutData = new Map();
|
|
59649
60137
|
const lastBar = this.barRenderers[this.barRenderers.length - 1];
|
|
59650
60138
|
this.barRenderers.splice(this.barRenderers.length - 1, 1);
|
|
59651
|
-
this.system.layout.unregisterBarRenderer(this.staffId, lastBar);
|
|
59652
60139
|
this.topOverflow = 0;
|
|
59653
60140
|
this.bottomOverflow = 0;
|
|
59654
60141
|
for (const r of this.barRenderers) {
|
|
@@ -59741,23 +60228,23 @@ class RenderStaff {
|
|
|
59741
60228
|
// changes in the overflows
|
|
59742
60229
|
let needsSecondPass = false;
|
|
59743
60230
|
let topOverflow = this.topOverflow;
|
|
59744
|
-
for (
|
|
59745
|
-
this.
|
|
59746
|
-
if (
|
|
60231
|
+
for (const renderer of this.barRenderers) {
|
|
60232
|
+
renderer.registerMultiSystemSlurs(this.system.layout.slurRegistry.getAllContinuations(renderer));
|
|
60233
|
+
if (renderer.finalizeRenderer()) {
|
|
59747
60234
|
needsSecondPass = true;
|
|
59748
60235
|
}
|
|
59749
|
-
this.height = Math.max(this.height,
|
|
60236
|
+
this.height = Math.max(this.height, renderer.height);
|
|
59750
60237
|
}
|
|
59751
60238
|
// 2nd pass: move renderers to correct position respecting the new overflows
|
|
59752
60239
|
if (needsSecondPass) {
|
|
59753
60240
|
topOverflow = this.topOverflow;
|
|
59754
60241
|
// shift all the renderers to the new position to match required spacing
|
|
59755
|
-
for (
|
|
59756
|
-
|
|
60242
|
+
for (const renderer of this.barRenderers) {
|
|
60243
|
+
renderer.y = this.topPadding + topOverflow;
|
|
59757
60244
|
}
|
|
59758
60245
|
// finalize again (to align ties)
|
|
59759
|
-
for (
|
|
59760
|
-
|
|
60246
|
+
for (const renderer of this.barRenderers) {
|
|
60247
|
+
renderer.finalizeRenderer();
|
|
59761
60248
|
}
|
|
59762
60249
|
}
|
|
59763
60250
|
if (this.height > 0) {
|
|
@@ -60363,6 +60850,7 @@ class StaffSystem {
|
|
|
60363
60850
|
if (newBarDisplayScale > barDisplayScale) {
|
|
60364
60851
|
barDisplayScale = newBarDisplayScale;
|
|
60365
60852
|
}
|
|
60853
|
+
lastBar.afterReverted();
|
|
60366
60854
|
}
|
|
60367
60855
|
this.width -= width;
|
|
60368
60856
|
this.computedWidth -= width;
|
|
@@ -60882,12 +61370,16 @@ class ScoreLayout {
|
|
|
60882
61370
|
constructor(renderer) {
|
|
60883
61371
|
this.renderer = renderer;
|
|
60884
61372
|
}
|
|
61373
|
+
slurRegistry = new SlurRegistry();
|
|
60885
61374
|
resize() {
|
|
60886
61375
|
this._lazyPartials.clear();
|
|
61376
|
+
this.slurRegistry.clear();
|
|
60887
61377
|
this.doResize();
|
|
60888
61378
|
}
|
|
60889
61379
|
layoutAndRender() {
|
|
60890
61380
|
this._lazyPartials.clear();
|
|
61381
|
+
this.slurRegistry.clear();
|
|
61382
|
+
this._barRendererLookup.clear();
|
|
60891
61383
|
this.profile = Environment.staveProfiles.get(this.renderer.settings.display.staveProfile);
|
|
60892
61384
|
const score = this.renderer.score;
|
|
60893
61385
|
this.firstBarIndex = ModelUtils.computeFirstDisplayedBarIndex(score, this.renderer.settings);
|
|
@@ -61156,17 +61648,6 @@ class ScoreLayout {
|
|
|
61156
61648
|
}
|
|
61157
61649
|
}
|
|
61158
61650
|
}
|
|
61159
|
-
unregisterBarRenderer(key, renderer) {
|
|
61160
|
-
if (this._barRendererLookup.has(key)) {
|
|
61161
|
-
const lookup = this._barRendererLookup.get(key);
|
|
61162
|
-
lookup.delete(renderer.bar.id);
|
|
61163
|
-
if (renderer.additionalMultiRestBars) {
|
|
61164
|
-
for (const b of renderer.additionalMultiRestBars) {
|
|
61165
|
-
lookup.delete(b.id);
|
|
61166
|
-
}
|
|
61167
|
-
}
|
|
61168
|
-
}
|
|
61169
|
-
}
|
|
61170
61651
|
getRendererForBar(key, bar) {
|
|
61171
61652
|
const barRendererId = bar.id;
|
|
61172
61653
|
if (this._barRendererLookup.has(key) && this._barRendererLookup.get(key).has(barRendererId)) {
|
|
@@ -62155,6 +62636,7 @@ class BarRendererBase {
|
|
|
62155
62636
|
_voiceContainers = new Map();
|
|
62156
62637
|
_postBeatGlyphs = new LeftToRightLayoutingGlyphGroup();
|
|
62157
62638
|
_ties = [];
|
|
62639
|
+
_multiSystemSlurs;
|
|
62158
62640
|
topEffects;
|
|
62159
62641
|
bottomEffects;
|
|
62160
62642
|
get nextRenderer() {
|
|
@@ -62307,6 +62789,11 @@ class BarRendererBase {
|
|
|
62307
62789
|
}
|
|
62308
62790
|
}
|
|
62309
62791
|
_appliedLayoutingInfo = 0;
|
|
62792
|
+
afterReverted() {
|
|
62793
|
+
this.staff = undefined;
|
|
62794
|
+
this.registerMultiSystemSlurs(undefined);
|
|
62795
|
+
this.isFinalized = false;
|
|
62796
|
+
}
|
|
62310
62797
|
afterStaffBarReverted() {
|
|
62311
62798
|
this.topEffects.afterStaffBarReverted();
|
|
62312
62799
|
this.bottomEffects.afterStaffBarReverted();
|
|
@@ -62352,13 +62839,26 @@ class BarRendererBase {
|
|
|
62352
62839
|
return true;
|
|
62353
62840
|
}
|
|
62354
62841
|
isFinalized = false;
|
|
62355
|
-
|
|
62356
|
-
|
|
62842
|
+
registerMultiSystemSlurs(startedTies) {
|
|
62843
|
+
if (!startedTies) {
|
|
62844
|
+
this._multiSystemSlurs = undefined;
|
|
62845
|
+
return;
|
|
62846
|
+
}
|
|
62847
|
+
let ties = undefined;
|
|
62848
|
+
for (const g of startedTies) {
|
|
62849
|
+
const continuation = new ContinuationTieGlyph(g);
|
|
62850
|
+
continuation.renderer = this;
|
|
62851
|
+
continuation.tieDirection = g.tieDirection;
|
|
62852
|
+
if (!ties) {
|
|
62853
|
+
ties = [];
|
|
62854
|
+
}
|
|
62855
|
+
ties.push(continuation);
|
|
62856
|
+
}
|
|
62857
|
+
this._multiSystemSlurs = ties;
|
|
62858
|
+
}
|
|
62859
|
+
_finalizeTies(ties, barTop, barBottom) {
|
|
62357
62860
|
let didChangeOverflows = false;
|
|
62358
|
-
|
|
62359
|
-
const barTop = this.y;
|
|
62360
|
-
const barBottom = this.y + this.height;
|
|
62361
|
-
for (const t of this._ties) {
|
|
62861
|
+
for (const t of ties) {
|
|
62362
62862
|
const tie = t;
|
|
62363
62863
|
tie.doLayout();
|
|
62364
62864
|
if (t.checkForOverflow) {
|
|
@@ -62379,6 +62879,21 @@ class BarRendererBase {
|
|
|
62379
62879
|
}
|
|
62380
62880
|
}
|
|
62381
62881
|
}
|
|
62882
|
+
return didChangeOverflows;
|
|
62883
|
+
}
|
|
62884
|
+
finalizeRenderer() {
|
|
62885
|
+
this.isFinalized = true;
|
|
62886
|
+
let didChangeOverflows = false;
|
|
62887
|
+
// allow spacing to be used for tie overflows
|
|
62888
|
+
const barTop = this.y;
|
|
62889
|
+
const barBottom = this.y + this.height;
|
|
62890
|
+
if (this._finalizeTies(this._ties, barTop, barBottom)) {
|
|
62891
|
+
didChangeOverflows = true;
|
|
62892
|
+
}
|
|
62893
|
+
const multiSystemSlurs = this._multiSystemSlurs;
|
|
62894
|
+
if (multiSystemSlurs && this._finalizeTies(multiSystemSlurs, barTop, barBottom)) {
|
|
62895
|
+
didChangeOverflows = true;
|
|
62896
|
+
}
|
|
62382
62897
|
const topHeightChanged = this.topEffects.finalizeEffects();
|
|
62383
62898
|
const bottomHeightChanged = this.bottomEffects.finalizeEffects();
|
|
62384
62899
|
if (topHeightChanged || bottomHeightChanged) {
|
|
@@ -62559,6 +63074,16 @@ class BarRendererBase {
|
|
|
62559
63074
|
}
|
|
62560
63075
|
canvas.color = this.resources.mainGlyphColor;
|
|
62561
63076
|
this._postBeatGlyphs.paint(cx + this.x, cy + this.y, canvas);
|
|
63077
|
+
this._paintMultiSystemSlurs(cx, cy, canvas);
|
|
63078
|
+
}
|
|
63079
|
+
_paintMultiSystemSlurs(cx, cy, canvas) {
|
|
63080
|
+
const multiSystemSlurs = this._multiSystemSlurs;
|
|
63081
|
+
if (!multiSystemSlurs) {
|
|
63082
|
+
return;
|
|
63083
|
+
}
|
|
63084
|
+
for (const slur of multiSystemSlurs) {
|
|
63085
|
+
slur.paint(cx, cy, canvas);
|
|
63086
|
+
}
|
|
62562
63087
|
}
|
|
62563
63088
|
paintBackground(cx, cy, canvas) {
|
|
62564
63089
|
this.layoutingInfo.paint(cx + this.x + this._preBeatGlyphs.x + this._preBeatGlyphs.width, cy + this.y + this.height, canvas);
|
|
@@ -64637,6 +65162,13 @@ class PageViewLayout extends ScoreLayout {
|
|
|
64637
65162
|
}
|
|
64638
65163
|
}
|
|
64639
65164
|
else {
|
|
65165
|
+
// clear out staves during re-layout, this info is outdated during
|
|
65166
|
+
// re-layout of the bars
|
|
65167
|
+
for (const r of this._allMasterBarRenderers) {
|
|
65168
|
+
for (const b of r.renderers) {
|
|
65169
|
+
b.afterReverted();
|
|
65170
|
+
}
|
|
65171
|
+
}
|
|
64640
65172
|
this._systems = [];
|
|
64641
65173
|
let currentIndex = 0;
|
|
64642
65174
|
const maxWidth = this._maxWidth;
|
|
@@ -65098,7 +65630,7 @@ class BarLineGlyph extends LeftToRightLayoutingGlyphGroup {
|
|
|
65098
65630
|
// as during layout things are still moving
|
|
65099
65631
|
let actualLineHeight = this.height;
|
|
65100
65632
|
const thisStaff = renderer.staff;
|
|
65101
|
-
const allStaves =
|
|
65633
|
+
const allStaves = thisStaff.system.allStaves;
|
|
65102
65634
|
let isExtended = false;
|
|
65103
65635
|
if (this._extendToNextStaff && thisStaff.index < allStaves.length - 1) {
|
|
65104
65636
|
const nextStaff = allStaves[thisStaff.index + 1];
|
|
@@ -65280,7 +65812,7 @@ class LineBarRenderer extends BarRendererBase {
|
|
|
65280
65812
|
}
|
|
65281
65813
|
// during system fitting it can happen that we have fraction widths
|
|
65282
65814
|
// but to have lines until the full end-pixel we round up.
|
|
65283
|
-
// this way we avoid holes,
|
|
65815
|
+
// this way we avoid holes,
|
|
65284
65816
|
const lineWidth = this.width;
|
|
65285
65817
|
// we want the lines to be exactly virtually aligned with the respective Y-position
|
|
65286
65818
|
// for note heads to align correctly
|
|
@@ -66046,375 +66578,23 @@ class LineBarRenderer extends BarRendererBase {
|
|
|
66046
66578
|
/**
|
|
66047
66579
|
* @internal
|
|
66048
66580
|
*/
|
|
66049
|
-
class
|
|
66050
|
-
startBeat;
|
|
66051
|
-
endBeat;
|
|
66052
|
-
yOffset = 0;
|
|
66053
|
-
forEnd;
|
|
66054
|
-
startNoteRenderer = null;
|
|
66055
|
-
endNoteRenderer = null;
|
|
66056
|
-
tieDirection = BeamDirection.Up;
|
|
66057
|
-
constructor(startBeat, endBeat, forEnd) {
|
|
66058
|
-
super(0, 0);
|
|
66059
|
-
this.startBeat = startBeat;
|
|
66060
|
-
this.endBeat = endBeat;
|
|
66061
|
-
this.forEnd = forEnd;
|
|
66062
|
-
}
|
|
66063
|
-
_startX = 0;
|
|
66064
|
-
_startY = 0;
|
|
66065
|
-
_endX = 0;
|
|
66066
|
-
_endY = 0;
|
|
66067
|
-
_tieHeight = 0;
|
|
66068
|
-
_shouldDraw = false;
|
|
66069
|
-
_boundingBox;
|
|
66070
|
-
get checkForOverflow() {
|
|
66071
|
-
return this._boundingBox !== undefined;
|
|
66072
|
-
}
|
|
66073
|
-
getBoundingBoxTop() {
|
|
66074
|
-
if (this._boundingBox) {
|
|
66075
|
-
return this._boundingBox.y;
|
|
66076
|
-
}
|
|
66077
|
-
return this._startY;
|
|
66078
|
-
}
|
|
66079
|
-
getBoundingBoxBottom() {
|
|
66080
|
-
if (this._boundingBox) {
|
|
66081
|
-
return this._boundingBox.y + this._boundingBox.h;
|
|
66082
|
-
}
|
|
66083
|
-
return this._startY;
|
|
66084
|
-
}
|
|
66085
|
-
doLayout() {
|
|
66086
|
-
this.width = 0;
|
|
66087
|
-
// TODO fix nullability of start/end beat,
|
|
66088
|
-
if (!this.endBeat) {
|
|
66089
|
-
this._shouldDraw = false;
|
|
66090
|
-
return;
|
|
66091
|
-
}
|
|
66092
|
-
const startNoteRenderer = this.renderer.scoreRenderer.layout.getRendererForBar(this.renderer.staff.staffId, this.startBeat.voice.bar);
|
|
66093
|
-
this.startNoteRenderer = startNoteRenderer;
|
|
66094
|
-
const endNoteRenderer = this.renderer.scoreRenderer.layout.getRendererForBar(this.renderer.staff.staffId, this.endBeat.voice.bar);
|
|
66095
|
-
this.endNoteRenderer = endNoteRenderer;
|
|
66096
|
-
this._startX = 0;
|
|
66097
|
-
this._endX = 0;
|
|
66098
|
-
this._startY = 0;
|
|
66099
|
-
this._endY = 0;
|
|
66100
|
-
this.height = 0;
|
|
66101
|
-
this._shouldDraw = false;
|
|
66102
|
-
// if we are on the tie start, we check if we
|
|
66103
|
-
// either can draw till the end note, or we just can draw till the bar end
|
|
66104
|
-
this.tieDirection = !startNoteRenderer
|
|
66105
|
-
? this.getBeamDirection(this.endBeat, endNoteRenderer)
|
|
66106
|
-
: this.getBeamDirection(this.startBeat, startNoteRenderer);
|
|
66107
|
-
if (!this.forEnd && startNoteRenderer) {
|
|
66108
|
-
// line break or bar break
|
|
66109
|
-
if (startNoteRenderer !== endNoteRenderer) {
|
|
66110
|
-
this._startX = startNoteRenderer.x + this.getStartX();
|
|
66111
|
-
this._startY = startNoteRenderer.y + this.getStartY() + this.yOffset;
|
|
66112
|
-
// line break: to bar end
|
|
66113
|
-
if (!endNoteRenderer || startNoteRenderer.staff !== endNoteRenderer.staff) {
|
|
66114
|
-
this._endX = startNoteRenderer.x + startNoteRenderer.width;
|
|
66115
|
-
this._endY = this._startY;
|
|
66116
|
-
}
|
|
66117
|
-
else {
|
|
66118
|
-
this._endX = endNoteRenderer.x + this.getEndX();
|
|
66119
|
-
this._endY = endNoteRenderer.y + this.getEndY() + this.yOffset;
|
|
66120
|
-
}
|
|
66121
|
-
}
|
|
66122
|
-
else {
|
|
66123
|
-
this._startX = startNoteRenderer.x + this.getStartX();
|
|
66124
|
-
this._endX = endNoteRenderer.x + this.getEndX();
|
|
66125
|
-
this._startY = startNoteRenderer.y + this.getStartY() + this.yOffset;
|
|
66126
|
-
this._endY = endNoteRenderer.y + this.getEndY() + this.yOffset;
|
|
66127
|
-
}
|
|
66128
|
-
this._shouldDraw = true;
|
|
66129
|
-
}
|
|
66130
|
-
else if (!startNoteRenderer || startNoteRenderer.staff !== endNoteRenderer.staff) {
|
|
66131
|
-
this._startX = endNoteRenderer.x;
|
|
66132
|
-
this._endX = endNoteRenderer.x + this.getEndX();
|
|
66133
|
-
this._startY = endNoteRenderer.y + this.getEndY() + this.yOffset;
|
|
66134
|
-
this._endY = this._startY;
|
|
66135
|
-
this._shouldDraw = true;
|
|
66136
|
-
}
|
|
66137
|
-
this._boundingBox = undefined;
|
|
66138
|
-
if (this._shouldDraw) {
|
|
66139
|
-
this.y = Math.min(this._startY, this._endY);
|
|
66140
|
-
if (this.shouldDrawBendSlur()) {
|
|
66141
|
-
this._tieHeight = 0; // TODO: Bend slur height to be considered?
|
|
66142
|
-
}
|
|
66143
|
-
else {
|
|
66144
|
-
this._tieHeight = this.getTieHeight(this._startX, this._startY, this._endX, this._endY);
|
|
66145
|
-
const tieBoundingBox = TieGlyph.calculateActualTieHeight(1, this._startX, this._startY, this._endX, this._endY, this.tieDirection === BeamDirection.Down, this._tieHeight, this.renderer.smuflMetrics.tieMidpointThickness);
|
|
66146
|
-
this._boundingBox = tieBoundingBox;
|
|
66147
|
-
this.height = tieBoundingBox.h;
|
|
66148
|
-
if (this.tieDirection === BeamDirection.Up) {
|
|
66149
|
-
// the tie might go above `this.y` due to its shape
|
|
66150
|
-
// here we calculate how much this is so we can consider the
|
|
66151
|
-
// respective overflow
|
|
66152
|
-
const overlap = this.y - tieBoundingBox.y;
|
|
66153
|
-
if (overlap > 0) {
|
|
66154
|
-
this.y -= overlap;
|
|
66155
|
-
}
|
|
66156
|
-
}
|
|
66157
|
-
}
|
|
66158
|
-
}
|
|
66159
|
-
}
|
|
66160
|
-
paint(cx, cy, canvas) {
|
|
66161
|
-
if (this._shouldDraw) {
|
|
66162
|
-
if (this.shouldDrawBendSlur()) {
|
|
66163
|
-
TieGlyph.drawBendSlur(canvas, cx + this._startX, cy + this._startY, cx + this._endX, cy + this._endY, this.tieDirection === BeamDirection.Down, 1, this.renderer.smuflMetrics.tieHeight);
|
|
66164
|
-
}
|
|
66165
|
-
else {
|
|
66166
|
-
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);
|
|
66167
|
-
}
|
|
66168
|
-
}
|
|
66169
|
-
}
|
|
66170
|
-
shouldDrawBendSlur() {
|
|
66171
|
-
return false;
|
|
66172
|
-
}
|
|
66173
|
-
getTieHeight(_startX, _startY, _endX, _endY) {
|
|
66174
|
-
return this.renderer.smuflMetrics.tieHeight;
|
|
66175
|
-
}
|
|
66176
|
-
getBeamDirection(_beat, _noteRenderer) {
|
|
66177
|
-
return BeamDirection.Down;
|
|
66178
|
-
}
|
|
66179
|
-
getStartY() {
|
|
66180
|
-
return 0;
|
|
66181
|
-
}
|
|
66182
|
-
getEndY() {
|
|
66183
|
-
return 0;
|
|
66184
|
-
}
|
|
66185
|
-
getStartX() {
|
|
66186
|
-
return 0;
|
|
66187
|
-
}
|
|
66188
|
-
getEndX() {
|
|
66189
|
-
return 0;
|
|
66190
|
-
}
|
|
66191
|
-
static calculateActualTieHeight(scale, x1, y1, x2, y2, down, offset, size) {
|
|
66192
|
-
const cp = TieGlyph._computeBezierControlPoints(scale, x1, y1, x2, y2, down, offset, size);
|
|
66193
|
-
// For a musical tie/slur, the extrema occur predictably near the midpoint
|
|
66194
|
-
// Evaluate at midpoint (t=0.5) and check endpoints
|
|
66195
|
-
const p0x = cp[0];
|
|
66196
|
-
const p0y = cp[1];
|
|
66197
|
-
const c1x = cp[2];
|
|
66198
|
-
const c1y = cp[3];
|
|
66199
|
-
const c2x = cp[4];
|
|
66200
|
-
const c2y = cp[5];
|
|
66201
|
-
const p1x = cp[6];
|
|
66202
|
-
const p1y = cp[7];
|
|
66203
|
-
// Evaluate at t=0.5 for midpoint
|
|
66204
|
-
const midX = 0.125 * p0x + 0.375 * c1x + 0.375 * c2x + 0.125 * p1x;
|
|
66205
|
-
const midY = 0.125 * p0y + 0.375 * c1y + 0.375 * c2y + 0.125 * p1y;
|
|
66206
|
-
// Bounds are simply min/max of start, end, and midpoint
|
|
66207
|
-
const xMin = Math.min(p0x, p1x, midX);
|
|
66208
|
-
const xMax = Math.max(p0x, p1x, midX);
|
|
66209
|
-
let yMin = Math.min(p0y, p1y, midY);
|
|
66210
|
-
let yMax = Math.max(p0y, p1y, midY);
|
|
66211
|
-
// Account for thickness of the tie/slur
|
|
66212
|
-
if (down) {
|
|
66213
|
-
yMax += size;
|
|
66214
|
-
}
|
|
66215
|
-
else {
|
|
66216
|
-
yMin -= size;
|
|
66217
|
-
}
|
|
66218
|
-
const b = new Bounds();
|
|
66219
|
-
b.x = xMin;
|
|
66220
|
-
b.y = yMin;
|
|
66221
|
-
b.w = xMax - xMin;
|
|
66222
|
-
b.h = yMax - yMin;
|
|
66223
|
-
return b;
|
|
66224
|
-
}
|
|
66225
|
-
static _computeBezierControlPoints(scale, x1, y1, x2, y2, down, offset, size) {
|
|
66226
|
-
if (x1 === x2 && y1 === y2) {
|
|
66227
|
-
return [];
|
|
66228
|
-
}
|
|
66229
|
-
// ensure endX > startX
|
|
66230
|
-
if (x2 < x1) {
|
|
66231
|
-
let t = x1;
|
|
66232
|
-
x1 = x2;
|
|
66233
|
-
x2 = t;
|
|
66234
|
-
t = y1;
|
|
66235
|
-
y1 = y2;
|
|
66236
|
-
y2 = t;
|
|
66237
|
-
}
|
|
66238
|
-
//
|
|
66239
|
-
// calculate control points
|
|
66240
|
-
//
|
|
66241
|
-
offset *= scale;
|
|
66242
|
-
size *= scale;
|
|
66243
|
-
if (down) {
|
|
66244
|
-
offset *= -1;
|
|
66245
|
-
size *= -1;
|
|
66246
|
-
}
|
|
66247
|
-
if (scale >= 1) {
|
|
66248
|
-
size *= 1.2;
|
|
66249
|
-
}
|
|
66250
|
-
// calculate control points on horizontal axis then rotate:
|
|
66251
|
-
/*
|
|
66252
|
-
cp1x/cpy1 cp2x/cpy2
|
|
66253
|
-
*----------------*
|
|
66254
|
-
/ \
|
|
66255
|
-
/ \
|
|
66256
|
-
x1/y1 * * x2/y2
|
|
66257
|
-
|
|
66258
|
-
cp3 and cp4 are simply with lower height
|
|
66259
|
-
*/
|
|
66260
|
-
const dY = y2 - y1;
|
|
66261
|
-
const dX = x2 - x1;
|
|
66262
|
-
const length = Math.sqrt(dX * dX + dY * dY);
|
|
66263
|
-
let cp1x = x1 + length * 0.25;
|
|
66264
|
-
let cp1y = y1 - offset;
|
|
66265
|
-
let cp2x = x1 + length * 0.75;
|
|
66266
|
-
let cp2y = y1 - offset;
|
|
66267
|
-
let cp3x = x1 + length * 0.75;
|
|
66268
|
-
let cp3y = y1 - offset - size;
|
|
66269
|
-
let cp4x = x1 + length * 0.25;
|
|
66270
|
-
let cp4y = y1 - offset - size;
|
|
66271
|
-
const angle = Math.atan2(dY, dX);
|
|
66272
|
-
[cp1x, cp1y] = TieGlyph._rotate(cp1x, cp1y, x1, y1, angle);
|
|
66273
|
-
[cp2x, cp2y] = TieGlyph._rotate(cp2x, cp2y, x1, y1, angle);
|
|
66274
|
-
[cp3x, cp3y] = TieGlyph._rotate(cp3x, cp3y, x1, y1, angle);
|
|
66275
|
-
[cp4x, cp4y] = TieGlyph._rotate(cp4x, cp4y, x1, y1, angle);
|
|
66276
|
-
return [x1, y1, cp1x, cp1y, cp2x, cp2y, x2, y2, cp3x, cp3y, cp4x, cp4y, x1, y1];
|
|
66277
|
-
}
|
|
66278
|
-
static _rotate(x, y, rotateX, rotateY, angle) {
|
|
66279
|
-
const dx = x - rotateX;
|
|
66280
|
-
const dy = y - rotateY;
|
|
66281
|
-
const rx = dx * Math.cos(angle) - dy * Math.sin(angle);
|
|
66282
|
-
const ry = dx * Math.sin(angle) + dy * Math.cos(angle);
|
|
66283
|
-
return [rotateX + rx, rotateY + ry];
|
|
66284
|
-
}
|
|
66285
|
-
static paintTie(canvas, scale, x1, y1, x2, y2, down /*= false*/, offset /*= 22*/, size /*= 4*/) {
|
|
66286
|
-
const cps = TieGlyph._computeBezierControlPoints(scale, x1, y1, x2, y2, down, offset, size);
|
|
66287
|
-
canvas.beginPath();
|
|
66288
|
-
canvas.moveTo(cps[0], cps[1]);
|
|
66289
|
-
canvas.bezierCurveTo(cps[2], cps[3], cps[4], cps[5], cps[6], cps[7]);
|
|
66290
|
-
canvas.bezierCurveTo(cps[8], cps[9], cps[10], cps[11], cps[12], cps[13]);
|
|
66291
|
-
canvas.closePath();
|
|
66292
|
-
canvas.fill();
|
|
66293
|
-
}
|
|
66294
|
-
static calculateBendSlurTopY(x1, y1, x2, y2, down, scale, bendSlurHeight) {
|
|
66295
|
-
let normalVectorX = y2 - y1;
|
|
66296
|
-
let normalVectorY = x2 - x1;
|
|
66297
|
-
const length = Math.sqrt(normalVectorX * normalVectorX + normalVectorY * normalVectorY);
|
|
66298
|
-
if (down) {
|
|
66299
|
-
normalVectorX *= -1;
|
|
66300
|
-
}
|
|
66301
|
-
else {
|
|
66302
|
-
normalVectorY *= -1;
|
|
66303
|
-
}
|
|
66304
|
-
// make to unit vector
|
|
66305
|
-
normalVectorX /= length;
|
|
66306
|
-
normalVectorY /= length;
|
|
66307
|
-
let offset = bendSlurHeight * scale;
|
|
66308
|
-
if (x2 - x1 < 20) {
|
|
66309
|
-
offset /= 2;
|
|
66310
|
-
}
|
|
66311
|
-
const centerY = (y2 + y1) / 2;
|
|
66312
|
-
const cp1Y = centerY + offset * normalVectorY;
|
|
66313
|
-
return cp1Y;
|
|
66314
|
-
}
|
|
66315
|
-
static drawBendSlur(canvas, x1, y1, x2, y2, down, scale, bendSlurHeight, slurText) {
|
|
66316
|
-
let normalVectorX = y2 - y1;
|
|
66317
|
-
let normalVectorY = x2 - x1;
|
|
66318
|
-
const length = Math.sqrt(normalVectorX * normalVectorX + normalVectorY * normalVectorY);
|
|
66319
|
-
if (down) {
|
|
66320
|
-
normalVectorX *= -1;
|
|
66321
|
-
}
|
|
66322
|
-
else {
|
|
66323
|
-
normalVectorY *= -1;
|
|
66324
|
-
}
|
|
66325
|
-
// make to unit vector
|
|
66326
|
-
normalVectorX /= length;
|
|
66327
|
-
normalVectorY /= length;
|
|
66328
|
-
// center of connection
|
|
66329
|
-
// TODO: should be 1/3
|
|
66330
|
-
const centerX = (x2 + x1) / 2;
|
|
66331
|
-
const centerY = (y2 + y1) / 2;
|
|
66332
|
-
let offset = bendSlurHeight * scale;
|
|
66333
|
-
if (x2 - x1 < 20) {
|
|
66334
|
-
offset /= 2;
|
|
66335
|
-
}
|
|
66336
|
-
const cp1X = centerX + offset * normalVectorX;
|
|
66337
|
-
const cp1Y = centerY + offset * normalVectorY;
|
|
66338
|
-
canvas.beginPath();
|
|
66339
|
-
canvas.moveTo(x1, y1);
|
|
66340
|
-
canvas.lineTo(cp1X, cp1Y);
|
|
66341
|
-
canvas.lineTo(x2, y2);
|
|
66342
|
-
canvas.stroke();
|
|
66343
|
-
if (slurText) {
|
|
66344
|
-
const w = canvas.measureText(slurText).width;
|
|
66345
|
-
const textOffset = down ? 0 : -canvas.font.size;
|
|
66346
|
-
canvas.fillText(slurText, cp1X - w / 2, cp1Y + textOffset);
|
|
66347
|
-
}
|
|
66348
|
-
}
|
|
66349
|
-
}
|
|
66350
|
-
|
|
66351
|
-
/**
|
|
66352
|
-
* @internal
|
|
66353
|
-
*/
|
|
66354
|
-
class NumberedTieGlyph extends TieGlyph {
|
|
66355
|
-
startNote;
|
|
66356
|
-
endNote;
|
|
66357
|
-
constructor(startNote, endNote, forEnd = false) {
|
|
66358
|
-
super(!startNote ? null : startNote.beat, !endNote ? null : endNote.beat, forEnd);
|
|
66359
|
-
this.startNote = startNote;
|
|
66360
|
-
this.endNote = endNote;
|
|
66361
|
-
}
|
|
66362
|
-
get _isLeftHandTap() {
|
|
66363
|
-
return this.startNote === this.endNote;
|
|
66364
|
-
}
|
|
66581
|
+
class NumberedTieGlyph extends NoteTieGlyph {
|
|
66365
66582
|
shouldDrawBendSlur() {
|
|
66366
66583
|
return (this.renderer.settings.notation.extendBendArrowsOnTiedNotes &&
|
|
66367
66584
|
!!this.startNote.bendOrigin &&
|
|
66368
66585
|
this.startNote.isTieOrigin);
|
|
66369
66586
|
}
|
|
66370
|
-
|
|
66371
|
-
super.doLayout();
|
|
66372
|
-
}
|
|
66373
|
-
getBeamDirection(_beat, _noteRenderer) {
|
|
66587
|
+
calculateTieDirection() {
|
|
66374
66588
|
return BeamDirection.Up;
|
|
66375
66589
|
}
|
|
66376
|
-
getStartY() {
|
|
66377
|
-
return this.startNoteRenderer.getNoteY(this.startNote, NoteYPosition.Top);
|
|
66378
|
-
}
|
|
66379
|
-
getEndY() {
|
|
66380
|
-
return this.getStartY();
|
|
66381
|
-
}
|
|
66382
|
-
getStartX() {
|
|
66383
|
-
if (this._isLeftHandTap) {
|
|
66384
|
-
return this.getEndX() - this.startNoteRenderer.smuflMetrics.leftHandTabTieWidth;
|
|
66385
|
-
}
|
|
66386
|
-
return this.startNoteRenderer.getNoteX(this.startNote, NoteXPosition.Center);
|
|
66387
|
-
}
|
|
66388
|
-
getEndX() {
|
|
66389
|
-
if (this._isLeftHandTap) {
|
|
66390
|
-
return this.endNoteRenderer.getNoteX(this.endNote, NoteXPosition.Left);
|
|
66391
|
-
}
|
|
66392
|
-
return this.endNoteRenderer.getNoteX(this.endNote, NoteXPosition.Center);
|
|
66393
|
-
}
|
|
66394
66590
|
}
|
|
66395
66591
|
|
|
66396
66592
|
/**
|
|
66397
66593
|
* @internal
|
|
66398
66594
|
*/
|
|
66399
|
-
class TabTieGlyph extends
|
|
66400
|
-
|
|
66401
|
-
|
|
66402
|
-
constructor(startNote, endNote, forEnd = false) {
|
|
66403
|
-
super(startNote.beat, endNote.beat, forEnd);
|
|
66404
|
-
this.startNote = startNote;
|
|
66405
|
-
this.endNote = endNote;
|
|
66406
|
-
}
|
|
66407
|
-
get _isLeftHandTap() {
|
|
66408
|
-
return this.startNote === this.endNote;
|
|
66409
|
-
}
|
|
66410
|
-
getTieHeight(startX, startY, endX, endY) {
|
|
66411
|
-
if (this._isLeftHandTap) {
|
|
66412
|
-
return this.startNoteRenderer.smuflMetrics.tieHeight;
|
|
66413
|
-
}
|
|
66414
|
-
return super.getTieHeight(startX, startY, endX, endY);
|
|
66415
|
-
}
|
|
66416
|
-
getBeamDirection(_beat, _noteRenderer) {
|
|
66417
|
-
if (this._isLeftHandTap) {
|
|
66595
|
+
class TabTieGlyph extends NoteTieGlyph {
|
|
66596
|
+
calculateTieDirection() {
|
|
66597
|
+
if (this.isLeftHandTap) {
|
|
66418
66598
|
return BeamDirection.Up;
|
|
66419
66599
|
}
|
|
66420
66600
|
return TabTieGlyph.getBeamDirectionForNote(this.startNote);
|
|
@@ -66422,54 +66602,25 @@ class TabTieGlyph extends TieGlyph {
|
|
|
66422
66602
|
static getBeamDirectionForNote(note) {
|
|
66423
66603
|
return note.string > 3 ? BeamDirection.Up : BeamDirection.Down;
|
|
66424
66604
|
}
|
|
66425
|
-
getStartY() {
|
|
66426
|
-
if (this._isLeftHandTap) {
|
|
66427
|
-
return this.startNoteRenderer.getNoteY(this.startNote, NoteYPosition.Center);
|
|
66428
|
-
}
|
|
66429
|
-
if (this.tieDirection === BeamDirection.Up) {
|
|
66430
|
-
return this.startNoteRenderer.getNoteY(this.startNote, NoteYPosition.Top);
|
|
66431
|
-
}
|
|
66432
|
-
return this.startNoteRenderer.getNoteY(this.startNote, NoteYPosition.Bottom);
|
|
66433
|
-
}
|
|
66434
|
-
getEndY() {
|
|
66435
|
-
return this.getStartY();
|
|
66436
|
-
}
|
|
66437
|
-
getStartX() {
|
|
66438
|
-
if (this._isLeftHandTap) {
|
|
66439
|
-
return this.getEndX() - this.renderer.smuflMetrics.leftHandTabTieWidth;
|
|
66440
|
-
}
|
|
66441
|
-
return this.startNoteRenderer.getNoteX(this.startNote, NoteXPosition.Center);
|
|
66442
|
-
}
|
|
66443
|
-
getEndX() {
|
|
66444
|
-
if (this._isLeftHandTap) {
|
|
66445
|
-
return this.endNoteRenderer.getNoteX(this.endNote, NoteXPosition.Left);
|
|
66446
|
-
}
|
|
66447
|
-
return this.endNoteRenderer.getNoteX(this.endNote, NoteXPosition.Center);
|
|
66448
|
-
}
|
|
66449
66605
|
}
|
|
66450
66606
|
|
|
66451
66607
|
/**
|
|
66452
66608
|
* @internal
|
|
66453
66609
|
*/
|
|
66454
|
-
class
|
|
66455
|
-
_direction;
|
|
66610
|
+
class TabSlurGlyph extends TabTieGlyph {
|
|
66456
66611
|
_forSlide;
|
|
66457
|
-
constructor(startNote, endNote, forSlide, forEnd
|
|
66458
|
-
super(startNote, endNote, forEnd);
|
|
66459
|
-
this._direction = BeamDirection.Up;
|
|
66612
|
+
constructor(slurEffectId, startNote, endNote, forSlide, forEnd) {
|
|
66613
|
+
super(slurEffectId, startNote, endNote, forEnd);
|
|
66460
66614
|
this._forSlide = forSlide;
|
|
66461
66615
|
}
|
|
66462
66616
|
getTieHeight(startX, _startY, endX, _endY) {
|
|
66463
|
-
return Math.log(endX - startX + 1) * this.renderer.settings.notation.slurHeight / 2;
|
|
66617
|
+
return (Math.log(endX - startX + 1) * this.renderer.settings.notation.slurHeight) / 2;
|
|
66464
66618
|
}
|
|
66465
66619
|
tryExpand(startNote, endNote, forSlide, forEnd) {
|
|
66466
66620
|
// same type required
|
|
66467
66621
|
if (this._forSlide !== forSlide) {
|
|
66468
66622
|
return false;
|
|
66469
66623
|
}
|
|
66470
|
-
if (this.forEnd !== forEnd) {
|
|
66471
|
-
return false;
|
|
66472
|
-
}
|
|
66473
66624
|
// same start and endbeat
|
|
66474
66625
|
if (this.startNote.beat.id !== startNote.beat.id) {
|
|
66475
66626
|
return false;
|
|
@@ -66477,41 +66628,43 @@ class NumberedSlurGlyph extends TabTieGlyph {
|
|
|
66477
66628
|
if (this.endNote.beat.id !== endNote.beat.id) {
|
|
66478
66629
|
return false;
|
|
66479
66630
|
}
|
|
66631
|
+
const isForEnd = this.renderer === this.lookupEndBeatRenderer();
|
|
66632
|
+
if (isForEnd !== forEnd) {
|
|
66633
|
+
return false;
|
|
66634
|
+
}
|
|
66635
|
+
// same draw direction
|
|
66636
|
+
if (this.tieDirection !== TabTieGlyph.getBeamDirectionForNote(startNote)) {
|
|
66637
|
+
return false;
|
|
66638
|
+
}
|
|
66480
66639
|
// if we can expand, expand in correct direction
|
|
66481
|
-
switch (this.
|
|
66640
|
+
switch (this.tieDirection) {
|
|
66482
66641
|
case BeamDirection.Up:
|
|
66483
66642
|
if (startNote.realValue > this.startNote.realValue) {
|
|
66484
66643
|
this.startNote = startNote;
|
|
66485
|
-
this.startBeat = startNote.beat;
|
|
66486
66644
|
}
|
|
66487
66645
|
if (endNote.realValue > this.endNote.realValue) {
|
|
66488
66646
|
this.endNote = endNote;
|
|
66489
|
-
this.endBeat = endNote.beat;
|
|
66490
66647
|
}
|
|
66491
66648
|
break;
|
|
66492
66649
|
case BeamDirection.Down:
|
|
66493
66650
|
if (startNote.realValue < this.startNote.realValue) {
|
|
66494
66651
|
this.startNote = startNote;
|
|
66495
|
-
this.startBeat = startNote.beat;
|
|
66496
66652
|
}
|
|
66497
66653
|
if (endNote.realValue < this.endNote.realValue) {
|
|
66498
66654
|
this.endNote = endNote;
|
|
66499
|
-
this.endBeat = endNote.beat;
|
|
66500
66655
|
}
|
|
66501
66656
|
break;
|
|
66502
66657
|
}
|
|
66503
66658
|
return true;
|
|
66504
66659
|
}
|
|
66505
|
-
|
|
66506
|
-
|
|
66507
|
-
|
|
66508
|
-
|
|
66509
|
-
|
|
66510
|
-
|
|
66511
|
-
|
|
66512
|
-
|
|
66513
|
-
super.paint(cx, cy, canvas);
|
|
66514
|
-
}
|
|
66660
|
+
}
|
|
66661
|
+
|
|
66662
|
+
/**
|
|
66663
|
+
* @internal
|
|
66664
|
+
*/
|
|
66665
|
+
class NumberedSlurGlyph extends TabSlurGlyph {
|
|
66666
|
+
calculateTieDirection() {
|
|
66667
|
+
return BeamDirection.Up;
|
|
66515
66668
|
}
|
|
66516
66669
|
}
|
|
66517
66670
|
|
|
@@ -66519,23 +66672,31 @@ class NumberedSlurGlyph extends TabTieGlyph {
|
|
|
66519
66672
|
* @internal
|
|
66520
66673
|
*/
|
|
66521
66674
|
class NumberedBeatContainerGlyph extends BeatContainerGlyph {
|
|
66675
|
+
_slurs = new Map();
|
|
66522
66676
|
_effectSlurs = [];
|
|
66677
|
+
doLayout() {
|
|
66678
|
+
this._slurs.clear();
|
|
66679
|
+
this._effectSlurs = [];
|
|
66680
|
+
super.doLayout();
|
|
66681
|
+
}
|
|
66523
66682
|
createTies(n) {
|
|
66524
66683
|
// create a tie if any effect requires it
|
|
66525
66684
|
if (!n.isVisible) {
|
|
66526
66685
|
return;
|
|
66527
66686
|
}
|
|
66528
|
-
if (n.isTieOrigin && n.tieDestination.isVisible) {
|
|
66529
|
-
const tie = new NumberedTieGlyph(n, n.tieDestination, false);
|
|
66687
|
+
if (n.isTieOrigin && n.tieDestination.isVisible && !this._slurs.has('numbered.tie')) {
|
|
66688
|
+
const tie = new NumberedTieGlyph(`numbered.tie.${n.beat.id}`, n, n.tieDestination, false);
|
|
66530
66689
|
this.addTie(tie);
|
|
66690
|
+
this._slurs.set(tie.slurEffectId, tie);
|
|
66531
66691
|
}
|
|
66532
66692
|
if (n.isTieDestination) {
|
|
66533
|
-
const tie = new NumberedTieGlyph(n.tieOrigin, n, true);
|
|
66693
|
+
const tie = new NumberedTieGlyph(`numbered.tie.${n.tieOrigin.beat.id}`, n.tieOrigin, n, true);
|
|
66534
66694
|
this.addTie(tie);
|
|
66535
66695
|
}
|
|
66536
|
-
if (n.isLeftHandTapped && !n.isHammerPullDestination) {
|
|
66537
|
-
const tapSlur = new NumberedTieGlyph(n, n, false);
|
|
66696
|
+
if (n.isLeftHandTapped && !n.isHammerPullDestination && !this._slurs.has(`numbered.tie.leftHandTap.${n.beat.id}`)) {
|
|
66697
|
+
const tapSlur = new NumberedTieGlyph(`numbered.tie.leftHandTap.${n.beat.id}`, n, n, false);
|
|
66538
66698
|
this.addTie(tapSlur);
|
|
66699
|
+
this._slurs.set(tapSlur.slurEffectId, tapSlur);
|
|
66539
66700
|
}
|
|
66540
66701
|
// start effect slur on first beat
|
|
66541
66702
|
if (n.isEffectSlurOrigin && n.effectSlurDestination) {
|
|
@@ -66547,9 +66708,11 @@ class NumberedBeatContainerGlyph extends BeatContainerGlyph {
|
|
|
66547
66708
|
}
|
|
66548
66709
|
}
|
|
66549
66710
|
if (!expanded) {
|
|
66550
|
-
const effectSlur = new NumberedSlurGlyph(n, n.effectSlurDestination, false, false);
|
|
66711
|
+
const effectSlur = new NumberedSlurGlyph(`numbered.slur.effect`, n, n.effectSlurDestination, false, false);
|
|
66551
66712
|
this._effectSlurs.push(effectSlur);
|
|
66552
66713
|
this.addTie(effectSlur);
|
|
66714
|
+
this._slurs.set(effectSlur.slurEffectId, effectSlur);
|
|
66715
|
+
this._slurs.set('numbered.slur.effect', effectSlur);
|
|
66553
66716
|
}
|
|
66554
66717
|
}
|
|
66555
66718
|
// end effect slur on last beat
|
|
@@ -66562,9 +66725,11 @@ class NumberedBeatContainerGlyph extends BeatContainerGlyph {
|
|
|
66562
66725
|
}
|
|
66563
66726
|
}
|
|
66564
66727
|
if (!expanded) {
|
|
66565
|
-
const effectSlur = new NumberedSlurGlyph(n.effectSlurOrigin, n, false, true);
|
|
66728
|
+
const effectSlur = new NumberedSlurGlyph(`numbered.slur.effect`, n.effectSlurOrigin, n, false, true);
|
|
66566
66729
|
this._effectSlurs.push(effectSlur);
|
|
66567
66730
|
this.addTie(effectSlur);
|
|
66731
|
+
this._slurs.set(effectSlur.slurEffectId, effectSlur);
|
|
66732
|
+
this._slurs.set('numbered.slur.effect', effectSlur);
|
|
66568
66733
|
}
|
|
66569
66734
|
}
|
|
66570
66735
|
}
|
|
@@ -66957,10 +67122,11 @@ class NumberedBeatGlyph extends BeatOnNoteGlyphBase {
|
|
|
66957
67122
|
if (sr.shortestDuration < this.container.beat.duration) {
|
|
66958
67123
|
sr.shortestDuration = this.container.beat.duration;
|
|
66959
67124
|
}
|
|
66960
|
-
const glyphY = sr.getLineY(sr.getNoteLine());
|
|
66961
67125
|
if (!this.container.beat.isEmpty) {
|
|
67126
|
+
const glyphY = sr.getLineY(0);
|
|
66962
67127
|
let numberWithinOctave = '0';
|
|
66963
67128
|
if (this.container.beat.notes.length > 0) {
|
|
67129
|
+
const note = this.container.beat.notes[0];
|
|
66964
67130
|
const kst = this.renderer.bar.keySignatureType;
|
|
66965
67131
|
const ks = this.renderer.bar.keySignature;
|
|
66966
67132
|
const ksi = ks + 7;
|
|
@@ -66968,7 +67134,6 @@ class NumberedBeatGlyph extends BeatOnNoteGlyphBase {
|
|
|
66968
67134
|
? NumberedBeatGlyph.minorKeySignatureOneValues
|
|
66969
67135
|
: NumberedBeatGlyph.majorKeySignatureOneValues;
|
|
66970
67136
|
const oneNoteValue = oneNoteValues[ksi];
|
|
66971
|
-
const note = this.container.beat.notes[0];
|
|
66972
67137
|
if (note.isDead) {
|
|
66973
67138
|
numberWithinOctave = 'X';
|
|
66974
67139
|
}
|
|
@@ -67015,7 +67180,7 @@ class NumberedBeatGlyph extends BeatOnNoteGlyphBase {
|
|
|
67015
67180
|
// Note dots
|
|
67016
67181
|
if (this.container.beat.dots > 0 && this.container.beat.duration >= Duration.Quarter) {
|
|
67017
67182
|
for (let i = 0; i < this.container.beat.dots; i++) {
|
|
67018
|
-
const dot = new AugmentationDotGlyph(0,
|
|
67183
|
+
const dot = new AugmentationDotGlyph(0, glyphY);
|
|
67019
67184
|
dot.renderer = this.renderer;
|
|
67020
67185
|
this.addEffect(dot);
|
|
67021
67186
|
}
|
|
@@ -67043,7 +67208,7 @@ class NumberedBeatGlyph extends BeatOnNoteGlyphBase {
|
|
|
67043
67208
|
numberOfQuarterNotes += numberOfAddedQuarters;
|
|
67044
67209
|
}
|
|
67045
67210
|
for (let i = 0; i < numberOfQuarterNotes - 1; i++) {
|
|
67046
|
-
const dash = new NumberedDashGlyph(0,
|
|
67211
|
+
const dash = new NumberedDashGlyph(0, glyphY, this.container.beat);
|
|
67047
67212
|
dash.renderer = this.renderer;
|
|
67048
67213
|
this.addNormal(dash);
|
|
67049
67214
|
}
|
|
@@ -67513,7 +67678,7 @@ class NumberedBarRenderer extends LineBarRenderer {
|
|
|
67513
67678
|
}
|
|
67514
67679
|
}
|
|
67515
67680
|
}
|
|
67516
|
-
getNoteLine() {
|
|
67681
|
+
getNoteLine(_note) {
|
|
67517
67682
|
return 0;
|
|
67518
67683
|
}
|
|
67519
67684
|
get tupletOffset() {
|
|
@@ -69728,87 +69893,128 @@ class ScoreBendGlyph extends ScoreHelperNotesBaseGlyph {
|
|
|
69728
69893
|
* @internal
|
|
69729
69894
|
*/
|
|
69730
69895
|
class ScoreLegatoGlyph extends TieGlyph {
|
|
69731
|
-
|
|
69732
|
-
|
|
69896
|
+
startBeat;
|
|
69897
|
+
endBeat;
|
|
69898
|
+
startBeatRenderer = null;
|
|
69899
|
+
endBeatRenderer = null;
|
|
69900
|
+
constructor(slurEffectId, startBeat, endBeat, forEnd) {
|
|
69901
|
+
super(slurEffectId, forEnd);
|
|
69902
|
+
this.startBeat = startBeat;
|
|
69903
|
+
this.endBeat = endBeat;
|
|
69733
69904
|
}
|
|
69734
69905
|
doLayout() {
|
|
69735
69906
|
super.doLayout();
|
|
69736
69907
|
}
|
|
69737
|
-
|
|
69738
|
-
if (
|
|
69908
|
+
lookupStartBeatRenderer() {
|
|
69909
|
+
if (!this.startBeatRenderer) {
|
|
69910
|
+
this.startBeatRenderer = this.renderer.scoreRenderer.layout.getRendererForBar(this.renderer.staff.staffId, this.startBeat.voice.bar);
|
|
69911
|
+
}
|
|
69912
|
+
return this.startBeatRenderer;
|
|
69913
|
+
}
|
|
69914
|
+
lookupEndBeatRenderer() {
|
|
69915
|
+
if (!this.endBeatRenderer) {
|
|
69916
|
+
this.endBeatRenderer = this.renderer.scoreRenderer.layout.getRendererForBar(this.renderer.staff.staffId, this.endBeat.voice.bar);
|
|
69917
|
+
}
|
|
69918
|
+
return this.endBeatRenderer;
|
|
69919
|
+
}
|
|
69920
|
+
shouldDrawBendSlur() {
|
|
69921
|
+
return false;
|
|
69922
|
+
}
|
|
69923
|
+
calculateTieDirection() {
|
|
69924
|
+
if (this.startBeat.isRest) {
|
|
69739
69925
|
return BeamDirection.Up;
|
|
69740
69926
|
}
|
|
69741
69927
|
// invert direction (if stems go up, ties go down to not cross them)
|
|
69742
|
-
switch (
|
|
69928
|
+
switch (this.lookupStartBeatRenderer().getBeatDirection(this.startBeat)) {
|
|
69743
69929
|
case BeamDirection.Up:
|
|
69744
69930
|
return BeamDirection.Down;
|
|
69745
69931
|
default:
|
|
69746
69932
|
return BeamDirection.Up;
|
|
69747
69933
|
}
|
|
69748
69934
|
}
|
|
69749
|
-
|
|
69935
|
+
calculateStartX() {
|
|
69936
|
+
const startBeatRenderer = this.lookupStartBeatRenderer();
|
|
69937
|
+
return startBeatRenderer.x + startBeatRenderer.getBeatX(this.startBeat, BeatXPosition.MiddleNotes);
|
|
69938
|
+
}
|
|
69939
|
+
calculateStartY() {
|
|
69940
|
+
const startBeatRenderer = this.lookupStartBeatRenderer();
|
|
69750
69941
|
if (this.startBeat.isRest) {
|
|
69751
|
-
|
|
69752
|
-
|
|
69942
|
+
switch (this.tieDirection) {
|
|
69943
|
+
case BeamDirection.Up:
|
|
69944
|
+
return (startBeatRenderer.y +
|
|
69945
|
+
startBeatRenderer.getBeatContainer(this.startBeat).onNotes.getBoundingBoxTop());
|
|
69946
|
+
default:
|
|
69947
|
+
return (startBeatRenderer.y +
|
|
69948
|
+
startBeatRenderer.getBeatContainer(this.startBeat).onNotes.getBoundingBoxBottom());
|
|
69949
|
+
}
|
|
69753
69950
|
}
|
|
69754
69951
|
switch (this.tieDirection) {
|
|
69755
69952
|
case BeamDirection.Up:
|
|
69756
69953
|
// below lowest note
|
|
69757
|
-
return
|
|
69954
|
+
return startBeatRenderer.y + startBeatRenderer.getNoteY(this.startBeat.maxNote, NoteYPosition.Top);
|
|
69758
69955
|
default:
|
|
69759
|
-
return
|
|
69956
|
+
return startBeatRenderer.y + startBeatRenderer.getNoteY(this.startBeat.minNote, NoteYPosition.Bottom);
|
|
69957
|
+
}
|
|
69958
|
+
}
|
|
69959
|
+
calculateEndX() {
|
|
69960
|
+
const endBeatRenderer = this.lookupEndBeatRenderer();
|
|
69961
|
+
if (!endBeatRenderer) {
|
|
69962
|
+
return this.calculateStartX() + this.renderer.smuflMetrics.leftHandTabTieWidth;
|
|
69760
69963
|
}
|
|
69964
|
+
const endBeamDirection = endBeatRenderer.getBeatDirection(this.endBeat);
|
|
69965
|
+
return (endBeatRenderer.x +
|
|
69966
|
+
endBeatRenderer.getBeatX(this.endBeat, this.endBeat.duration > Duration.Whole && endBeamDirection === this.tieDirection
|
|
69967
|
+
? BeatXPosition.Stem
|
|
69968
|
+
: BeatXPosition.MiddleNotes));
|
|
69761
69969
|
}
|
|
69762
|
-
|
|
69763
|
-
const
|
|
69970
|
+
caclculateEndY() {
|
|
69971
|
+
const endBeatRenderer = this.lookupEndBeatRenderer();
|
|
69972
|
+
if (!endBeatRenderer) {
|
|
69973
|
+
return this.calculateStartY();
|
|
69974
|
+
}
|
|
69764
69975
|
if (this.endBeat.isRest) {
|
|
69765
69976
|
switch (this.tieDirection) {
|
|
69766
69977
|
case BeamDirection.Up:
|
|
69767
|
-
return
|
|
69978
|
+
return (endBeatRenderer.y + endBeatRenderer.getBeatContainer(this.endBeat).onNotes.getBoundingBoxTop());
|
|
69768
69979
|
default:
|
|
69769
|
-
return
|
|
69980
|
+
return (endBeatRenderer.y +
|
|
69981
|
+
endBeatRenderer.getBeatContainer(this.endBeat).onNotes.getBoundingBoxBottom());
|
|
69770
69982
|
}
|
|
69771
69983
|
}
|
|
69772
|
-
const startBeamDirection = this.
|
|
69773
|
-
const endBeamDirection =
|
|
69984
|
+
const startBeamDirection = this.lookupStartBeatRenderer().getBeatDirection(this.startBeat);
|
|
69985
|
+
const endBeamDirection = endBeatRenderer.getBeatDirection(this.endBeat);
|
|
69774
69986
|
if (startBeamDirection !== endBeamDirection && this.startBeat.graceType === GraceType.None) {
|
|
69775
69987
|
if (endBeamDirection === this.tieDirection) {
|
|
69776
69988
|
switch (this.tieDirection) {
|
|
69777
69989
|
case BeamDirection.Up:
|
|
69778
69990
|
// stem upper end
|
|
69779
|
-
return
|
|
69991
|
+
return (endBeatRenderer.y +
|
|
69992
|
+
endBeatRenderer.getNoteY(this.endBeat.maxNote, NoteYPosition.TopWithStem));
|
|
69780
69993
|
default:
|
|
69781
69994
|
// stem lower end
|
|
69782
|
-
return
|
|
69995
|
+
return (endBeatRenderer.y +
|
|
69996
|
+
endBeatRenderer.getNoteY(this.endBeat.minNote, NoteYPosition.BottomWithStem));
|
|
69783
69997
|
}
|
|
69784
69998
|
}
|
|
69785
69999
|
switch (this.tieDirection) {
|
|
69786
70000
|
case BeamDirection.Up:
|
|
69787
70001
|
// stem upper end
|
|
69788
|
-
return
|
|
70002
|
+
return (endBeatRenderer.y +
|
|
70003
|
+
endBeatRenderer.getNoteY(this.endBeat.maxNote, NoteYPosition.BottomWithStem));
|
|
69789
70004
|
default:
|
|
69790
70005
|
// stem lower end
|
|
69791
|
-
return
|
|
70006
|
+
return (endBeatRenderer.y + endBeatRenderer.getNoteY(this.endBeat.minNote, NoteYPosition.TopWithStem));
|
|
69792
70007
|
}
|
|
69793
70008
|
}
|
|
69794
70009
|
switch (this.tieDirection) {
|
|
69795
70010
|
case BeamDirection.Up:
|
|
69796
70011
|
// below lowest note
|
|
69797
|
-
return
|
|
70012
|
+
return endBeatRenderer.y + endBeatRenderer.getNoteY(this.endBeat.maxNote, NoteYPosition.Top);
|
|
69798
70013
|
default:
|
|
69799
70014
|
// above highest note
|
|
69800
|
-
return
|
|
70015
|
+
return endBeatRenderer.y + endBeatRenderer.getNoteY(this.endBeat.minNote, NoteYPosition.Bottom);
|
|
69801
70016
|
}
|
|
69802
70017
|
}
|
|
69803
|
-
getStartX() {
|
|
69804
|
-
return this.startNoteRenderer.getBeatX(this.startBeat, BeatXPosition.MiddleNotes);
|
|
69805
|
-
}
|
|
69806
|
-
getEndX() {
|
|
69807
|
-
const endBeamDirection = this.endNoteRenderer.getBeatDirection(this.endBeat);
|
|
69808
|
-
return this.endNoteRenderer.getBeatX(this.endBeat, this.endBeat.duration > Duration.Whole && endBeamDirection === this.tieDirection
|
|
69809
|
-
? BeatXPosition.Stem
|
|
69810
|
-
: BeatXPosition.MiddleNotes);
|
|
69811
|
-
}
|
|
69812
70018
|
}
|
|
69813
70019
|
|
|
69814
70020
|
/**
|
|
@@ -70008,142 +70214,106 @@ class ScoreSlideLineGlyph extends Glyph {
|
|
|
70008
70214
|
/**
|
|
70009
70215
|
* @internal
|
|
70010
70216
|
*/
|
|
70011
|
-
class
|
|
70012
|
-
|
|
70013
|
-
|
|
70014
|
-
|
|
70015
|
-
|
|
70016
|
-
|
|
70017
|
-
|
|
70217
|
+
class ScoreTieGlyph extends NoteTieGlyph {
|
|
70218
|
+
shouldDrawBendSlur() {
|
|
70219
|
+
return (this.renderer.settings.notation.extendBendArrowsOnTiedNotes &&
|
|
70220
|
+
!!this.startNote.bendOrigin &&
|
|
70221
|
+
this.startNote.isTieOrigin);
|
|
70222
|
+
}
|
|
70223
|
+
calculateStartX() {
|
|
70224
|
+
if (this.isLeftHandTap) {
|
|
70225
|
+
return this.calculateEndX() - this.renderer.smuflMetrics.leftHandTabTieWidth;
|
|
70226
|
+
}
|
|
70227
|
+
return this.renderer.x + this.renderer.getBeatX(this.startNote.beat, BeatXPosition.PostNotes);
|
|
70228
|
+
}
|
|
70229
|
+
calculateEndX() {
|
|
70230
|
+
const endNoteRenderer = this.lookupEndBeatRenderer();
|
|
70231
|
+
if (!endNoteRenderer) {
|
|
70232
|
+
return this.calculateStartX() + this.renderer.smuflMetrics.leftHandTabTieWidth;
|
|
70233
|
+
}
|
|
70234
|
+
if (this.isLeftHandTap) {
|
|
70235
|
+
return endNoteRenderer.x + endNoteRenderer.getNoteX(this.endNote, NoteXPosition.Left);
|
|
70236
|
+
}
|
|
70237
|
+
return endNoteRenderer.x + endNoteRenderer.getBeatX(this.endNote.beat, BeatXPosition.PreNotes);
|
|
70018
70238
|
}
|
|
70239
|
+
}
|
|
70240
|
+
|
|
70241
|
+
/**
|
|
70242
|
+
* @internal
|
|
70243
|
+
*/
|
|
70244
|
+
class ScoreSlurGlyph extends ScoreTieGlyph {
|
|
70019
70245
|
getTieHeight(startX, _startY, endX, _endY) {
|
|
70020
|
-
return Math.log2(endX - startX + 1) * this.renderer.settings.notation.slurHeight / 2;
|
|
70246
|
+
return (Math.log2(endX - startX + 1) * this.renderer.settings.notation.slurHeight) / 2;
|
|
70021
70247
|
}
|
|
70022
|
-
|
|
70248
|
+
calculateStartX() {
|
|
70249
|
+
return (this.renderer.x +
|
|
70250
|
+
(this._isStartCentered()
|
|
70251
|
+
? this.renderer.getBeatX(this.startNote.beat, BeatXPosition.MiddleNotes)
|
|
70252
|
+
: this.renderer.getNoteX(this.startNote, NoteXPosition.Right)));
|
|
70253
|
+
}
|
|
70254
|
+
calculateStartY() {
|
|
70023
70255
|
if (this._isStartCentered()) {
|
|
70024
70256
|
switch (this.tieDirection) {
|
|
70025
70257
|
case BeamDirection.Up:
|
|
70026
|
-
|
|
70027
|
-
return this.startNoteRenderer.getNoteY(this._startNote, NoteYPosition.Top);
|
|
70258
|
+
return this.renderer.y + this.renderer.getNoteY(this.startNote, NoteYPosition.Top);
|
|
70028
70259
|
default:
|
|
70029
|
-
return this.
|
|
70260
|
+
return this.renderer.y + this.renderer.getNoteY(this.startNote, NoteYPosition.Bottom);
|
|
70261
|
+
}
|
|
70262
|
+
}
|
|
70263
|
+
return this.renderer.y + this.renderer.getNoteY(this.startNote, NoteYPosition.Center);
|
|
70264
|
+
}
|
|
70265
|
+
calculateEndX() {
|
|
70266
|
+
const endNoteRenderer = this.lookupEndBeatRenderer();
|
|
70267
|
+
if (!endNoteRenderer) {
|
|
70268
|
+
return this.calculateStartX() + this.renderer.smuflMetrics.leftHandTabTieWidth;
|
|
70269
|
+
}
|
|
70270
|
+
if (this._isEndCentered()) {
|
|
70271
|
+
if (this._isEndOnStem()) {
|
|
70272
|
+
return endNoteRenderer.x + endNoteRenderer.getBeatX(this.endNote.beat, BeatXPosition.Stem);
|
|
70030
70273
|
}
|
|
70274
|
+
return endNoteRenderer.x + endNoteRenderer.getNoteX(this.endNote, NoteXPosition.Center);
|
|
70031
70275
|
}
|
|
70032
|
-
return
|
|
70276
|
+
return endNoteRenderer.x + endNoteRenderer.getBeatX(this.endNote.beat, BeatXPosition.PreNotes);
|
|
70033
70277
|
}
|
|
70034
|
-
|
|
70278
|
+
caclculateEndY() {
|
|
70279
|
+
const endNoteRenderer = this.lookupEndBeatRenderer();
|
|
70280
|
+
if (!endNoteRenderer) {
|
|
70281
|
+
return this.calculateStartY();
|
|
70282
|
+
}
|
|
70035
70283
|
if (this._isEndCentered()) {
|
|
70036
70284
|
if (this._isEndOnStem()) {
|
|
70037
70285
|
switch (this.tieDirection) {
|
|
70038
70286
|
case BeamDirection.Up:
|
|
70039
|
-
return
|
|
70287
|
+
return endNoteRenderer.y + endNoteRenderer.getNoteY(this.endNote, NoteYPosition.TopWithStem);
|
|
70040
70288
|
default:
|
|
70041
|
-
return
|
|
70289
|
+
return endNoteRenderer.y + endNoteRenderer.getNoteY(this.endNote, NoteYPosition.BottomWithStem);
|
|
70042
70290
|
}
|
|
70043
70291
|
}
|
|
70044
70292
|
switch (this.tieDirection) {
|
|
70045
70293
|
case BeamDirection.Up:
|
|
70046
|
-
return
|
|
70294
|
+
return endNoteRenderer.y + endNoteRenderer.getNoteY(this.endNote, NoteYPosition.Top);
|
|
70047
70295
|
default:
|
|
70048
|
-
return
|
|
70296
|
+
return endNoteRenderer.y + endNoteRenderer.getNoteY(this.endNote, NoteYPosition.Bottom);
|
|
70049
70297
|
}
|
|
70050
70298
|
}
|
|
70051
|
-
return
|
|
70299
|
+
return endNoteRenderer.y + endNoteRenderer.getNoteY(this.endNote, NoteYPosition.Center);
|
|
70052
70300
|
}
|
|
70053
70301
|
_isStartCentered() {
|
|
70054
|
-
return ((this.
|
|
70055
|
-
(this.
|
|
70302
|
+
return ((this.startNote === this.startNote.beat.maxNote && this.tieDirection === BeamDirection.Up) ||
|
|
70303
|
+
(this.startNote === this.startNote.beat.minNote && this.tieDirection === BeamDirection.Down));
|
|
70056
70304
|
}
|
|
70057
70305
|
_isEndCentered() {
|
|
70058
|
-
return (this.
|
|
70059
|
-
((this.
|
|
70060
|
-
(this.
|
|
70306
|
+
return (this.startNote.beat.graceType === GraceType.None &&
|
|
70307
|
+
((this.endNote === this.endNote.beat.maxNote && this.tieDirection === BeamDirection.Up) ||
|
|
70308
|
+
(this.endNote === this.endNote.beat.minNote && this.tieDirection === BeamDirection.Down)));
|
|
70061
70309
|
}
|
|
70062
70310
|
_isEndOnStem() {
|
|
70063
|
-
const
|
|
70064
|
-
const
|
|
70065
|
-
const endBeamDirection =
|
|
70066
|
-
|
|
70067
|
-
|
|
70068
|
-
|
|
70069
|
-
return this._isStartCentered()
|
|
70070
|
-
? this.startNoteRenderer.getBeatX(this._startNote.beat, BeatXPosition.MiddleNotes)
|
|
70071
|
-
: this.startNoteRenderer.getNoteX(this._startNote, NoteXPosition.Right);
|
|
70072
|
-
}
|
|
70073
|
-
getEndX() {
|
|
70074
|
-
if (this._isEndCentered()) {
|
|
70075
|
-
if (this._isEndOnStem()) {
|
|
70076
|
-
return this.endNoteRenderer.getBeatX(this._endNote.beat, BeatXPosition.Stem);
|
|
70077
|
-
}
|
|
70078
|
-
return this.endNoteRenderer.getNoteX(this._endNote, NoteXPosition.Center);
|
|
70079
|
-
}
|
|
70080
|
-
return this.endNoteRenderer.getBeatX(this._endNote.beat, BeatXPosition.PreNotes);
|
|
70081
|
-
}
|
|
70082
|
-
}
|
|
70083
|
-
|
|
70084
|
-
/**
|
|
70085
|
-
* @internal
|
|
70086
|
-
*/
|
|
70087
|
-
class ScoreTieGlyph extends TieGlyph {
|
|
70088
|
-
startNote;
|
|
70089
|
-
endNote;
|
|
70090
|
-
constructor(startNote, endNote, forEnd = false) {
|
|
70091
|
-
super(!startNote ? null : startNote.beat, !endNote ? null : endNote.beat, forEnd);
|
|
70092
|
-
this.startNote = startNote;
|
|
70093
|
-
this.endNote = endNote;
|
|
70094
|
-
}
|
|
70095
|
-
shouldDrawBendSlur() {
|
|
70096
|
-
return (this.renderer.settings.notation.extendBendArrowsOnTiedNotes &&
|
|
70097
|
-
!!this.startNote.bendOrigin &&
|
|
70098
|
-
this.startNote.isTieOrigin);
|
|
70099
|
-
}
|
|
70100
|
-
doLayout() {
|
|
70101
|
-
super.doLayout();
|
|
70102
|
-
}
|
|
70103
|
-
getBeamDirection(beat, noteRenderer) {
|
|
70104
|
-
// invert direction (if stems go up, ties go down to not cross them)
|
|
70105
|
-
switch (noteRenderer.getBeatDirection(beat)) {
|
|
70106
|
-
case BeamDirection.Up:
|
|
70107
|
-
return BeamDirection.Down;
|
|
70108
|
-
default:
|
|
70109
|
-
return BeamDirection.Up;
|
|
70110
|
-
}
|
|
70111
|
-
}
|
|
70112
|
-
getStartY() {
|
|
70113
|
-
if (this.startBeat.isRest) {
|
|
70114
|
-
// below all lines
|
|
70115
|
-
return this.startNoteRenderer.getScoreY(9);
|
|
70116
|
-
}
|
|
70117
|
-
switch (this.tieDirection) {
|
|
70118
|
-
case BeamDirection.Up:
|
|
70119
|
-
// below lowest note
|
|
70120
|
-
return this.startNoteRenderer.getNoteY(this.startNote, NoteYPosition.Top);
|
|
70121
|
-
default:
|
|
70122
|
-
return this.startNoteRenderer.getNoteY(this.startNote, NoteYPosition.Bottom);
|
|
70123
|
-
}
|
|
70124
|
-
}
|
|
70125
|
-
getEndY() {
|
|
70126
|
-
const endNoteScoreRenderer = this.endNoteRenderer;
|
|
70127
|
-
if (this.endBeat.isRest) {
|
|
70128
|
-
switch (this.tieDirection) {
|
|
70129
|
-
case BeamDirection.Up:
|
|
70130
|
-
return endNoteScoreRenderer.getScoreY(9);
|
|
70131
|
-
default:
|
|
70132
|
-
return endNoteScoreRenderer.getScoreY(0);
|
|
70133
|
-
}
|
|
70134
|
-
}
|
|
70135
|
-
switch (this.tieDirection) {
|
|
70136
|
-
case BeamDirection.Up:
|
|
70137
|
-
return endNoteScoreRenderer.getNoteY(this.endNote, NoteYPosition.Top);
|
|
70138
|
-
default:
|
|
70139
|
-
return endNoteScoreRenderer.getNoteY(this.endNote, NoteYPosition.Bottom);
|
|
70140
|
-
}
|
|
70141
|
-
}
|
|
70142
|
-
getStartX() {
|
|
70143
|
-
return this.startNoteRenderer.getBeatX(this.startNote.beat, BeatXPosition.PostNotes);
|
|
70144
|
-
}
|
|
70145
|
-
getEndX() {
|
|
70146
|
-
return this.endNoteRenderer.getBeatX(this.endNote.beat, BeatXPosition.PreNotes);
|
|
70311
|
+
const startBeamDirection = this.lookupStartBeatRenderer().getBeatDirection(this.startNote.beat);
|
|
70312
|
+
const endBeatRenderer = this.lookupEndBeatRenderer();
|
|
70313
|
+
const endBeamDirection = endBeatRenderer
|
|
70314
|
+
? endBeatRenderer.getBeatDirection(this.endNote.beat)
|
|
70315
|
+
: startBeamDirection;
|
|
70316
|
+
return startBeamDirection !== endBeamDirection && this.startNote.beat.graceType === GraceType.None;
|
|
70147
70317
|
}
|
|
70148
70318
|
}
|
|
70149
70319
|
|
|
@@ -70193,12 +70363,11 @@ class ScoreBeatContainerGlyph extends BeatContainerGlyph {
|
|
|
70193
70363
|
n.beat.graceType !== GraceType.BendGrace &&
|
|
70194
70364
|
n.tieDestination &&
|
|
70195
70365
|
n.tieDestination.isVisible) {
|
|
70196
|
-
|
|
70197
|
-
const tie = new ScoreTieGlyph(n, n.tieDestination, false);
|
|
70366
|
+
const tie = new ScoreTieGlyph(`score.tie.${n.id}`, n, n.tieDestination, false);
|
|
70198
70367
|
this.addTie(tie);
|
|
70199
70368
|
}
|
|
70200
70369
|
if (n.isTieDestination && !n.tieOrigin.hasBend && !n.beat.hasWhammyBar) {
|
|
70201
|
-
const tie = new ScoreTieGlyph(n.tieOrigin, n, true);
|
|
70370
|
+
const tie = new ScoreTieGlyph(`score.tie.${n.tieOrigin.id}`, n.tieOrigin, n, true);
|
|
70202
70371
|
this.addTie(tie);
|
|
70203
70372
|
}
|
|
70204
70373
|
// TODO: depending on the type we have other positioning
|
|
@@ -70208,17 +70377,16 @@ class ScoreBeatContainerGlyph extends BeatContainerGlyph {
|
|
|
70208
70377
|
this.addTie(l);
|
|
70209
70378
|
}
|
|
70210
70379
|
if (n.isSlurOrigin && n.slurDestination && n.slurDestination.isVisible) {
|
|
70211
|
-
|
|
70212
|
-
const tie = new ScoreSlurGlyph(n, n.slurDestination, false);
|
|
70380
|
+
const tie = new ScoreSlurGlyph(`score.slur.${n.id}`, n, n.slurDestination, false);
|
|
70213
70381
|
this.addTie(tie);
|
|
70214
70382
|
}
|
|
70215
70383
|
if (n.isSlurDestination) {
|
|
70216
|
-
const tie = new ScoreSlurGlyph(n.slurOrigin, n, true);
|
|
70384
|
+
const tie = new ScoreSlurGlyph(`score.slur.${n.slurOrigin.id}`, n.slurOrigin, n, true);
|
|
70217
70385
|
this.addTie(tie);
|
|
70218
70386
|
}
|
|
70219
70387
|
// start effect slur on first beat
|
|
70220
70388
|
if (!this._effectSlur && n.isEffectSlurOrigin && n.effectSlurDestination) {
|
|
70221
|
-
const effectSlur = new ScoreSlurGlyph(n, n.effectSlurDestination, false);
|
|
70389
|
+
const effectSlur = new ScoreSlurGlyph(`score.slur.effect.${n.beat.id}`, n, n.effectSlurDestination, false);
|
|
70222
70390
|
this._effectSlur = effectSlur;
|
|
70223
70391
|
this.addTie(effectSlur);
|
|
70224
70392
|
}
|
|
@@ -70227,7 +70395,7 @@ class ScoreBeatContainerGlyph extends BeatContainerGlyph {
|
|
|
70227
70395
|
const direction = this.onNotes.beamingHelper.direction;
|
|
70228
70396
|
const startNote = direction === BeamDirection.Up ? n.beat.effectSlurOrigin.minNote : n.beat.effectSlurOrigin.maxNote;
|
|
70229
70397
|
const endNote = direction === BeamDirection.Up ? n.beat.minNote : n.beat.maxNote;
|
|
70230
|
-
const effectEndSlur = new ScoreSlurGlyph(startNote, endNote, true);
|
|
70398
|
+
const effectEndSlur = new ScoreSlurGlyph(`score.slur.effect.${startNote.beat.id}`, startNote, endNote, true);
|
|
70231
70399
|
this._effectEndSlur = effectEndSlur;
|
|
70232
70400
|
this.addTie(effectEndSlur);
|
|
70233
70401
|
}
|
|
@@ -70249,7 +70417,7 @@ class ScoreBeatContainerGlyph extends BeatContainerGlyph {
|
|
|
70249
70417
|
while (destination.nextBeat && destination.nextBeat.isLegatoDestination) {
|
|
70250
70418
|
destination = destination.nextBeat;
|
|
70251
70419
|
}
|
|
70252
|
-
this.addTie(new ScoreLegatoGlyph(this.beat, destination, false));
|
|
70420
|
+
this.addTie(new ScoreLegatoGlyph(`score.legato.${this.beat.id}`, this.beat, destination, false));
|
|
70253
70421
|
}
|
|
70254
70422
|
}
|
|
70255
70423
|
else if (this.beat.isLegatoDestination) {
|
|
@@ -70259,7 +70427,7 @@ class ScoreBeatContainerGlyph extends BeatContainerGlyph {
|
|
|
70259
70427
|
while (origin.previousBeat && origin.previousBeat.isLegatoOrigin) {
|
|
70260
70428
|
origin = origin.previousBeat;
|
|
70261
70429
|
}
|
|
70262
|
-
this.addTie(new ScoreLegatoGlyph(origin, this.beat, true));
|
|
70430
|
+
this.addTie(new ScoreLegatoGlyph(`score.legato.${origin.id}`, origin, this.beat, true));
|
|
70263
70431
|
}
|
|
70264
70432
|
}
|
|
70265
70433
|
}
|
|
@@ -70639,6 +70807,9 @@ class ScoreBarRenderer extends LineBarRenderer {
|
|
|
70639
70807
|
this.addBeatGlyph(container);
|
|
70640
70808
|
}
|
|
70641
70809
|
}
|
|
70810
|
+
getNoteLine(note) {
|
|
70811
|
+
return this.accidentalHelper.getNoteSteps(note) / 2;
|
|
70812
|
+
}
|
|
70642
70813
|
getNoteSteps(n) {
|
|
70643
70814
|
return this.accidentalHelper.getNoteSteps(n);
|
|
70644
70815
|
}
|
|
@@ -70695,43 +70866,15 @@ class ScoreBarRendererFactory extends BarRendererFactory {
|
|
|
70695
70866
|
/**
|
|
70696
70867
|
* @internal
|
|
70697
70868
|
*/
|
|
70698
|
-
class SlashTieGlyph extends
|
|
70699
|
-
|
|
70700
|
-
endNote;
|
|
70701
|
-
constructor(startNote, endNote, forEnd = false) {
|
|
70702
|
-
super(startNote.beat, endNote.beat, forEnd);
|
|
70703
|
-
this.startNote = startNote;
|
|
70704
|
-
this.endNote = endNote;
|
|
70705
|
-
}
|
|
70706
|
-
get _isLeftHandTap() {
|
|
70707
|
-
return this.startNote === this.endNote;
|
|
70708
|
-
}
|
|
70709
|
-
getTieHeight(startX, startY, endX, endY) {
|
|
70710
|
-
if (this._isLeftHandTap) {
|
|
70711
|
-
return this.startNoteRenderer.smuflMetrics.tieHeight;
|
|
70712
|
-
}
|
|
70713
|
-
return super.getTieHeight(startX, startY, endX, endY);
|
|
70714
|
-
}
|
|
70715
|
-
getBeamDirection(_beat, _noteRenderer) {
|
|
70869
|
+
class SlashTieGlyph extends NoteTieGlyph {
|
|
70870
|
+
calculateTieDirection() {
|
|
70716
70871
|
return BeamDirection.Down;
|
|
70717
70872
|
}
|
|
70718
|
-
|
|
70719
|
-
return
|
|
70720
|
-
}
|
|
70721
|
-
getStartY() {
|
|
70722
|
-
return this.startNoteRenderer.getNoteY(this.startNote, NoteYPosition.Center);
|
|
70723
|
-
}
|
|
70724
|
-
getEndY() {
|
|
70725
|
-
return this.getStartY();
|
|
70726
|
-
}
|
|
70727
|
-
getStartX() {
|
|
70728
|
-
if (this._isLeftHandTap) {
|
|
70729
|
-
return this.getEndX() - this.renderer.smuflMetrics.leftHandTabTieWidth;
|
|
70730
|
-
}
|
|
70731
|
-
return this.startNoteRenderer.getNoteX(this.startNote, NoteXPosition.Right);
|
|
70873
|
+
getStartNotePosition() {
|
|
70874
|
+
return NoteXPosition.Right;
|
|
70732
70875
|
}
|
|
70733
|
-
|
|
70734
|
-
return
|
|
70876
|
+
getEndNotePosition() {
|
|
70877
|
+
return NoteXPosition.Left;
|
|
70735
70878
|
}
|
|
70736
70879
|
}
|
|
70737
70880
|
|
|
@@ -70746,12 +70889,12 @@ class SlashBeatContainerGlyph extends BeatContainerGlyph {
|
|
|
70746
70889
|
return;
|
|
70747
70890
|
}
|
|
70748
70891
|
if (!this._tiedNoteTie && n.isTieOrigin && n.tieDestination.isVisible) {
|
|
70749
|
-
const tie = new SlashTieGlyph(n, n.tieDestination, false);
|
|
70892
|
+
const tie = new SlashTieGlyph('slash.tie', n, n.tieDestination, false);
|
|
70750
70893
|
this._tiedNoteTie = tie;
|
|
70751
70894
|
this.addTie(tie);
|
|
70752
70895
|
}
|
|
70753
70896
|
if (!this._tiedNoteTie && n.isTieDestination) {
|
|
70754
|
-
const tie = new SlashTieGlyph(n.tieOrigin, n, true);
|
|
70897
|
+
const tie = new SlashTieGlyph('slash.tie', n.tieOrigin, n, true);
|
|
70755
70898
|
this._tiedNoteTie = tie;
|
|
70756
70899
|
this.addTie(tie);
|
|
70757
70900
|
}
|
|
@@ -70878,8 +71021,7 @@ class SlashBeatGlyph extends BeatOnNoteGlyphBase {
|
|
|
70878
71021
|
doLayout() {
|
|
70879
71022
|
// create glyphs
|
|
70880
71023
|
const sr = this.renderer;
|
|
70881
|
-
const
|
|
70882
|
-
const glyphY = sr.getLineY(line);
|
|
71024
|
+
const glyphY = sr.getLineY(0);
|
|
70883
71025
|
if (this.container.beat.deadSlapped) {
|
|
70884
71026
|
const deadSlapped = new DeadSlappedBeatGlyph();
|
|
70885
71027
|
deadSlapped.renderer = this.renderer;
|
|
@@ -70912,7 +71054,7 @@ class SlashBeatGlyph extends BeatOnNoteGlyphBase {
|
|
|
70912
71054
|
//
|
|
70913
71055
|
if (this.container.beat.dots > 0) {
|
|
70914
71056
|
for (let i = 0; i < this.container.beat.dots; i++) {
|
|
70915
|
-
this.addEffect(new AugmentationDotGlyph(0,
|
|
71057
|
+
this.addEffect(new AugmentationDotGlyph(0, glyphY - sr.getLineHeight(0.5)));
|
|
70916
71058
|
}
|
|
70917
71059
|
}
|
|
70918
71060
|
super.doLayout();
|
|
@@ -70994,7 +71136,7 @@ class SlashBarRenderer extends LineBarRenderer {
|
|
|
70994
71136
|
this.registerOverflowTop(this.tupletSize);
|
|
70995
71137
|
}
|
|
70996
71138
|
}
|
|
70997
|
-
getNoteLine() {
|
|
71139
|
+
getNoteLine(_note) {
|
|
70998
71140
|
return 0;
|
|
70999
71141
|
}
|
|
71000
71142
|
getFlagTopY(beat, _direction) {
|
|
@@ -71331,77 +71473,6 @@ class TabSlideLineGlyph extends Glyph {
|
|
|
71331
71473
|
}
|
|
71332
71474
|
}
|
|
71333
71475
|
|
|
71334
|
-
/**
|
|
71335
|
-
* @internal
|
|
71336
|
-
*/
|
|
71337
|
-
class TabSlurGlyph extends TabTieGlyph {
|
|
71338
|
-
_direction;
|
|
71339
|
-
_forSlide;
|
|
71340
|
-
constructor(startNote, endNote, forSlide, forEnd = false) {
|
|
71341
|
-
super(startNote, endNote, forEnd);
|
|
71342
|
-
this._direction = TabTieGlyph.getBeamDirectionForNote(startNote);
|
|
71343
|
-
this._forSlide = forSlide;
|
|
71344
|
-
}
|
|
71345
|
-
getTieHeight(startX, _startY, endX, _endY) {
|
|
71346
|
-
return Math.log(endX - startX + 1) * this.renderer.settings.notation.slurHeight / 2;
|
|
71347
|
-
}
|
|
71348
|
-
tryExpand(startNote, endNote, forSlide, forEnd) {
|
|
71349
|
-
// same type required
|
|
71350
|
-
if (this._forSlide !== forSlide) {
|
|
71351
|
-
return false;
|
|
71352
|
-
}
|
|
71353
|
-
if (this.forEnd !== forEnd) {
|
|
71354
|
-
return false;
|
|
71355
|
-
}
|
|
71356
|
-
// same start and endbeat
|
|
71357
|
-
if (this.startNote.beat.id !== startNote.beat.id) {
|
|
71358
|
-
return false;
|
|
71359
|
-
}
|
|
71360
|
-
if (this.endNote.beat.id !== endNote.beat.id) {
|
|
71361
|
-
return false;
|
|
71362
|
-
}
|
|
71363
|
-
// same draw direction
|
|
71364
|
-
if (this._direction !== TabTieGlyph.getBeamDirectionForNote(startNote)) {
|
|
71365
|
-
return false;
|
|
71366
|
-
}
|
|
71367
|
-
// if we can expand, expand in correct direction
|
|
71368
|
-
switch (this._direction) {
|
|
71369
|
-
case BeamDirection.Up:
|
|
71370
|
-
if (startNote.realValue > this.startNote.realValue) {
|
|
71371
|
-
this.startNote = startNote;
|
|
71372
|
-
this.startBeat = startNote.beat;
|
|
71373
|
-
}
|
|
71374
|
-
if (endNote.realValue > this.endNote.realValue) {
|
|
71375
|
-
this.endNote = endNote;
|
|
71376
|
-
this.endBeat = endNote.beat;
|
|
71377
|
-
}
|
|
71378
|
-
break;
|
|
71379
|
-
case BeamDirection.Down:
|
|
71380
|
-
if (startNote.realValue < this.startNote.realValue) {
|
|
71381
|
-
this.startNote = startNote;
|
|
71382
|
-
this.startBeat = startNote.beat;
|
|
71383
|
-
}
|
|
71384
|
-
if (endNote.realValue < this.endNote.realValue) {
|
|
71385
|
-
this.endNote = endNote;
|
|
71386
|
-
this.endBeat = endNote.beat;
|
|
71387
|
-
}
|
|
71388
|
-
break;
|
|
71389
|
-
}
|
|
71390
|
-
return true;
|
|
71391
|
-
}
|
|
71392
|
-
paint(cx, cy, canvas) {
|
|
71393
|
-
const startNoteRenderer = this.renderer.scoreRenderer.layout.getRendererForBar(this.renderer.staff.staffId, this.startBeat.voice.bar);
|
|
71394
|
-
const direction = this.getBeamDirection(this.startBeat, startNoteRenderer);
|
|
71395
|
-
const slurId = `tab.slur.${this.startNote.beat.id}.${this.endNote.beat.id}.${direction}`;
|
|
71396
|
-
const renderer = this.renderer;
|
|
71397
|
-
const isSlurRendered = renderer.staff.getSharedLayoutData(slurId, false);
|
|
71398
|
-
if (!isSlurRendered) {
|
|
71399
|
-
renderer.staff.setSharedLayoutData(slurId, true);
|
|
71400
|
-
super.paint(cx, cy, canvas);
|
|
71401
|
-
}
|
|
71402
|
-
}
|
|
71403
|
-
}
|
|
71404
|
-
|
|
71405
71476
|
/**
|
|
71406
71477
|
* @internal
|
|
71407
71478
|
*/
|
|
@@ -71426,15 +71497,15 @@ class TabBeatContainerGlyph extends BeatContainerGlyph {
|
|
|
71426
71497
|
}
|
|
71427
71498
|
const renderer = this.renderer;
|
|
71428
71499
|
if (n.isTieOrigin && renderer.showTiedNotes && n.tieDestination.isVisible) {
|
|
71429
|
-
const tie = new TabTieGlyph(n, n.tieDestination, false);
|
|
71500
|
+
const tie = new TabTieGlyph(`tab.tie.${n.id}`, n, n.tieDestination, false);
|
|
71430
71501
|
this.addTie(tie);
|
|
71431
71502
|
}
|
|
71432
71503
|
if (n.isTieDestination && renderer.showTiedNotes) {
|
|
71433
|
-
const tie = new TabTieGlyph(n.tieOrigin, n, true);
|
|
71504
|
+
const tie = new TabTieGlyph(`tab.tie.${n.tieOrigin.id}`, n.tieOrigin, n, true);
|
|
71434
71505
|
this.addTie(tie);
|
|
71435
71506
|
}
|
|
71436
71507
|
if (n.isLeftHandTapped && !n.isHammerPullDestination) {
|
|
71437
|
-
const tapSlur = new TabTieGlyph(n, n, false);
|
|
71508
|
+
const tapSlur = new TabTieGlyph(`tab.tie.leftHandTap.${n.id}`, n, n, false);
|
|
71438
71509
|
this.addTie(tapSlur);
|
|
71439
71510
|
}
|
|
71440
71511
|
// start effect slur on first beat
|
|
@@ -71447,7 +71518,7 @@ class TabBeatContainerGlyph extends BeatContainerGlyph {
|
|
|
71447
71518
|
}
|
|
71448
71519
|
}
|
|
71449
71520
|
if (!expanded) {
|
|
71450
|
-
const effectSlur = new TabSlurGlyph(n, n.effectSlurDestination, false, false);
|
|
71521
|
+
const effectSlur = new TabSlurGlyph(`tab.slur.effect.${n.id}`, n, n.effectSlurDestination, false, false);
|
|
71451
71522
|
this._effectSlurs.push(effectSlur);
|
|
71452
71523
|
this.addTie(effectSlur);
|
|
71453
71524
|
}
|
|
@@ -71462,7 +71533,7 @@ class TabBeatContainerGlyph extends BeatContainerGlyph {
|
|
|
71462
71533
|
}
|
|
71463
71534
|
}
|
|
71464
71535
|
if (!expanded) {
|
|
71465
|
-
const effectSlur = new TabSlurGlyph(n.effectSlurOrigin, n, false, true);
|
|
71536
|
+
const effectSlur = new TabSlurGlyph(`tab.slur.effect.${n.effectSlurOrigin.id}`, n.effectSlurOrigin, n, false, true);
|
|
71466
71537
|
this._effectSlurs.push(effectSlur);
|
|
71467
71538
|
this.addTie(effectSlur);
|
|
71468
71539
|
}
|
|
@@ -71881,7 +71952,7 @@ class TabBeatGlyph extends BeatOnNoteGlyphBase {
|
|
|
71881
71952
|
}
|
|
71882
71953
|
else {
|
|
71883
71954
|
const line = Math.floor((this.renderer.bar.staff.tuning.length - 1) / 2);
|
|
71884
|
-
const y = tabRenderer.
|
|
71955
|
+
const y = tabRenderer.getLineY(line);
|
|
71885
71956
|
const restGlyph = new TabRestGlyph(0, y, tabRenderer.showRests, this.container.beat.duration);
|
|
71886
71957
|
this.restGlyph = restGlyph;
|
|
71887
71958
|
restGlyph.beat = this.container.beat;
|
|
@@ -71940,8 +72011,8 @@ class TabBeatGlyph extends BeatOnNoteGlyphBase {
|
|
|
71940
72011
|
_createNoteGlyph(n) {
|
|
71941
72012
|
const tr = this.renderer;
|
|
71942
72013
|
const noteNumberGlyph = new NoteNumberGlyph(0, 0, n);
|
|
71943
|
-
const l =
|
|
71944
|
-
noteNumberGlyph.y = tr.
|
|
72014
|
+
const l = tr.getNoteLine(n);
|
|
72015
|
+
noteNumberGlyph.y = tr.getLineY(l);
|
|
71945
72016
|
noteNumberGlyph.renderer = this.renderer;
|
|
71946
72017
|
noteNumberGlyph.doLayout();
|
|
71947
72018
|
this.noteNumbers.addNoteGlyph(noteNumberGlyph, n);
|
|
@@ -72132,17 +72203,8 @@ class TabBarRenderer extends LineBarRenderer {
|
|
|
72132
72203
|
}
|
|
72133
72204
|
return mode;
|
|
72134
72205
|
}
|
|
72135
|
-
|
|
72136
|
-
|
|
72137
|
-
* @param line the line of the particular string where 0 is the most top line
|
|
72138
|
-
* @param correction
|
|
72139
|
-
* @returns
|
|
72140
|
-
*/
|
|
72141
|
-
getTabY(line) {
|
|
72142
|
-
return super.getLineY(line);
|
|
72143
|
-
}
|
|
72144
|
-
getTabHeight(line) {
|
|
72145
|
-
return super.getLineHeight(line);
|
|
72206
|
+
getNoteLine(note) {
|
|
72207
|
+
return this.bar.staff.tuning.length - note.string;
|
|
72146
72208
|
}
|
|
72147
72209
|
minString = Number.NaN;
|
|
72148
72210
|
maxString = Number.NaN;
|
|
@@ -72231,7 +72293,7 @@ class TabBarRenderer extends LineBarRenderer {
|
|
|
72231
72293
|
if (this.isFirstOfLine) {
|
|
72232
72294
|
const center = (this.bar.staff.tuning.length - 1) / 2;
|
|
72233
72295
|
this.createStartSpacing();
|
|
72234
|
-
this.addPreBeatGlyph(new TabClefGlyph(0, this.
|
|
72296
|
+
this.addPreBeatGlyph(new TabClefGlyph(0, this.getLineY(center)));
|
|
72235
72297
|
}
|
|
72236
72298
|
// Time Signature
|
|
72237
72299
|
if (this.showTimeSignature &&
|
|
@@ -72252,7 +72314,7 @@ class TabBarRenderer extends LineBarRenderer {
|
|
|
72252
72314
|
_createTimeSignatureGlyphs() {
|
|
72253
72315
|
this.addPreBeatGlyph(new SpacingGlyph(0, 0, this.smuflMetrics.oneStaffSpace));
|
|
72254
72316
|
const lines = (this.bar.staff.tuning.length + 1) / 2 - 1;
|
|
72255
|
-
this.addPreBeatGlyph(new TabTimeSignatureGlyph(0, this.
|
|
72317
|
+
this.addPreBeatGlyph(new TabTimeSignatureGlyph(0, this.getLineY(lines), this.bar.masterBar.timeSignatureNumerator, this.bar.masterBar.timeSignatureDenominator, this.bar.masterBar.timeSignatureCommon, this.bar.masterBar.isFreeTime));
|
|
72256
72318
|
}
|
|
72257
72319
|
createVoiceGlyphs(v) {
|
|
72258
72320
|
super.createVoiceGlyphs(v);
|