@coderline/alphatab 1.8.0-alpha.1637 → 1.8.0-alpha.1640
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/alphaTab.core.min.mjs +2 -2
- package/dist/alphaTab.core.mjs +860 -757
- package/dist/alphaTab.js +860 -757
- package/dist/alphaTab.min.js +2 -2
- package/dist/alphaTab.min.mjs +1 -1
- package/dist/alphaTab.mjs +1 -1
- package/dist/alphaTab.worker.min.mjs +1 -1
- package/dist/alphaTab.worker.mjs +1 -1
- package/dist/alphaTab.worklet.min.mjs +1 -1
- package/dist/alphaTab.worklet.mjs +1 -1
- package/package.json +3 -3
package/dist/alphaTab.core.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* alphaTab v1.8.0-alpha.
|
|
2
|
+
* alphaTab v1.8.0-alpha.1640 (develop, build 1640)
|
|
3
3
|
*
|
|
4
4
|
* Copyright © 2025, Daniel Kuschny and Contributors, All rights reserved.
|
|
5
5
|
*
|
|
@@ -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.1640';
|
|
207
|
+
static date = '2025-12-10T02:19:08.776Z';
|
|
208
|
+
static commit = '343f59ee6b39b4f3a41636b3c33db34bccf631f9';
|
|
209
209
|
static print(print) {
|
|
210
210
|
print(`alphaTab ${VersionInfo.version}`);
|
|
211
211
|
print(`commit: ${VersionInfo.commit}`);
|
|
@@ -48527,7 +48527,7 @@ class BeatContainerGlyph extends Glyph {
|
|
|
48527
48527
|
onNotes;
|
|
48528
48528
|
minWidth = 0;
|
|
48529
48529
|
get onTimeX() {
|
|
48530
|
-
return this.onNotes.x + this.onNotes.
|
|
48530
|
+
return this.onNotes.x + this.onNotes.onTimeX;
|
|
48531
48531
|
}
|
|
48532
48532
|
constructor(beat, voiceContainer) {
|
|
48533
48533
|
super(0, 0);
|
|
@@ -48551,8 +48551,8 @@ class BeatContainerGlyph extends Glyph {
|
|
|
48551
48551
|
return helper.hasFlag(false, undefined);
|
|
48552
48552
|
}
|
|
48553
48553
|
registerLayoutingInfo(layoutings) {
|
|
48554
|
-
const preBeatStretch = this.preNotes.computedWidth + this.onNotes.
|
|
48555
|
-
let postBeatStretch = this.onNotes.computedWidth - this.onNotes.
|
|
48554
|
+
const preBeatStretch = this.preNotes.computedWidth + this.onNotes.onTimeX;
|
|
48555
|
+
let postBeatStretch = this.onNotes.computedWidth - this.onNotes.onTimeX;
|
|
48556
48556
|
// make space for flag
|
|
48557
48557
|
const helper = this.renderer.helpers.getBeamingHelperForBeat(this.beat);
|
|
48558
48558
|
if (this.beat.graceType !== GraceType.None) {
|
|
@@ -48695,7 +48695,7 @@ class BeatContainerGlyph extends Glyph {
|
|
|
48695
48695
|
beatBoundings.realBounds.y = barBounds.realBounds.y;
|
|
48696
48696
|
beatBoundings.realBounds.w = this.width;
|
|
48697
48697
|
beatBoundings.realBounds.h = barBounds.realBounds.h;
|
|
48698
|
-
beatBoundings.onNotesX = cx + this.x + this.onNotes.
|
|
48698
|
+
beatBoundings.onNotesX = cx + this.x + this.onNotes.x + this.onNotes.onTimeX;
|
|
48699
48699
|
}
|
|
48700
48700
|
else {
|
|
48701
48701
|
beatBoundings.visualBounds = new Bounds();
|
|
@@ -48733,7 +48733,7 @@ class BeatContainerGlyph extends Glyph {
|
|
|
48733
48733
|
beatBoundings.realBounds.y = barBounds.realBounds.y;
|
|
48734
48734
|
beatBoundings.realBounds.w = this.width;
|
|
48735
48735
|
beatBoundings.realBounds.h = barBounds.realBounds.h;
|
|
48736
|
-
beatBoundings.onNotesX = cx + this.x + this.onNotes.x + this.onNotes.
|
|
48736
|
+
beatBoundings.onNotesX = cx + this.x + this.onNotes.x + this.onNotes.onTimeX;
|
|
48737
48737
|
}
|
|
48738
48738
|
barBounds.addBeat(beatBoundings);
|
|
48739
48739
|
if (this.renderer.settings.core.includeNoteBounds) {
|
|
@@ -54358,6 +54358,7 @@ class Cursors {
|
|
|
54358
54358
|
class ScalableHtmlElementContainer extends HtmlElementContainer {
|
|
54359
54359
|
_xscale;
|
|
54360
54360
|
_yscale;
|
|
54361
|
+
centerAtPosition = false;
|
|
54361
54362
|
constructor(element, xscale, yscale) {
|
|
54362
54363
|
super(element);
|
|
54363
54364
|
this._xscale = xscale;
|
|
@@ -54399,7 +54400,11 @@ class ScalableHtmlElementContainer extends HtmlElementContainer {
|
|
|
54399
54400
|
else {
|
|
54400
54401
|
h = h / this._yscale;
|
|
54401
54402
|
}
|
|
54402
|
-
|
|
54403
|
+
let transform = `translate(${x}px, ${y}px) scale(${w}, ${h})`;
|
|
54404
|
+
if (this.centerAtPosition) {
|
|
54405
|
+
transform += ` translateX(-50%)`;
|
|
54406
|
+
}
|
|
54407
|
+
this.element.style.transform = transform;
|
|
54403
54408
|
this.element.style.transformOrigin = 'top left';
|
|
54404
54409
|
this.lastBounds.x = x;
|
|
54405
54410
|
this.lastBounds.y = y;
|
|
@@ -55260,6 +55265,7 @@ class BrowserUiFacade {
|
|
|
55260
55265
|
beatCursor.style.willChange = 'transform';
|
|
55261
55266
|
beatCursorContainer.width = 3;
|
|
55262
55267
|
beatCursorContainer.height = 1;
|
|
55268
|
+
beatCursorContainer.centerAtPosition = true;
|
|
55263
55269
|
beatCursorContainer.setBounds(0, 0, 1, 1);
|
|
55264
55270
|
// add cursors to UI
|
|
55265
55271
|
element.insertBefore(cursorWrapper, element.firstChild);
|
|
@@ -56634,7 +56640,7 @@ var BeatXPosition;
|
|
|
56634
56640
|
*/
|
|
56635
56641
|
BeatXPosition[BeatXPosition["OnNotes"] = 1] = "OnNotes";
|
|
56636
56642
|
/**
|
|
56637
|
-
* Gets the middle-notes position which is located after in the
|
|
56643
|
+
* Gets the middle-notes position which is located after in the exact center of the note heads.
|
|
56638
56644
|
*/
|
|
56639
56645
|
BeatXPosition[BeatXPosition["MiddleNotes"] = 2] = "MiddleNotes";
|
|
56640
56646
|
/**
|
|
@@ -56664,12 +56670,12 @@ class GroupedEffectGlyph extends EffectGlyph {
|
|
|
56664
56670
|
this.endPosition = endPosition;
|
|
56665
56671
|
}
|
|
56666
56672
|
get isLinkedWithPrevious() {
|
|
56667
|
-
return !!this.previousGlyph && this.previousGlyph.renderer.staff
|
|
56673
|
+
return !!this.previousGlyph && this.previousGlyph.renderer.staff?.system === this.renderer.staff.system;
|
|
56668
56674
|
}
|
|
56669
56675
|
get isLinkedWithNext() {
|
|
56670
56676
|
return (!!this.nextGlyph &&
|
|
56671
56677
|
this.nextGlyph.renderer.isFinalized &&
|
|
56672
|
-
this.nextGlyph.renderer.staff
|
|
56678
|
+
this.nextGlyph.renderer.staff?.system === this.renderer.staff.system);
|
|
56673
56679
|
}
|
|
56674
56680
|
paint(cx, cy, canvas) {
|
|
56675
56681
|
// if we are linked with the previous, the first glyph of the group will also render this one.
|
|
@@ -59057,6 +59063,437 @@ class LeftToRightLayoutingGlyphGroup extends GlyphGroup {
|
|
|
59057
59063
|
}
|
|
59058
59064
|
}
|
|
59059
59065
|
|
|
59066
|
+
/**
|
|
59067
|
+
* @internal
|
|
59068
|
+
*/
|
|
59069
|
+
class TieGlyph extends Glyph {
|
|
59070
|
+
tieDirection = BeamDirection.Up;
|
|
59071
|
+
slurEffectId;
|
|
59072
|
+
isForEnd;
|
|
59073
|
+
constructor(slurEffectId, forEnd) {
|
|
59074
|
+
super(0, 0);
|
|
59075
|
+
this.slurEffectId = slurEffectId;
|
|
59076
|
+
this.isForEnd = forEnd;
|
|
59077
|
+
}
|
|
59078
|
+
_startX = 0;
|
|
59079
|
+
_startY = 0;
|
|
59080
|
+
_endX = 0;
|
|
59081
|
+
_endY = 0;
|
|
59082
|
+
_tieHeight = 0;
|
|
59083
|
+
_boundingBox;
|
|
59084
|
+
_shouldPaint = false;
|
|
59085
|
+
get checkForOverflow() {
|
|
59086
|
+
return this._shouldPaint && this._boundingBox !== undefined;
|
|
59087
|
+
}
|
|
59088
|
+
getBoundingBoxTop() {
|
|
59089
|
+
if (this._boundingBox) {
|
|
59090
|
+
return this._boundingBox.y;
|
|
59091
|
+
}
|
|
59092
|
+
return this._startY;
|
|
59093
|
+
}
|
|
59094
|
+
getBoundingBoxBottom() {
|
|
59095
|
+
if (this._boundingBox) {
|
|
59096
|
+
return this._boundingBox.y + this._boundingBox.h;
|
|
59097
|
+
}
|
|
59098
|
+
return this._startY;
|
|
59099
|
+
}
|
|
59100
|
+
doLayout() {
|
|
59101
|
+
this.width = 0;
|
|
59102
|
+
const startNoteRenderer = this.lookupStartBeatRenderer();
|
|
59103
|
+
const endNoteRenderer = this.lookupEndBeatRenderer();
|
|
59104
|
+
this._startX = 0;
|
|
59105
|
+
this._endX = 0;
|
|
59106
|
+
this._startY = 0;
|
|
59107
|
+
this._endY = 0;
|
|
59108
|
+
this.height = 0;
|
|
59109
|
+
// if we are on the tie start, we check if we
|
|
59110
|
+
// either can draw till the end note, or we just can draw till the bar end
|
|
59111
|
+
this.tieDirection = this.calculateTieDirection();
|
|
59112
|
+
const forEnd = this.isForEnd;
|
|
59113
|
+
this._shouldPaint = false;
|
|
59114
|
+
if (!forEnd) {
|
|
59115
|
+
if (startNoteRenderer !== endNoteRenderer) {
|
|
59116
|
+
this._startX = this.calculateStartX();
|
|
59117
|
+
this._startY = this.calculateStartY();
|
|
59118
|
+
if (!endNoteRenderer || startNoteRenderer.staff !== endNoteRenderer.staff) {
|
|
59119
|
+
const lastRendererInStaff = startNoteRenderer.staff.barRenderers[startNoteRenderer.staff.barRenderers.length - 1];
|
|
59120
|
+
this._endX = lastRendererInStaff.x + lastRendererInStaff.width;
|
|
59121
|
+
this._endY = this._startY;
|
|
59122
|
+
startNoteRenderer.scoreRenderer.layout.slurRegistry.startMultiSystemSlur(this);
|
|
59123
|
+
}
|
|
59124
|
+
else {
|
|
59125
|
+
this._endX = this.calculateEndX();
|
|
59126
|
+
this._endY = this.caclculateEndY();
|
|
59127
|
+
}
|
|
59128
|
+
}
|
|
59129
|
+
else {
|
|
59130
|
+
this._shouldPaint = true;
|
|
59131
|
+
this._startX = this.calculateStartX();
|
|
59132
|
+
this._endX = this.calculateEndX();
|
|
59133
|
+
this._startY = this.calculateStartY();
|
|
59134
|
+
this._endY = this.caclculateEndY();
|
|
59135
|
+
}
|
|
59136
|
+
this._shouldPaint = true;
|
|
59137
|
+
}
|
|
59138
|
+
else if (startNoteRenderer.staff !== endNoteRenderer.staff) {
|
|
59139
|
+
const firstRendererInStaff = startNoteRenderer.staff.barRenderers[0];
|
|
59140
|
+
this._startX = firstRendererInStaff.x;
|
|
59141
|
+
this._endX = this.calculateEndX();
|
|
59142
|
+
const startGlyph = startNoteRenderer.scoreRenderer.layout.slurRegistry.completeMultiSystemSlur(this);
|
|
59143
|
+
if (startGlyph) {
|
|
59144
|
+
this._startY = startGlyph.calculateMultiSystemSlurY(endNoteRenderer);
|
|
59145
|
+
}
|
|
59146
|
+
else {
|
|
59147
|
+
this._startY = this.caclculateEndY();
|
|
59148
|
+
}
|
|
59149
|
+
this._endY = this.caclculateEndY();
|
|
59150
|
+
this._shouldPaint = startNoteRenderer.staff !== endNoteRenderer.staff;
|
|
59151
|
+
}
|
|
59152
|
+
this._boundingBox = undefined;
|
|
59153
|
+
this.y = Math.min(this._startY, this._endY);
|
|
59154
|
+
if (this.shouldDrawBendSlur()) {
|
|
59155
|
+
this._tieHeight = 0; // TODO: Bend slur height to be considered?
|
|
59156
|
+
}
|
|
59157
|
+
else {
|
|
59158
|
+
this._tieHeight = this.getTieHeight(this._startX, this._startY, this._endX, this._endY);
|
|
59159
|
+
const tieBoundingBox = TieGlyph.calculateActualTieHeight(1, this._startX, this._startY, this._endX, this._endY, this.tieDirection === BeamDirection.Down, this._tieHeight, this.renderer.smuflMetrics.tieMidpointThickness);
|
|
59160
|
+
this._boundingBox = tieBoundingBox;
|
|
59161
|
+
this.height = tieBoundingBox.h;
|
|
59162
|
+
if (this.tieDirection === BeamDirection.Up) {
|
|
59163
|
+
// the tie might go above `this.y` due to its shape
|
|
59164
|
+
// here we calculate how much this is so we can consider the
|
|
59165
|
+
// respective overflow
|
|
59166
|
+
const overlap = this.y - tieBoundingBox.y;
|
|
59167
|
+
if (overlap > 0) {
|
|
59168
|
+
this.y -= overlap;
|
|
59169
|
+
}
|
|
59170
|
+
}
|
|
59171
|
+
}
|
|
59172
|
+
}
|
|
59173
|
+
paint(cx, cy, canvas) {
|
|
59174
|
+
if (!this._shouldPaint) {
|
|
59175
|
+
return;
|
|
59176
|
+
}
|
|
59177
|
+
if (this.shouldDrawBendSlur()) {
|
|
59178
|
+
TieGlyph.drawBendSlur(canvas, cx + this._startX, cy + this._startY, cx + this._endX, cy + this._endY, this.tieDirection === BeamDirection.Down, 1, this.renderer.smuflMetrics.tieHeight);
|
|
59179
|
+
}
|
|
59180
|
+
else {
|
|
59181
|
+
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);
|
|
59182
|
+
}
|
|
59183
|
+
}
|
|
59184
|
+
getTieHeight(_startX, _startY, _endX, _endY) {
|
|
59185
|
+
return this.renderer.smuflMetrics.tieHeight;
|
|
59186
|
+
}
|
|
59187
|
+
calculateMultiSystemSlurY(renderer) {
|
|
59188
|
+
const startRenderer = this.lookupStartBeatRenderer();
|
|
59189
|
+
const startY = this.calculateStartY();
|
|
59190
|
+
const relY = startY - startRenderer.y;
|
|
59191
|
+
return renderer.y + relY;
|
|
59192
|
+
}
|
|
59193
|
+
shouldCreateMultiSystemSlur(renderer) {
|
|
59194
|
+
const endStaff = this.lookupEndBeatRenderer()?.staff;
|
|
59195
|
+
if (!endStaff) {
|
|
59196
|
+
return true;
|
|
59197
|
+
}
|
|
59198
|
+
return renderer.staff.system.index < endStaff.system.index;
|
|
59199
|
+
}
|
|
59200
|
+
static calculateActualTieHeight(scale, x1, y1, x2, y2, down, offset, size) {
|
|
59201
|
+
const cp = TieGlyph._computeBezierControlPoints(scale, x1, y1, x2, y2, down, offset, size);
|
|
59202
|
+
if (cp.length === 0) {
|
|
59203
|
+
return new Bounds(x1, y1, x2 - x1, y2 - y1);
|
|
59204
|
+
}
|
|
59205
|
+
// For a musical tie/slur, the extrema occur predictably near the midpoint
|
|
59206
|
+
// Evaluate at midpoint (t=0.5) and check endpoints
|
|
59207
|
+
const p0x = cp[0];
|
|
59208
|
+
const p0y = cp[1];
|
|
59209
|
+
const c1x = cp[2];
|
|
59210
|
+
const c1y = cp[3];
|
|
59211
|
+
const c2x = cp[4];
|
|
59212
|
+
const c2y = cp[5];
|
|
59213
|
+
const p1x = cp[6];
|
|
59214
|
+
const p1y = cp[7];
|
|
59215
|
+
// Evaluate at t=0.5 for midpoint
|
|
59216
|
+
const midX = 0.125 * p0x + 0.375 * c1x + 0.375 * c2x + 0.125 * p1x;
|
|
59217
|
+
const midY = 0.125 * p0y + 0.375 * c1y + 0.375 * c2y + 0.125 * p1y;
|
|
59218
|
+
// Bounds are simply min/max of start, end, and midpoint
|
|
59219
|
+
const xMin = Math.min(p0x, p1x, midX);
|
|
59220
|
+
const xMax = Math.max(p0x, p1x, midX);
|
|
59221
|
+
let yMin = Math.min(p0y, p1y, midY);
|
|
59222
|
+
let yMax = Math.max(p0y, p1y, midY);
|
|
59223
|
+
// Account for thickness of the tie/slur
|
|
59224
|
+
if (down) {
|
|
59225
|
+
yMax += size;
|
|
59226
|
+
}
|
|
59227
|
+
else {
|
|
59228
|
+
yMin -= size;
|
|
59229
|
+
}
|
|
59230
|
+
const b = new Bounds();
|
|
59231
|
+
b.x = xMin;
|
|
59232
|
+
b.y = yMin;
|
|
59233
|
+
b.w = xMax - xMin;
|
|
59234
|
+
b.h = yMax - yMin;
|
|
59235
|
+
return b;
|
|
59236
|
+
}
|
|
59237
|
+
static _computeBezierControlPoints(scale, x1, y1, x2, y2, down, offset, size) {
|
|
59238
|
+
if (x1 === x2 && y1 === y2) {
|
|
59239
|
+
return [];
|
|
59240
|
+
}
|
|
59241
|
+
// ensure endX > startX
|
|
59242
|
+
if (x2 < x1) {
|
|
59243
|
+
let t = x1;
|
|
59244
|
+
x1 = x2;
|
|
59245
|
+
x2 = t;
|
|
59246
|
+
t = y1;
|
|
59247
|
+
y1 = y2;
|
|
59248
|
+
y2 = t;
|
|
59249
|
+
}
|
|
59250
|
+
//
|
|
59251
|
+
// calculate control points
|
|
59252
|
+
//
|
|
59253
|
+
offset *= scale;
|
|
59254
|
+
size *= scale;
|
|
59255
|
+
if (down) {
|
|
59256
|
+
offset *= -1;
|
|
59257
|
+
size *= -1;
|
|
59258
|
+
}
|
|
59259
|
+
if (scale >= 1) {
|
|
59260
|
+
size *= 1.2;
|
|
59261
|
+
}
|
|
59262
|
+
// calculate control points on horizontal axis then rotate:
|
|
59263
|
+
/*
|
|
59264
|
+
cp1x/cpy1 cp2x/cpy2
|
|
59265
|
+
*----------------*
|
|
59266
|
+
/ \
|
|
59267
|
+
/ \
|
|
59268
|
+
x1/y1 * * x2/y2
|
|
59269
|
+
|
|
59270
|
+
cp3 and cp4 are simply with lower height
|
|
59271
|
+
*/
|
|
59272
|
+
const dY = y2 - y1;
|
|
59273
|
+
const dX = x2 - x1;
|
|
59274
|
+
const length = Math.sqrt(dX * dX + dY * dY);
|
|
59275
|
+
let cp1x = x1 + length * 0.25;
|
|
59276
|
+
let cp1y = y1 - offset;
|
|
59277
|
+
let cp2x = x1 + length * 0.75;
|
|
59278
|
+
let cp2y = y1 - offset;
|
|
59279
|
+
let cp3x = x1 + length * 0.75;
|
|
59280
|
+
let cp3y = y1 - offset - size;
|
|
59281
|
+
let cp4x = x1 + length * 0.25;
|
|
59282
|
+
let cp4y = y1 - offset - size;
|
|
59283
|
+
const angle = Math.atan2(dY, dX);
|
|
59284
|
+
[cp1x, cp1y] = TieGlyph._rotate(cp1x, cp1y, x1, y1, angle);
|
|
59285
|
+
[cp2x, cp2y] = TieGlyph._rotate(cp2x, cp2y, x1, y1, angle);
|
|
59286
|
+
[cp3x, cp3y] = TieGlyph._rotate(cp3x, cp3y, x1, y1, angle);
|
|
59287
|
+
[cp4x, cp4y] = TieGlyph._rotate(cp4x, cp4y, x1, y1, angle);
|
|
59288
|
+
return [x1, y1, cp1x, cp1y, cp2x, cp2y, x2, y2, cp3x, cp3y, cp4x, cp4y, x1, y1];
|
|
59289
|
+
}
|
|
59290
|
+
static _rotate(x, y, rotateX, rotateY, angle) {
|
|
59291
|
+
const dx = x - rotateX;
|
|
59292
|
+
const dy = y - rotateY;
|
|
59293
|
+
const rx = dx * Math.cos(angle) - dy * Math.sin(angle);
|
|
59294
|
+
const ry = dx * Math.sin(angle) + dy * Math.cos(angle);
|
|
59295
|
+
return [rotateX + rx, rotateY + ry];
|
|
59296
|
+
}
|
|
59297
|
+
static paintTie(canvas, scale, x1, y1, x2, y2, down /*= false*/, offset /*= 22*/, size /*= 4*/) {
|
|
59298
|
+
const cps = TieGlyph._computeBezierControlPoints(scale, x1, y1, x2, y2, down, offset, size);
|
|
59299
|
+
canvas.beginPath();
|
|
59300
|
+
canvas.moveTo(cps[0], cps[1]);
|
|
59301
|
+
canvas.bezierCurveTo(cps[2], cps[3], cps[4], cps[5], cps[6], cps[7]);
|
|
59302
|
+
canvas.bezierCurveTo(cps[8], cps[9], cps[10], cps[11], cps[12], cps[13]);
|
|
59303
|
+
canvas.closePath();
|
|
59304
|
+
canvas.fill();
|
|
59305
|
+
}
|
|
59306
|
+
static calculateBendSlurTopY(x1, y1, x2, y2, down, scale, bendSlurHeight) {
|
|
59307
|
+
let normalVectorX = y2 - y1;
|
|
59308
|
+
let normalVectorY = x2 - x1;
|
|
59309
|
+
const length = Math.sqrt(normalVectorX * normalVectorX + normalVectorY * normalVectorY);
|
|
59310
|
+
if (down) {
|
|
59311
|
+
normalVectorX *= -1;
|
|
59312
|
+
}
|
|
59313
|
+
else {
|
|
59314
|
+
normalVectorY *= -1;
|
|
59315
|
+
}
|
|
59316
|
+
// make to unit vector
|
|
59317
|
+
normalVectorX /= length;
|
|
59318
|
+
normalVectorY /= length;
|
|
59319
|
+
let offset = bendSlurHeight * scale;
|
|
59320
|
+
if (x2 - x1 < 20) {
|
|
59321
|
+
offset /= 2;
|
|
59322
|
+
}
|
|
59323
|
+
const centerY = (y2 + y1) / 2;
|
|
59324
|
+
const cp1Y = centerY + offset * normalVectorY;
|
|
59325
|
+
return cp1Y;
|
|
59326
|
+
}
|
|
59327
|
+
static drawBendSlur(canvas, x1, y1, x2, y2, down, scale, bendSlurHeight, slurText) {
|
|
59328
|
+
let normalVectorX = y2 - y1;
|
|
59329
|
+
let normalVectorY = x2 - x1;
|
|
59330
|
+
const length = Math.sqrt(normalVectorX * normalVectorX + normalVectorY * normalVectorY);
|
|
59331
|
+
if (down) {
|
|
59332
|
+
normalVectorX *= -1;
|
|
59333
|
+
}
|
|
59334
|
+
else {
|
|
59335
|
+
normalVectorY *= -1;
|
|
59336
|
+
}
|
|
59337
|
+
// make to unit vector
|
|
59338
|
+
normalVectorX /= length;
|
|
59339
|
+
normalVectorY /= length;
|
|
59340
|
+
// center of connection
|
|
59341
|
+
// TODO: should be 1/3
|
|
59342
|
+
const centerX = (x2 + x1) / 2;
|
|
59343
|
+
const centerY = (y2 + y1) / 2;
|
|
59344
|
+
let offset = bendSlurHeight * scale;
|
|
59345
|
+
if (x2 - x1 < 20) {
|
|
59346
|
+
offset /= 2;
|
|
59347
|
+
}
|
|
59348
|
+
const cp1X = centerX + offset * normalVectorX;
|
|
59349
|
+
const cp1Y = centerY + offset * normalVectorY;
|
|
59350
|
+
canvas.beginPath();
|
|
59351
|
+
canvas.moveTo(x1, y1);
|
|
59352
|
+
canvas.lineTo(cp1X, cp1Y);
|
|
59353
|
+
canvas.lineTo(x2, y2);
|
|
59354
|
+
canvas.stroke();
|
|
59355
|
+
if (slurText) {
|
|
59356
|
+
const w = canvas.measureText(slurText).width;
|
|
59357
|
+
const textOffset = down ? 0 : -canvas.font.size;
|
|
59358
|
+
canvas.fillText(slurText, cp1X - w / 2, cp1Y + textOffset);
|
|
59359
|
+
}
|
|
59360
|
+
}
|
|
59361
|
+
}
|
|
59362
|
+
/**
|
|
59363
|
+
* A common tie implementation using note details for positioning
|
|
59364
|
+
* @internal
|
|
59365
|
+
*/
|
|
59366
|
+
class NoteTieGlyph extends TieGlyph {
|
|
59367
|
+
startNote;
|
|
59368
|
+
endNote;
|
|
59369
|
+
startNoteRenderer = null;
|
|
59370
|
+
endNoteRenderer = null;
|
|
59371
|
+
constructor(slurEffectId, startNote, endNote, forEnd) {
|
|
59372
|
+
super(slurEffectId, forEnd);
|
|
59373
|
+
this.startNote = startNote;
|
|
59374
|
+
this.endNote = endNote;
|
|
59375
|
+
}
|
|
59376
|
+
get isLeftHandTap() {
|
|
59377
|
+
return this.startNote === this.endNote;
|
|
59378
|
+
}
|
|
59379
|
+
getTieHeight(startX, startY, endX, endY) {
|
|
59380
|
+
if (this.isLeftHandTap) {
|
|
59381
|
+
return this.renderer.smuflMetrics.tieHeight;
|
|
59382
|
+
}
|
|
59383
|
+
return super.getTieHeight(startX, startY, endX, endY);
|
|
59384
|
+
}
|
|
59385
|
+
calculateTieDirection() {
|
|
59386
|
+
// invert direction (if stems go up, ties go down to not cross them)
|
|
59387
|
+
switch (this.lookupStartBeatRenderer().getBeatDirection(this.startNote.beat)) {
|
|
59388
|
+
case BeamDirection.Up:
|
|
59389
|
+
return BeamDirection.Down;
|
|
59390
|
+
default:
|
|
59391
|
+
return BeamDirection.Up;
|
|
59392
|
+
}
|
|
59393
|
+
}
|
|
59394
|
+
calculateStartX() {
|
|
59395
|
+
const startNoteRenderer = this.lookupStartBeatRenderer();
|
|
59396
|
+
if (this.isLeftHandTap) {
|
|
59397
|
+
return this.calculateEndX() - startNoteRenderer.smuflMetrics.leftHandTabTieWidth;
|
|
59398
|
+
}
|
|
59399
|
+
return startNoteRenderer.x + startNoteRenderer.getNoteX(this.startNote, this.getStartNotePosition());
|
|
59400
|
+
}
|
|
59401
|
+
getStartNotePosition() {
|
|
59402
|
+
return NoteXPosition.Center;
|
|
59403
|
+
}
|
|
59404
|
+
calculateStartY() {
|
|
59405
|
+
const startNoteRenderer = this.lookupStartBeatRenderer();
|
|
59406
|
+
if (this.isLeftHandTap) {
|
|
59407
|
+
return startNoteRenderer.y + startNoteRenderer.getNoteY(this.startNote, NoteYPosition.Center);
|
|
59408
|
+
}
|
|
59409
|
+
switch (this.tieDirection) {
|
|
59410
|
+
case BeamDirection.Up:
|
|
59411
|
+
return startNoteRenderer.y + startNoteRenderer.getNoteY(this.startNote, NoteYPosition.Top);
|
|
59412
|
+
default:
|
|
59413
|
+
return startNoteRenderer.y + startNoteRenderer.getNoteY(this.startNote, NoteYPosition.Bottom);
|
|
59414
|
+
}
|
|
59415
|
+
}
|
|
59416
|
+
calculateEndX() {
|
|
59417
|
+
const endNoteRenderer = this.lookupEndBeatRenderer();
|
|
59418
|
+
if (!endNoteRenderer) {
|
|
59419
|
+
return this.calculateStartY() + this.renderer.smuflMetrics.leftHandTabTieWidth;
|
|
59420
|
+
}
|
|
59421
|
+
if (this.isLeftHandTap) {
|
|
59422
|
+
return endNoteRenderer.x + endNoteRenderer.getNoteX(this.endNote, NoteXPosition.Left);
|
|
59423
|
+
}
|
|
59424
|
+
return endNoteRenderer.x + endNoteRenderer.getNoteX(this.endNote, NoteXPosition.Center);
|
|
59425
|
+
}
|
|
59426
|
+
getEndNotePosition() {
|
|
59427
|
+
return NoteXPosition.Center;
|
|
59428
|
+
}
|
|
59429
|
+
caclculateEndY() {
|
|
59430
|
+
const endNoteRenderer = this.lookupEndBeatRenderer();
|
|
59431
|
+
if (!endNoteRenderer) {
|
|
59432
|
+
return this.calculateStartY();
|
|
59433
|
+
}
|
|
59434
|
+
if (this.isLeftHandTap) {
|
|
59435
|
+
return endNoteRenderer.y + endNoteRenderer.getNoteY(this.endNote, NoteYPosition.Center);
|
|
59436
|
+
}
|
|
59437
|
+
switch (this.tieDirection) {
|
|
59438
|
+
case BeamDirection.Up:
|
|
59439
|
+
return endNoteRenderer.y + endNoteRenderer.getNoteY(this.endNote, NoteYPosition.Top);
|
|
59440
|
+
default:
|
|
59441
|
+
return endNoteRenderer.y + endNoteRenderer.getNoteY(this.endNote, NoteYPosition.Bottom);
|
|
59442
|
+
}
|
|
59443
|
+
}
|
|
59444
|
+
lookupEndBeatRenderer() {
|
|
59445
|
+
if (!this.endNoteRenderer) {
|
|
59446
|
+
this.endNoteRenderer = this.renderer.scoreRenderer.layout.getRendererForBar(this.renderer.staff.staffId, this.endNote.beat.voice.bar);
|
|
59447
|
+
}
|
|
59448
|
+
return this.endNoteRenderer;
|
|
59449
|
+
}
|
|
59450
|
+
lookupStartBeatRenderer() {
|
|
59451
|
+
if (!this.startNoteRenderer) {
|
|
59452
|
+
this.startNoteRenderer = this.renderer.scoreRenderer.layout.getRendererForBar(this.renderer.staff.staffId, this.startNote.beat.voice.bar);
|
|
59453
|
+
}
|
|
59454
|
+
return this.startNoteRenderer;
|
|
59455
|
+
}
|
|
59456
|
+
shouldDrawBendSlur() {
|
|
59457
|
+
return false;
|
|
59458
|
+
}
|
|
59459
|
+
}
|
|
59460
|
+
/**
|
|
59461
|
+
* A tie glyph for continued multi-system ties/slurs
|
|
59462
|
+
* @internal
|
|
59463
|
+
*/
|
|
59464
|
+
class ContinuationTieGlyph extends TieGlyph {
|
|
59465
|
+
_startTie;
|
|
59466
|
+
constructor(startTie) {
|
|
59467
|
+
super(startTie.slurEffectId, false);
|
|
59468
|
+
this._startTie = startTie;
|
|
59469
|
+
}
|
|
59470
|
+
lookupStartBeatRenderer() {
|
|
59471
|
+
return this.renderer;
|
|
59472
|
+
}
|
|
59473
|
+
lookupEndBeatRenderer() {
|
|
59474
|
+
return this.renderer;
|
|
59475
|
+
}
|
|
59476
|
+
shouldDrawBendSlur() {
|
|
59477
|
+
return false;
|
|
59478
|
+
}
|
|
59479
|
+
calculateTieDirection() {
|
|
59480
|
+
return this._startTie.tieDirection;
|
|
59481
|
+
}
|
|
59482
|
+
calculateStartY() {
|
|
59483
|
+
return this._startTie.calculateMultiSystemSlurY(this.renderer);
|
|
59484
|
+
}
|
|
59485
|
+
caclculateEndY() {
|
|
59486
|
+
return this.calculateStartY();
|
|
59487
|
+
}
|
|
59488
|
+
calculateStartX() {
|
|
59489
|
+
return this.renderer.staff.barRenderers[0].x;
|
|
59490
|
+
}
|
|
59491
|
+
calculateEndX() {
|
|
59492
|
+
const last = this.renderer.staff.barRenderers[this.renderer.staff.barRenderers.length - 1];
|
|
59493
|
+
return last.x + last.width;
|
|
59494
|
+
}
|
|
59495
|
+
}
|
|
59496
|
+
|
|
59060
59497
|
/**
|
|
59061
59498
|
* This glyph acts as container for handling
|
|
59062
59499
|
* multiple voice rendering
|
|
@@ -59527,6 +59964,63 @@ class TuningGlyph extends GlyphGroup {
|
|
|
59527
59964
|
}
|
|
59528
59965
|
}
|
|
59529
59966
|
|
|
59967
|
+
/**
|
|
59968
|
+
* This registry keeps track of which slurs and ties were started and needs completion.
|
|
59969
|
+
* Slurs might span multiple systems, and in such cases we need to create additional
|
|
59970
|
+
* slur/ties in the intermediate and end system.
|
|
59971
|
+
*
|
|
59972
|
+
* @internal
|
|
59973
|
+
*
|
|
59974
|
+
*/
|
|
59975
|
+
class SlurRegistry {
|
|
59976
|
+
_staffLookup = new Map();
|
|
59977
|
+
clear() {
|
|
59978
|
+
this._staffLookup.clear();
|
|
59979
|
+
}
|
|
59980
|
+
startMultiSystemSlur(startGlyph) {
|
|
59981
|
+
const staffId = SlurRegistry._staffId(startGlyph.renderer.staff);
|
|
59982
|
+
let container;
|
|
59983
|
+
if (!this._staffLookup.has(staffId)) {
|
|
59984
|
+
container = {
|
|
59985
|
+
startedSlurs: new Map()
|
|
59986
|
+
};
|
|
59987
|
+
this._staffLookup.set(staffId, container);
|
|
59988
|
+
}
|
|
59989
|
+
else {
|
|
59990
|
+
container = this._staffLookup.get(staffId);
|
|
59991
|
+
}
|
|
59992
|
+
container.startedSlurs.set(startGlyph.slurEffectId, { startGlyph });
|
|
59993
|
+
}
|
|
59994
|
+
static _staffId(staff) {
|
|
59995
|
+
return `${staff.modelStaff.index}.${staff.modelStaff.track.index}.${staff.staffId}`;
|
|
59996
|
+
}
|
|
59997
|
+
completeMultiSystemSlur(endGlyph) {
|
|
59998
|
+
const staffId = SlurRegistry._staffId(endGlyph.renderer.staff);
|
|
59999
|
+
if (!this._staffLookup.has(staffId)) {
|
|
60000
|
+
return undefined;
|
|
60001
|
+
}
|
|
60002
|
+
const container = this._staffLookup.get(staffId);
|
|
60003
|
+
if (container.startedSlurs.has(endGlyph.slurEffectId)) {
|
|
60004
|
+
const info = container.startedSlurs.get(endGlyph.slurEffectId);
|
|
60005
|
+
info.endGlyph = endGlyph;
|
|
60006
|
+
return info.startGlyph;
|
|
60007
|
+
}
|
|
60008
|
+
return undefined;
|
|
60009
|
+
}
|
|
60010
|
+
*getAllContinuations(renderer) {
|
|
60011
|
+
const staffId = SlurRegistry._staffId(renderer.staff);
|
|
60012
|
+
if (!this._staffLookup.has(staffId) || renderer.index > 0) {
|
|
60013
|
+
return;
|
|
60014
|
+
}
|
|
60015
|
+
const container = this._staffLookup.get(staffId);
|
|
60016
|
+
for (const g of container.startedSlurs.values()) {
|
|
60017
|
+
if (g.startGlyph.shouldCreateMultiSystemSlur(renderer)) {
|
|
60018
|
+
yield g.startGlyph;
|
|
60019
|
+
}
|
|
60020
|
+
}
|
|
60021
|
+
}
|
|
60022
|
+
}
|
|
60023
|
+
|
|
59530
60024
|
/**
|
|
59531
60025
|
* A Staff represents a single line within a StaffSystem.
|
|
59532
60026
|
* It stores BarRenderer instances created from a given factory.
|
|
@@ -59648,7 +60142,6 @@ class RenderStaff {
|
|
|
59648
60142
|
this._sharedLayoutData = new Map();
|
|
59649
60143
|
const lastBar = this.barRenderers[this.barRenderers.length - 1];
|
|
59650
60144
|
this.barRenderers.splice(this.barRenderers.length - 1, 1);
|
|
59651
|
-
this.system.layout.unregisterBarRenderer(this.staffId, lastBar);
|
|
59652
60145
|
this.topOverflow = 0;
|
|
59653
60146
|
this.bottomOverflow = 0;
|
|
59654
60147
|
for (const r of this.barRenderers) {
|
|
@@ -59741,23 +60234,23 @@ class RenderStaff {
|
|
|
59741
60234
|
// changes in the overflows
|
|
59742
60235
|
let needsSecondPass = false;
|
|
59743
60236
|
let topOverflow = this.topOverflow;
|
|
59744
|
-
for (
|
|
59745
|
-
this.
|
|
59746
|
-
if (
|
|
60237
|
+
for (const renderer of this.barRenderers) {
|
|
60238
|
+
renderer.registerMultiSystemSlurs(this.system.layout.slurRegistry.getAllContinuations(renderer));
|
|
60239
|
+
if (renderer.finalizeRenderer()) {
|
|
59747
60240
|
needsSecondPass = true;
|
|
59748
60241
|
}
|
|
59749
|
-
this.height = Math.max(this.height,
|
|
60242
|
+
this.height = Math.max(this.height, renderer.height);
|
|
59750
60243
|
}
|
|
59751
60244
|
// 2nd pass: move renderers to correct position respecting the new overflows
|
|
59752
60245
|
if (needsSecondPass) {
|
|
59753
60246
|
topOverflow = this.topOverflow;
|
|
59754
60247
|
// shift all the renderers to the new position to match required spacing
|
|
59755
|
-
for (
|
|
59756
|
-
|
|
60248
|
+
for (const renderer of this.barRenderers) {
|
|
60249
|
+
renderer.y = this.topPadding + topOverflow;
|
|
59757
60250
|
}
|
|
59758
60251
|
// finalize again (to align ties)
|
|
59759
|
-
for (
|
|
59760
|
-
|
|
60252
|
+
for (const renderer of this.barRenderers) {
|
|
60253
|
+
renderer.finalizeRenderer();
|
|
59761
60254
|
}
|
|
59762
60255
|
}
|
|
59763
60256
|
if (this.height > 0) {
|
|
@@ -60363,6 +60856,7 @@ class StaffSystem {
|
|
|
60363
60856
|
if (newBarDisplayScale > barDisplayScale) {
|
|
60364
60857
|
barDisplayScale = newBarDisplayScale;
|
|
60365
60858
|
}
|
|
60859
|
+
lastBar.afterReverted();
|
|
60366
60860
|
}
|
|
60367
60861
|
this.width -= width;
|
|
60368
60862
|
this.computedWidth -= width;
|
|
@@ -60882,12 +61376,16 @@ class ScoreLayout {
|
|
|
60882
61376
|
constructor(renderer) {
|
|
60883
61377
|
this.renderer = renderer;
|
|
60884
61378
|
}
|
|
61379
|
+
slurRegistry = new SlurRegistry();
|
|
60885
61380
|
resize() {
|
|
60886
61381
|
this._lazyPartials.clear();
|
|
61382
|
+
this.slurRegistry.clear();
|
|
60887
61383
|
this.doResize();
|
|
60888
61384
|
}
|
|
60889
61385
|
layoutAndRender() {
|
|
60890
61386
|
this._lazyPartials.clear();
|
|
61387
|
+
this.slurRegistry.clear();
|
|
61388
|
+
this._barRendererLookup.clear();
|
|
60891
61389
|
this.profile = Environment.staveProfiles.get(this.renderer.settings.display.staveProfile);
|
|
60892
61390
|
const score = this.renderer.score;
|
|
60893
61391
|
this.firstBarIndex = ModelUtils.computeFirstDisplayedBarIndex(score, this.renderer.settings);
|
|
@@ -61156,17 +61654,6 @@ class ScoreLayout {
|
|
|
61156
61654
|
}
|
|
61157
61655
|
}
|
|
61158
61656
|
}
|
|
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
61657
|
getRendererForBar(key, bar) {
|
|
61171
61658
|
const barRendererId = bar.id;
|
|
61172
61659
|
if (this._barRendererLookup.has(key) && this._barRendererLookup.get(key).has(barRendererId)) {
|
|
@@ -61332,7 +61819,8 @@ class BeatGlyphBase extends GlyphGroup {
|
|
|
61332
61819
|
*/
|
|
61333
61820
|
class BeatOnNoteGlyphBase extends BeatGlyphBase {
|
|
61334
61821
|
beamingHelper;
|
|
61335
|
-
|
|
61822
|
+
onTimeX = 0;
|
|
61823
|
+
middleX = 0;
|
|
61336
61824
|
updateBeamingHelper() {
|
|
61337
61825
|
}
|
|
61338
61826
|
buildBoundingsLookup(_beatBounds, _cx, _cy) {
|
|
@@ -62155,6 +62643,7 @@ class BarRendererBase {
|
|
|
62155
62643
|
_voiceContainers = new Map();
|
|
62156
62644
|
_postBeatGlyphs = new LeftToRightLayoutingGlyphGroup();
|
|
62157
62645
|
_ties = [];
|
|
62646
|
+
_multiSystemSlurs;
|
|
62158
62647
|
topEffects;
|
|
62159
62648
|
bottomEffects;
|
|
62160
62649
|
get nextRenderer() {
|
|
@@ -62307,6 +62796,11 @@ class BarRendererBase {
|
|
|
62307
62796
|
}
|
|
62308
62797
|
}
|
|
62309
62798
|
_appliedLayoutingInfo = 0;
|
|
62799
|
+
afterReverted() {
|
|
62800
|
+
this.staff = undefined;
|
|
62801
|
+
this.registerMultiSystemSlurs(undefined);
|
|
62802
|
+
this.isFinalized = false;
|
|
62803
|
+
}
|
|
62310
62804
|
afterStaffBarReverted() {
|
|
62311
62805
|
this.topEffects.afterStaffBarReverted();
|
|
62312
62806
|
this.bottomEffects.afterStaffBarReverted();
|
|
@@ -62352,13 +62846,26 @@ class BarRendererBase {
|
|
|
62352
62846
|
return true;
|
|
62353
62847
|
}
|
|
62354
62848
|
isFinalized = false;
|
|
62355
|
-
|
|
62356
|
-
|
|
62849
|
+
registerMultiSystemSlurs(startedTies) {
|
|
62850
|
+
if (!startedTies) {
|
|
62851
|
+
this._multiSystemSlurs = undefined;
|
|
62852
|
+
return;
|
|
62853
|
+
}
|
|
62854
|
+
let ties = undefined;
|
|
62855
|
+
for (const g of startedTies) {
|
|
62856
|
+
const continuation = new ContinuationTieGlyph(g);
|
|
62857
|
+
continuation.renderer = this;
|
|
62858
|
+
continuation.tieDirection = g.tieDirection;
|
|
62859
|
+
if (!ties) {
|
|
62860
|
+
ties = [];
|
|
62861
|
+
}
|
|
62862
|
+
ties.push(continuation);
|
|
62863
|
+
}
|
|
62864
|
+
this._multiSystemSlurs = ties;
|
|
62865
|
+
}
|
|
62866
|
+
_finalizeTies(ties, barTop, barBottom) {
|
|
62357
62867
|
let didChangeOverflows = false;
|
|
62358
|
-
|
|
62359
|
-
const barTop = this.y;
|
|
62360
|
-
const barBottom = this.y + this.height;
|
|
62361
|
-
for (const t of this._ties) {
|
|
62868
|
+
for (const t of ties) {
|
|
62362
62869
|
const tie = t;
|
|
62363
62870
|
tie.doLayout();
|
|
62364
62871
|
if (t.checkForOverflow) {
|
|
@@ -62379,6 +62886,21 @@ class BarRendererBase {
|
|
|
62379
62886
|
}
|
|
62380
62887
|
}
|
|
62381
62888
|
}
|
|
62889
|
+
return didChangeOverflows;
|
|
62890
|
+
}
|
|
62891
|
+
finalizeRenderer() {
|
|
62892
|
+
this.isFinalized = true;
|
|
62893
|
+
let didChangeOverflows = false;
|
|
62894
|
+
// allow spacing to be used for tie overflows
|
|
62895
|
+
const barTop = this.y;
|
|
62896
|
+
const barBottom = this.y + this.height;
|
|
62897
|
+
if (this._finalizeTies(this._ties, barTop, barBottom)) {
|
|
62898
|
+
didChangeOverflows = true;
|
|
62899
|
+
}
|
|
62900
|
+
const multiSystemSlurs = this._multiSystemSlurs;
|
|
62901
|
+
if (multiSystemSlurs && this._finalizeTies(multiSystemSlurs, barTop, barBottom)) {
|
|
62902
|
+
didChangeOverflows = true;
|
|
62903
|
+
}
|
|
62382
62904
|
const topHeightChanged = this.topEffects.finalizeEffects();
|
|
62383
62905
|
const bottomHeightChanged = this.bottomEffects.finalizeEffects();
|
|
62384
62906
|
if (topHeightChanged || bottomHeightChanged) {
|
|
@@ -62559,6 +63081,16 @@ class BarRendererBase {
|
|
|
62559
63081
|
}
|
|
62560
63082
|
canvas.color = this.resources.mainGlyphColor;
|
|
62561
63083
|
this._postBeatGlyphs.paint(cx + this.x, cy + this.y, canvas);
|
|
63084
|
+
this._paintMultiSystemSlurs(cx, cy, canvas);
|
|
63085
|
+
}
|
|
63086
|
+
_paintMultiSystemSlurs(cx, cy, canvas) {
|
|
63087
|
+
const multiSystemSlurs = this._multiSystemSlurs;
|
|
63088
|
+
if (!multiSystemSlurs) {
|
|
63089
|
+
return;
|
|
63090
|
+
}
|
|
63091
|
+
for (const slur of multiSystemSlurs) {
|
|
63092
|
+
slur.paint(cx, cy, canvas);
|
|
63093
|
+
}
|
|
62562
63094
|
}
|
|
62563
63095
|
paintBackground(cx, cy, canvas) {
|
|
62564
63096
|
this.layoutingInfo.paint(cx + this.x + this._preBeatGlyphs.x + this._preBeatGlyphs.width, cy + this.y + this.height, canvas);
|
|
@@ -62624,7 +63156,7 @@ class BarRendererBase {
|
|
|
62624
63156
|
case BeatXPosition.OnNotes:
|
|
62625
63157
|
return container.voiceContainer.x + container.x + container.onNotes.x;
|
|
62626
63158
|
case BeatXPosition.MiddleNotes:
|
|
62627
|
-
return container.voiceContainer.x + container.x + container.
|
|
63159
|
+
return container.voiceContainer.x + container.x + container.onNotes.x + container.onNotes.middleX;
|
|
62628
63160
|
case BeatXPosition.Stem:
|
|
62629
63161
|
const offset = container.onNotes.beamingHelper
|
|
62630
63162
|
? container.onNotes.beamingHelper.getBeatLineX(beat)
|
|
@@ -64637,6 +65169,13 @@ class PageViewLayout extends ScoreLayout {
|
|
|
64637
65169
|
}
|
|
64638
65170
|
}
|
|
64639
65171
|
else {
|
|
65172
|
+
// clear out staves during re-layout, this info is outdated during
|
|
65173
|
+
// re-layout of the bars
|
|
65174
|
+
for (const r of this._allMasterBarRenderers) {
|
|
65175
|
+
for (const b of r.renderers) {
|
|
65176
|
+
b.afterReverted();
|
|
65177
|
+
}
|
|
65178
|
+
}
|
|
64640
65179
|
this._systems = [];
|
|
64641
65180
|
let currentIndex = 0;
|
|
64642
65181
|
const maxWidth = this._maxWidth;
|
|
@@ -65098,7 +65637,7 @@ class BarLineGlyph extends LeftToRightLayoutingGlyphGroup {
|
|
|
65098
65637
|
// as during layout things are still moving
|
|
65099
65638
|
let actualLineHeight = this.height;
|
|
65100
65639
|
const thisStaff = renderer.staff;
|
|
65101
|
-
const allStaves =
|
|
65640
|
+
const allStaves = thisStaff.system.allStaves;
|
|
65102
65641
|
let isExtended = false;
|
|
65103
65642
|
if (this._extendToNextStaff && thisStaff.index < allStaves.length - 1) {
|
|
65104
65643
|
const nextStaff = allStaves[thisStaff.index + 1];
|
|
@@ -65280,7 +65819,7 @@ class LineBarRenderer extends BarRendererBase {
|
|
|
65280
65819
|
}
|
|
65281
65820
|
// during system fitting it can happen that we have fraction widths
|
|
65282
65821
|
// but to have lines until the full end-pixel we round up.
|
|
65283
|
-
// this way we avoid holes,
|
|
65822
|
+
// this way we avoid holes,
|
|
65284
65823
|
const lineWidth = this.width;
|
|
65285
65824
|
// we want the lines to be exactly virtually aligned with the respective Y-position
|
|
65286
65825
|
// for note heads to align correctly
|
|
@@ -66046,375 +66585,23 @@ class LineBarRenderer extends BarRendererBase {
|
|
|
66046
66585
|
/**
|
|
66047
66586
|
* @internal
|
|
66048
66587
|
*/
|
|
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
|
-
}
|
|
66588
|
+
class NumberedTieGlyph extends NoteTieGlyph {
|
|
66365
66589
|
shouldDrawBendSlur() {
|
|
66366
66590
|
return (this.renderer.settings.notation.extendBendArrowsOnTiedNotes &&
|
|
66367
66591
|
!!this.startNote.bendOrigin &&
|
|
66368
66592
|
this.startNote.isTieOrigin);
|
|
66369
66593
|
}
|
|
66370
|
-
|
|
66371
|
-
super.doLayout();
|
|
66372
|
-
}
|
|
66373
|
-
getBeamDirection(_beat, _noteRenderer) {
|
|
66594
|
+
calculateTieDirection() {
|
|
66374
66595
|
return BeamDirection.Up;
|
|
66375
66596
|
}
|
|
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
66597
|
}
|
|
66395
66598
|
|
|
66396
66599
|
/**
|
|
66397
66600
|
* @internal
|
|
66398
66601
|
*/
|
|
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) {
|
|
66602
|
+
class TabTieGlyph extends NoteTieGlyph {
|
|
66603
|
+
calculateTieDirection() {
|
|
66604
|
+
if (this.isLeftHandTap) {
|
|
66418
66605
|
return BeamDirection.Up;
|
|
66419
66606
|
}
|
|
66420
66607
|
return TabTieGlyph.getBeamDirectionForNote(this.startNote);
|
|
@@ -66422,54 +66609,25 @@ class TabTieGlyph extends TieGlyph {
|
|
|
66422
66609
|
static getBeamDirectionForNote(note) {
|
|
66423
66610
|
return note.string > 3 ? BeamDirection.Up : BeamDirection.Down;
|
|
66424
66611
|
}
|
|
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
66612
|
}
|
|
66450
66613
|
|
|
66451
66614
|
/**
|
|
66452
66615
|
* @internal
|
|
66453
66616
|
*/
|
|
66454
|
-
class
|
|
66455
|
-
_direction;
|
|
66617
|
+
class TabSlurGlyph extends TabTieGlyph {
|
|
66456
66618
|
_forSlide;
|
|
66457
|
-
constructor(startNote, endNote, forSlide, forEnd
|
|
66458
|
-
super(startNote, endNote, forEnd);
|
|
66459
|
-
this._direction = BeamDirection.Up;
|
|
66619
|
+
constructor(slurEffectId, startNote, endNote, forSlide, forEnd) {
|
|
66620
|
+
super(slurEffectId, startNote, endNote, forEnd);
|
|
66460
66621
|
this._forSlide = forSlide;
|
|
66461
66622
|
}
|
|
66462
66623
|
getTieHeight(startX, _startY, endX, _endY) {
|
|
66463
|
-
return Math.log(endX - startX + 1) * this.renderer.settings.notation.slurHeight / 2;
|
|
66624
|
+
return (Math.log(endX - startX + 1) * this.renderer.settings.notation.slurHeight) / 2;
|
|
66464
66625
|
}
|
|
66465
66626
|
tryExpand(startNote, endNote, forSlide, forEnd) {
|
|
66466
66627
|
// same type required
|
|
66467
66628
|
if (this._forSlide !== forSlide) {
|
|
66468
66629
|
return false;
|
|
66469
66630
|
}
|
|
66470
|
-
if (this.forEnd !== forEnd) {
|
|
66471
|
-
return false;
|
|
66472
|
-
}
|
|
66473
66631
|
// same start and endbeat
|
|
66474
66632
|
if (this.startNote.beat.id !== startNote.beat.id) {
|
|
66475
66633
|
return false;
|
|
@@ -66477,41 +66635,43 @@ class NumberedSlurGlyph extends TabTieGlyph {
|
|
|
66477
66635
|
if (this.endNote.beat.id !== endNote.beat.id) {
|
|
66478
66636
|
return false;
|
|
66479
66637
|
}
|
|
66638
|
+
const isForEnd = this.renderer === this.lookupEndBeatRenderer();
|
|
66639
|
+
if (isForEnd !== forEnd) {
|
|
66640
|
+
return false;
|
|
66641
|
+
}
|
|
66642
|
+
// same draw direction
|
|
66643
|
+
if (this.tieDirection !== TabTieGlyph.getBeamDirectionForNote(startNote)) {
|
|
66644
|
+
return false;
|
|
66645
|
+
}
|
|
66480
66646
|
// if we can expand, expand in correct direction
|
|
66481
|
-
switch (this.
|
|
66647
|
+
switch (this.tieDirection) {
|
|
66482
66648
|
case BeamDirection.Up:
|
|
66483
66649
|
if (startNote.realValue > this.startNote.realValue) {
|
|
66484
66650
|
this.startNote = startNote;
|
|
66485
|
-
this.startBeat = startNote.beat;
|
|
66486
66651
|
}
|
|
66487
66652
|
if (endNote.realValue > this.endNote.realValue) {
|
|
66488
66653
|
this.endNote = endNote;
|
|
66489
|
-
this.endBeat = endNote.beat;
|
|
66490
66654
|
}
|
|
66491
66655
|
break;
|
|
66492
66656
|
case BeamDirection.Down:
|
|
66493
66657
|
if (startNote.realValue < this.startNote.realValue) {
|
|
66494
66658
|
this.startNote = startNote;
|
|
66495
|
-
this.startBeat = startNote.beat;
|
|
66496
66659
|
}
|
|
66497
66660
|
if (endNote.realValue < this.endNote.realValue) {
|
|
66498
66661
|
this.endNote = endNote;
|
|
66499
|
-
this.endBeat = endNote.beat;
|
|
66500
66662
|
}
|
|
66501
66663
|
break;
|
|
66502
66664
|
}
|
|
66503
66665
|
return true;
|
|
66504
66666
|
}
|
|
66505
|
-
|
|
66506
|
-
|
|
66507
|
-
|
|
66508
|
-
|
|
66509
|
-
|
|
66510
|
-
|
|
66511
|
-
|
|
66512
|
-
|
|
66513
|
-
super.paint(cx, cy, canvas);
|
|
66514
|
-
}
|
|
66667
|
+
}
|
|
66668
|
+
|
|
66669
|
+
/**
|
|
66670
|
+
* @internal
|
|
66671
|
+
*/
|
|
66672
|
+
class NumberedSlurGlyph extends TabSlurGlyph {
|
|
66673
|
+
calculateTieDirection() {
|
|
66674
|
+
return BeamDirection.Up;
|
|
66515
66675
|
}
|
|
66516
66676
|
}
|
|
66517
66677
|
|
|
@@ -66519,23 +66679,31 @@ class NumberedSlurGlyph extends TabTieGlyph {
|
|
|
66519
66679
|
* @internal
|
|
66520
66680
|
*/
|
|
66521
66681
|
class NumberedBeatContainerGlyph extends BeatContainerGlyph {
|
|
66682
|
+
_slurs = new Map();
|
|
66522
66683
|
_effectSlurs = [];
|
|
66684
|
+
doLayout() {
|
|
66685
|
+
this._slurs.clear();
|
|
66686
|
+
this._effectSlurs = [];
|
|
66687
|
+
super.doLayout();
|
|
66688
|
+
}
|
|
66523
66689
|
createTies(n) {
|
|
66524
66690
|
// create a tie if any effect requires it
|
|
66525
66691
|
if (!n.isVisible) {
|
|
66526
66692
|
return;
|
|
66527
66693
|
}
|
|
66528
|
-
if (n.isTieOrigin && n.tieDestination.isVisible) {
|
|
66529
|
-
const tie = new NumberedTieGlyph(n, n.tieDestination, false);
|
|
66694
|
+
if (n.isTieOrigin && n.tieDestination.isVisible && !this._slurs.has('numbered.tie')) {
|
|
66695
|
+
const tie = new NumberedTieGlyph(`numbered.tie.${n.beat.id}`, n, n.tieDestination, false);
|
|
66530
66696
|
this.addTie(tie);
|
|
66697
|
+
this._slurs.set(tie.slurEffectId, tie);
|
|
66531
66698
|
}
|
|
66532
66699
|
if (n.isTieDestination) {
|
|
66533
|
-
const tie = new NumberedTieGlyph(n.tieOrigin, n, true);
|
|
66700
|
+
const tie = new NumberedTieGlyph(`numbered.tie.${n.tieOrigin.beat.id}`, n.tieOrigin, n, true);
|
|
66534
66701
|
this.addTie(tie);
|
|
66535
66702
|
}
|
|
66536
|
-
if (n.isLeftHandTapped && !n.isHammerPullDestination) {
|
|
66537
|
-
const tapSlur = new NumberedTieGlyph(n, n, false);
|
|
66703
|
+
if (n.isLeftHandTapped && !n.isHammerPullDestination && !this._slurs.has(`numbered.tie.leftHandTap.${n.beat.id}`)) {
|
|
66704
|
+
const tapSlur = new NumberedTieGlyph(`numbered.tie.leftHandTap.${n.beat.id}`, n, n, false);
|
|
66538
66705
|
this.addTie(tapSlur);
|
|
66706
|
+
this._slurs.set(tapSlur.slurEffectId, tapSlur);
|
|
66539
66707
|
}
|
|
66540
66708
|
// start effect slur on first beat
|
|
66541
66709
|
if (n.isEffectSlurOrigin && n.effectSlurDestination) {
|
|
@@ -66547,9 +66715,11 @@ class NumberedBeatContainerGlyph extends BeatContainerGlyph {
|
|
|
66547
66715
|
}
|
|
66548
66716
|
}
|
|
66549
66717
|
if (!expanded) {
|
|
66550
|
-
const effectSlur = new NumberedSlurGlyph(n, n.effectSlurDestination, false, false);
|
|
66718
|
+
const effectSlur = new NumberedSlurGlyph(`numbered.slur.effect`, n, n.effectSlurDestination, false, false);
|
|
66551
66719
|
this._effectSlurs.push(effectSlur);
|
|
66552
66720
|
this.addTie(effectSlur);
|
|
66721
|
+
this._slurs.set(effectSlur.slurEffectId, effectSlur);
|
|
66722
|
+
this._slurs.set('numbered.slur.effect', effectSlur);
|
|
66553
66723
|
}
|
|
66554
66724
|
}
|
|
66555
66725
|
// end effect slur on last beat
|
|
@@ -66562,9 +66732,11 @@ class NumberedBeatContainerGlyph extends BeatContainerGlyph {
|
|
|
66562
66732
|
}
|
|
66563
66733
|
}
|
|
66564
66734
|
if (!expanded) {
|
|
66565
|
-
const effectSlur = new NumberedSlurGlyph(n.effectSlurOrigin, n, false, true);
|
|
66735
|
+
const effectSlur = new NumberedSlurGlyph(`numbered.slur.effect`, n.effectSlurOrigin, n, false, true);
|
|
66566
66736
|
this._effectSlurs.push(effectSlur);
|
|
66567
66737
|
this.addTie(effectSlur);
|
|
66738
|
+
this._slurs.set(effectSlur.slurEffectId, effectSlur);
|
|
66739
|
+
this._slurs.set('numbered.slur.effect', effectSlur);
|
|
66568
66740
|
}
|
|
66569
66741
|
}
|
|
66570
66742
|
}
|
|
@@ -66957,10 +67129,11 @@ class NumberedBeatGlyph extends BeatOnNoteGlyphBase {
|
|
|
66957
67129
|
if (sr.shortestDuration < this.container.beat.duration) {
|
|
66958
67130
|
sr.shortestDuration = this.container.beat.duration;
|
|
66959
67131
|
}
|
|
66960
|
-
const glyphY = sr.getLineY(sr.getNoteLine());
|
|
66961
67132
|
if (!this.container.beat.isEmpty) {
|
|
67133
|
+
const glyphY = sr.getLineY(0);
|
|
66962
67134
|
let numberWithinOctave = '0';
|
|
66963
67135
|
if (this.container.beat.notes.length > 0) {
|
|
67136
|
+
const note = this.container.beat.notes[0];
|
|
66964
67137
|
const kst = this.renderer.bar.keySignatureType;
|
|
66965
67138
|
const ks = this.renderer.bar.keySignature;
|
|
66966
67139
|
const ksi = ks + 7;
|
|
@@ -66968,7 +67141,6 @@ class NumberedBeatGlyph extends BeatOnNoteGlyphBase {
|
|
|
66968
67141
|
? NumberedBeatGlyph.minorKeySignatureOneValues
|
|
66969
67142
|
: NumberedBeatGlyph.majorKeySignatureOneValues;
|
|
66970
67143
|
const oneNoteValue = oneNoteValues[ksi];
|
|
66971
|
-
const note = this.container.beat.notes[0];
|
|
66972
67144
|
if (note.isDead) {
|
|
66973
67145
|
numberWithinOctave = 'X';
|
|
66974
67146
|
}
|
|
@@ -67015,7 +67187,7 @@ class NumberedBeatGlyph extends BeatOnNoteGlyphBase {
|
|
|
67015
67187
|
// Note dots
|
|
67016
67188
|
if (this.container.beat.dots > 0 && this.container.beat.duration >= Duration.Quarter) {
|
|
67017
67189
|
for (let i = 0; i < this.container.beat.dots; i++) {
|
|
67018
|
-
const dot = new AugmentationDotGlyph(0,
|
|
67190
|
+
const dot = new AugmentationDotGlyph(0, glyphY);
|
|
67019
67191
|
dot.renderer = this.renderer;
|
|
67020
67192
|
this.addEffect(dot);
|
|
67021
67193
|
}
|
|
@@ -67043,21 +67215,22 @@ class NumberedBeatGlyph extends BeatOnNoteGlyphBase {
|
|
|
67043
67215
|
numberOfQuarterNotes += numberOfAddedQuarters;
|
|
67044
67216
|
}
|
|
67045
67217
|
for (let i = 0; i < numberOfQuarterNotes - 1; i++) {
|
|
67046
|
-
const dash = new NumberedDashGlyph(0,
|
|
67218
|
+
const dash = new NumberedDashGlyph(0, glyphY, this.container.beat);
|
|
67047
67219
|
dash.renderer = this.renderer;
|
|
67048
67220
|
this.addNormal(dash);
|
|
67049
67221
|
}
|
|
67050
67222
|
}
|
|
67051
67223
|
super.doLayout();
|
|
67052
67224
|
if (this.container.beat.isEmpty) {
|
|
67053
|
-
this.
|
|
67225
|
+
this.onTimeX = this.width / 2;
|
|
67054
67226
|
}
|
|
67055
67227
|
else if (this.noteHeads) {
|
|
67056
|
-
this.
|
|
67228
|
+
this.onTimeX = this.noteHeads.x + this.noteHeads.width / 2;
|
|
67057
67229
|
}
|
|
67058
67230
|
else if (this.deadSlapped) {
|
|
67059
|
-
this.
|
|
67231
|
+
this.onTimeX = this.deadSlapped.x + this.deadSlapped.width / 2;
|
|
67060
67232
|
}
|
|
67233
|
+
this.middleX = this.onTimeX;
|
|
67061
67234
|
}
|
|
67062
67235
|
}
|
|
67063
67236
|
|
|
@@ -67513,7 +67686,7 @@ class NumberedBarRenderer extends LineBarRenderer {
|
|
|
67513
67686
|
}
|
|
67514
67687
|
}
|
|
67515
67688
|
}
|
|
67516
|
-
getNoteLine() {
|
|
67689
|
+
getNoteLine(_note) {
|
|
67517
67690
|
return 0;
|
|
67518
67691
|
}
|
|
67519
67692
|
get tupletOffset() {
|
|
@@ -67923,6 +68096,7 @@ class ScoreNoteChordGlyphBase extends Glyph {
|
|
|
67923
68096
|
upLineX = 0;
|
|
67924
68097
|
downLineX = 0;
|
|
67925
68098
|
noteStartX = 0;
|
|
68099
|
+
onTimeX = 0;
|
|
67926
68100
|
constructor() {
|
|
67927
68101
|
super(0, 0);
|
|
67928
68102
|
}
|
|
@@ -68009,6 +68183,8 @@ class ScoreNoteChordGlyphBase extends Glyph {
|
|
|
68009
68183
|
// align all notes so that they align with the stem positions
|
|
68010
68184
|
const stemPosition = anyDisplaced || direction === BeamDirection.Up ? stemUpX : stemDownX;
|
|
68011
68185
|
let w = 0;
|
|
68186
|
+
let displacedWidth = 0;
|
|
68187
|
+
let nonDisplacedWidth = 0;
|
|
68012
68188
|
for (let i = 0, j = this._infos.length; i < j; i++) {
|
|
68013
68189
|
const g = this._infos[i].glyph;
|
|
68014
68190
|
const alignDisplaced = displaced.get(i);
|
|
@@ -68024,7 +68200,14 @@ class ScoreNoteChordGlyphBase extends Glyph {
|
|
|
68024
68200
|
}
|
|
68025
68201
|
}
|
|
68026
68202
|
g.x += this.noteStartX;
|
|
68027
|
-
|
|
68203
|
+
const gw = g.x + g.width;
|
|
68204
|
+
w = Math.max(w, gw);
|
|
68205
|
+
if (alignDisplaced) {
|
|
68206
|
+
displacedWidth = Math.max(displacedWidth, gw);
|
|
68207
|
+
}
|
|
68208
|
+
else {
|
|
68209
|
+
nonDisplacedWidth = Math.max(nonDisplacedWidth, gw);
|
|
68210
|
+
}
|
|
68028
68211
|
// after size calculation, re-align glyph to stem if needed
|
|
68029
68212
|
if (g instanceof NoteHeadGlyph && g.centerOnStem) {
|
|
68030
68213
|
g.x = stemPosition;
|
|
@@ -68038,6 +68221,23 @@ class ScoreNoteChordGlyphBase extends Glyph {
|
|
|
68038
68221
|
this.upLineX = stemUpX;
|
|
68039
68222
|
this.downLineX = stemDownX;
|
|
68040
68223
|
}
|
|
68224
|
+
// the center of score notes, (used for aligning the beat to the right on-time position)
|
|
68225
|
+
// is always the center of the "correct note" position.
|
|
68226
|
+
// * If the stem is upwards, the center is the middle of the left hand side note head
|
|
68227
|
+
// * If the stem is downards, the center is the middle of the right-hand-side note head
|
|
68228
|
+
if (anyDisplaced) {
|
|
68229
|
+
if (direction === BeamDirection.Up) {
|
|
68230
|
+
this.onTimeX = nonDisplacedWidth / 2;
|
|
68231
|
+
}
|
|
68232
|
+
else {
|
|
68233
|
+
const displacedRawWith = displacedWidth - stemPosition;
|
|
68234
|
+
this.onTimeX = stemPosition + (displacedRawWith / 2);
|
|
68235
|
+
}
|
|
68236
|
+
}
|
|
68237
|
+
else {
|
|
68238
|
+
// for no displaced notes it is simply the center
|
|
68239
|
+
this.onTimeX = w / 2;
|
|
68240
|
+
}
|
|
68041
68241
|
this.width = w;
|
|
68042
68242
|
}
|
|
68043
68243
|
paint(cx, cy, canvas) {
|
|
@@ -68214,6 +68414,7 @@ class ScoreNoteChordGlyph extends ScoreNoteChordGlyphBase {
|
|
|
68214
68414
|
this._deadSlapped.renderer = this.renderer;
|
|
68215
68415
|
this._deadSlapped.doLayout();
|
|
68216
68416
|
this.width = this._deadSlapped.width;
|
|
68417
|
+
this.onTimeX = this.width / 2;
|
|
68217
68418
|
}
|
|
68218
68419
|
let aboveBeatEffectsY = 0;
|
|
68219
68420
|
let belowBeatEffectsY = 0;
|
|
@@ -69112,13 +69313,16 @@ class ScoreBeatGlyph extends BeatOnNoteGlyphBase {
|
|
|
69112
69313
|
}
|
|
69113
69314
|
super.doLayout();
|
|
69114
69315
|
if (this.container.beat.isEmpty) {
|
|
69115
|
-
this.
|
|
69316
|
+
this.onTimeX = this.width / 2;
|
|
69317
|
+
this.middleX = this.onTimeX;
|
|
69116
69318
|
}
|
|
69117
69319
|
else if (this.restGlyph) {
|
|
69118
|
-
this.
|
|
69320
|
+
this.onTimeX = this.restGlyph.x + this.restGlyph.width / 2;
|
|
69321
|
+
this.middleX = this.onTimeX;
|
|
69119
69322
|
}
|
|
69120
69323
|
else if (this.noteHeads) {
|
|
69121
|
-
this.
|
|
69324
|
+
this.onTimeX = this.noteHeads.x + this.noteHeads.onTimeX;
|
|
69325
|
+
this.middleX = this.noteHeads.x + this.noteHeads.width / 2;
|
|
69122
69326
|
}
|
|
69123
69327
|
}
|
|
69124
69328
|
_createBeatDot(line, group) {
|
|
@@ -69728,87 +69932,128 @@ class ScoreBendGlyph extends ScoreHelperNotesBaseGlyph {
|
|
|
69728
69932
|
* @internal
|
|
69729
69933
|
*/
|
|
69730
69934
|
class ScoreLegatoGlyph extends TieGlyph {
|
|
69731
|
-
|
|
69732
|
-
|
|
69935
|
+
startBeat;
|
|
69936
|
+
endBeat;
|
|
69937
|
+
startBeatRenderer = null;
|
|
69938
|
+
endBeatRenderer = null;
|
|
69939
|
+
constructor(slurEffectId, startBeat, endBeat, forEnd) {
|
|
69940
|
+
super(slurEffectId, forEnd);
|
|
69941
|
+
this.startBeat = startBeat;
|
|
69942
|
+
this.endBeat = endBeat;
|
|
69733
69943
|
}
|
|
69734
69944
|
doLayout() {
|
|
69735
69945
|
super.doLayout();
|
|
69736
69946
|
}
|
|
69737
|
-
|
|
69738
|
-
if (
|
|
69947
|
+
lookupStartBeatRenderer() {
|
|
69948
|
+
if (!this.startBeatRenderer) {
|
|
69949
|
+
this.startBeatRenderer = this.renderer.scoreRenderer.layout.getRendererForBar(this.renderer.staff.staffId, this.startBeat.voice.bar);
|
|
69950
|
+
}
|
|
69951
|
+
return this.startBeatRenderer;
|
|
69952
|
+
}
|
|
69953
|
+
lookupEndBeatRenderer() {
|
|
69954
|
+
if (!this.endBeatRenderer) {
|
|
69955
|
+
this.endBeatRenderer = this.renderer.scoreRenderer.layout.getRendererForBar(this.renderer.staff.staffId, this.endBeat.voice.bar);
|
|
69956
|
+
}
|
|
69957
|
+
return this.endBeatRenderer;
|
|
69958
|
+
}
|
|
69959
|
+
shouldDrawBendSlur() {
|
|
69960
|
+
return false;
|
|
69961
|
+
}
|
|
69962
|
+
calculateTieDirection() {
|
|
69963
|
+
if (this.startBeat.isRest) {
|
|
69739
69964
|
return BeamDirection.Up;
|
|
69740
69965
|
}
|
|
69741
69966
|
// invert direction (if stems go up, ties go down to not cross them)
|
|
69742
|
-
switch (
|
|
69967
|
+
switch (this.lookupStartBeatRenderer().getBeatDirection(this.startBeat)) {
|
|
69743
69968
|
case BeamDirection.Up:
|
|
69744
69969
|
return BeamDirection.Down;
|
|
69745
69970
|
default:
|
|
69746
69971
|
return BeamDirection.Up;
|
|
69747
69972
|
}
|
|
69748
69973
|
}
|
|
69749
|
-
|
|
69974
|
+
calculateStartX() {
|
|
69975
|
+
const startBeatRenderer = this.lookupStartBeatRenderer();
|
|
69976
|
+
return startBeatRenderer.x + startBeatRenderer.getBeatX(this.startBeat, BeatXPosition.MiddleNotes);
|
|
69977
|
+
}
|
|
69978
|
+
calculateStartY() {
|
|
69979
|
+
const startBeatRenderer = this.lookupStartBeatRenderer();
|
|
69750
69980
|
if (this.startBeat.isRest) {
|
|
69751
|
-
|
|
69752
|
-
|
|
69981
|
+
switch (this.tieDirection) {
|
|
69982
|
+
case BeamDirection.Up:
|
|
69983
|
+
return (startBeatRenderer.y +
|
|
69984
|
+
startBeatRenderer.getBeatContainer(this.startBeat).onNotes.getBoundingBoxTop());
|
|
69985
|
+
default:
|
|
69986
|
+
return (startBeatRenderer.y +
|
|
69987
|
+
startBeatRenderer.getBeatContainer(this.startBeat).onNotes.getBoundingBoxBottom());
|
|
69988
|
+
}
|
|
69753
69989
|
}
|
|
69754
69990
|
switch (this.tieDirection) {
|
|
69755
69991
|
case BeamDirection.Up:
|
|
69756
69992
|
// below lowest note
|
|
69757
|
-
return
|
|
69993
|
+
return startBeatRenderer.y + startBeatRenderer.getNoteY(this.startBeat.maxNote, NoteYPosition.Top);
|
|
69758
69994
|
default:
|
|
69759
|
-
return
|
|
69995
|
+
return startBeatRenderer.y + startBeatRenderer.getNoteY(this.startBeat.minNote, NoteYPosition.Bottom);
|
|
69996
|
+
}
|
|
69997
|
+
}
|
|
69998
|
+
calculateEndX() {
|
|
69999
|
+
const endBeatRenderer = this.lookupEndBeatRenderer();
|
|
70000
|
+
if (!endBeatRenderer) {
|
|
70001
|
+
return this.calculateStartX() + this.renderer.smuflMetrics.leftHandTabTieWidth;
|
|
69760
70002
|
}
|
|
70003
|
+
const endBeamDirection = endBeatRenderer.getBeatDirection(this.endBeat);
|
|
70004
|
+
return (endBeatRenderer.x +
|
|
70005
|
+
endBeatRenderer.getBeatX(this.endBeat, this.endBeat.duration > Duration.Whole && endBeamDirection === this.tieDirection
|
|
70006
|
+
? BeatXPosition.Stem
|
|
70007
|
+
: BeatXPosition.MiddleNotes));
|
|
69761
70008
|
}
|
|
69762
|
-
|
|
69763
|
-
const
|
|
70009
|
+
caclculateEndY() {
|
|
70010
|
+
const endBeatRenderer = this.lookupEndBeatRenderer();
|
|
70011
|
+
if (!endBeatRenderer) {
|
|
70012
|
+
return this.calculateStartY();
|
|
70013
|
+
}
|
|
69764
70014
|
if (this.endBeat.isRest) {
|
|
69765
70015
|
switch (this.tieDirection) {
|
|
69766
70016
|
case BeamDirection.Up:
|
|
69767
|
-
return
|
|
70017
|
+
return (endBeatRenderer.y + endBeatRenderer.getBeatContainer(this.endBeat).onNotes.getBoundingBoxTop());
|
|
69768
70018
|
default:
|
|
69769
|
-
return
|
|
70019
|
+
return (endBeatRenderer.y +
|
|
70020
|
+
endBeatRenderer.getBeatContainer(this.endBeat).onNotes.getBoundingBoxBottom());
|
|
69770
70021
|
}
|
|
69771
70022
|
}
|
|
69772
|
-
const startBeamDirection = this.
|
|
69773
|
-
const endBeamDirection =
|
|
70023
|
+
const startBeamDirection = this.lookupStartBeatRenderer().getBeatDirection(this.startBeat);
|
|
70024
|
+
const endBeamDirection = endBeatRenderer.getBeatDirection(this.endBeat);
|
|
69774
70025
|
if (startBeamDirection !== endBeamDirection && this.startBeat.graceType === GraceType.None) {
|
|
69775
70026
|
if (endBeamDirection === this.tieDirection) {
|
|
69776
70027
|
switch (this.tieDirection) {
|
|
69777
70028
|
case BeamDirection.Up:
|
|
69778
70029
|
// stem upper end
|
|
69779
|
-
return
|
|
70030
|
+
return (endBeatRenderer.y +
|
|
70031
|
+
endBeatRenderer.getNoteY(this.endBeat.maxNote, NoteYPosition.TopWithStem));
|
|
69780
70032
|
default:
|
|
69781
70033
|
// stem lower end
|
|
69782
|
-
return
|
|
70034
|
+
return (endBeatRenderer.y +
|
|
70035
|
+
endBeatRenderer.getNoteY(this.endBeat.minNote, NoteYPosition.BottomWithStem));
|
|
69783
70036
|
}
|
|
69784
70037
|
}
|
|
69785
70038
|
switch (this.tieDirection) {
|
|
69786
70039
|
case BeamDirection.Up:
|
|
69787
70040
|
// stem upper end
|
|
69788
|
-
return
|
|
70041
|
+
return (endBeatRenderer.y +
|
|
70042
|
+
endBeatRenderer.getNoteY(this.endBeat.maxNote, NoteYPosition.BottomWithStem));
|
|
69789
70043
|
default:
|
|
69790
70044
|
// stem lower end
|
|
69791
|
-
return
|
|
70045
|
+
return (endBeatRenderer.y + endBeatRenderer.getNoteY(this.endBeat.minNote, NoteYPosition.TopWithStem));
|
|
69792
70046
|
}
|
|
69793
70047
|
}
|
|
69794
70048
|
switch (this.tieDirection) {
|
|
69795
70049
|
case BeamDirection.Up:
|
|
69796
70050
|
// below lowest note
|
|
69797
|
-
return
|
|
70051
|
+
return endBeatRenderer.y + endBeatRenderer.getNoteY(this.endBeat.maxNote, NoteYPosition.Top);
|
|
69798
70052
|
default:
|
|
69799
70053
|
// above highest note
|
|
69800
|
-
return
|
|
70054
|
+
return endBeatRenderer.y + endBeatRenderer.getNoteY(this.endBeat.minNote, NoteYPosition.Bottom);
|
|
69801
70055
|
}
|
|
69802
70056
|
}
|
|
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
70057
|
}
|
|
69813
70058
|
|
|
69814
70059
|
/**
|
|
@@ -70008,142 +70253,106 @@ class ScoreSlideLineGlyph extends Glyph {
|
|
|
70008
70253
|
/**
|
|
70009
70254
|
* @internal
|
|
70010
70255
|
*/
|
|
70011
|
-
class
|
|
70012
|
-
|
|
70013
|
-
|
|
70014
|
-
|
|
70015
|
-
|
|
70016
|
-
|
|
70017
|
-
|
|
70256
|
+
class ScoreTieGlyph extends NoteTieGlyph {
|
|
70257
|
+
shouldDrawBendSlur() {
|
|
70258
|
+
return (this.renderer.settings.notation.extendBendArrowsOnTiedNotes &&
|
|
70259
|
+
!!this.startNote.bendOrigin &&
|
|
70260
|
+
this.startNote.isTieOrigin);
|
|
70261
|
+
}
|
|
70262
|
+
calculateStartX() {
|
|
70263
|
+
if (this.isLeftHandTap) {
|
|
70264
|
+
return this.calculateEndX() - this.renderer.smuflMetrics.leftHandTabTieWidth;
|
|
70265
|
+
}
|
|
70266
|
+
return this.renderer.x + this.renderer.getBeatX(this.startNote.beat, BeatXPosition.PostNotes);
|
|
70018
70267
|
}
|
|
70268
|
+
calculateEndX() {
|
|
70269
|
+
const endNoteRenderer = this.lookupEndBeatRenderer();
|
|
70270
|
+
if (!endNoteRenderer) {
|
|
70271
|
+
return this.calculateStartX() + this.renderer.smuflMetrics.leftHandTabTieWidth;
|
|
70272
|
+
}
|
|
70273
|
+
if (this.isLeftHandTap) {
|
|
70274
|
+
return endNoteRenderer.x + endNoteRenderer.getNoteX(this.endNote, NoteXPosition.Left);
|
|
70275
|
+
}
|
|
70276
|
+
return endNoteRenderer.x + endNoteRenderer.getBeatX(this.endNote.beat, BeatXPosition.PreNotes);
|
|
70277
|
+
}
|
|
70278
|
+
}
|
|
70279
|
+
|
|
70280
|
+
/**
|
|
70281
|
+
* @internal
|
|
70282
|
+
*/
|
|
70283
|
+
class ScoreSlurGlyph extends ScoreTieGlyph {
|
|
70019
70284
|
getTieHeight(startX, _startY, endX, _endY) {
|
|
70020
|
-
return Math.log2(endX - startX + 1) * this.renderer.settings.notation.slurHeight / 2;
|
|
70285
|
+
return (Math.log2(endX - startX + 1) * this.renderer.settings.notation.slurHeight) / 2;
|
|
70286
|
+
}
|
|
70287
|
+
calculateStartX() {
|
|
70288
|
+
return (this.renderer.x +
|
|
70289
|
+
(this._isStartCentered()
|
|
70290
|
+
? this.renderer.getBeatX(this.startNote.beat, BeatXPosition.MiddleNotes)
|
|
70291
|
+
: this.renderer.getNoteX(this.startNote, NoteXPosition.Right)));
|
|
70021
70292
|
}
|
|
70022
|
-
|
|
70293
|
+
calculateStartY() {
|
|
70023
70294
|
if (this._isStartCentered()) {
|
|
70024
70295
|
switch (this.tieDirection) {
|
|
70025
70296
|
case BeamDirection.Up:
|
|
70026
|
-
|
|
70027
|
-
return this.startNoteRenderer.getNoteY(this._startNote, NoteYPosition.Top);
|
|
70297
|
+
return this.renderer.y + this.renderer.getNoteY(this.startNote, NoteYPosition.Top);
|
|
70028
70298
|
default:
|
|
70029
|
-
return this.
|
|
70299
|
+
return this.renderer.y + this.renderer.getNoteY(this.startNote, NoteYPosition.Bottom);
|
|
70030
70300
|
}
|
|
70031
70301
|
}
|
|
70032
|
-
return this.
|
|
70302
|
+
return this.renderer.y + this.renderer.getNoteY(this.startNote, NoteYPosition.Center);
|
|
70033
70303
|
}
|
|
70034
|
-
|
|
70304
|
+
calculateEndX() {
|
|
70305
|
+
const endNoteRenderer = this.lookupEndBeatRenderer();
|
|
70306
|
+
if (!endNoteRenderer) {
|
|
70307
|
+
return this.calculateStartX() + this.renderer.smuflMetrics.leftHandTabTieWidth;
|
|
70308
|
+
}
|
|
70309
|
+
if (this._isEndCentered()) {
|
|
70310
|
+
if (this._isEndOnStem()) {
|
|
70311
|
+
return endNoteRenderer.x + endNoteRenderer.getBeatX(this.endNote.beat, BeatXPosition.Stem);
|
|
70312
|
+
}
|
|
70313
|
+
return endNoteRenderer.x + endNoteRenderer.getNoteX(this.endNote, NoteXPosition.Center);
|
|
70314
|
+
}
|
|
70315
|
+
return endNoteRenderer.x + endNoteRenderer.getBeatX(this.endNote.beat, BeatXPosition.PreNotes);
|
|
70316
|
+
}
|
|
70317
|
+
caclculateEndY() {
|
|
70318
|
+
const endNoteRenderer = this.lookupEndBeatRenderer();
|
|
70319
|
+
if (!endNoteRenderer) {
|
|
70320
|
+
return this.calculateStartY();
|
|
70321
|
+
}
|
|
70035
70322
|
if (this._isEndCentered()) {
|
|
70036
70323
|
if (this._isEndOnStem()) {
|
|
70037
70324
|
switch (this.tieDirection) {
|
|
70038
70325
|
case BeamDirection.Up:
|
|
70039
|
-
return
|
|
70326
|
+
return endNoteRenderer.y + endNoteRenderer.getNoteY(this.endNote, NoteYPosition.TopWithStem);
|
|
70040
70327
|
default:
|
|
70041
|
-
return
|
|
70328
|
+
return endNoteRenderer.y + endNoteRenderer.getNoteY(this.endNote, NoteYPosition.BottomWithStem);
|
|
70042
70329
|
}
|
|
70043
70330
|
}
|
|
70044
70331
|
switch (this.tieDirection) {
|
|
70045
70332
|
case BeamDirection.Up:
|
|
70046
|
-
return
|
|
70333
|
+
return endNoteRenderer.y + endNoteRenderer.getNoteY(this.endNote, NoteYPosition.Top);
|
|
70047
70334
|
default:
|
|
70048
|
-
return
|
|
70335
|
+
return endNoteRenderer.y + endNoteRenderer.getNoteY(this.endNote, NoteYPosition.Bottom);
|
|
70049
70336
|
}
|
|
70050
70337
|
}
|
|
70051
|
-
return
|
|
70338
|
+
return endNoteRenderer.y + endNoteRenderer.getNoteY(this.endNote, NoteYPosition.Center);
|
|
70052
70339
|
}
|
|
70053
70340
|
_isStartCentered() {
|
|
70054
|
-
return ((this.
|
|
70055
|
-
(this.
|
|
70341
|
+
return ((this.startNote === this.startNote.beat.maxNote && this.tieDirection === BeamDirection.Up) ||
|
|
70342
|
+
(this.startNote === this.startNote.beat.minNote && this.tieDirection === BeamDirection.Down));
|
|
70056
70343
|
}
|
|
70057
70344
|
_isEndCentered() {
|
|
70058
|
-
return (this.
|
|
70059
|
-
((this.
|
|
70060
|
-
(this.
|
|
70345
|
+
return (this.startNote.beat.graceType === GraceType.None &&
|
|
70346
|
+
((this.endNote === this.endNote.beat.maxNote && this.tieDirection === BeamDirection.Up) ||
|
|
70347
|
+
(this.endNote === this.endNote.beat.minNote && this.tieDirection === BeamDirection.Down)));
|
|
70061
70348
|
}
|
|
70062
70349
|
_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);
|
|
70350
|
+
const startBeamDirection = this.lookupStartBeatRenderer().getBeatDirection(this.startNote.beat);
|
|
70351
|
+
const endBeatRenderer = this.lookupEndBeatRenderer();
|
|
70352
|
+
const endBeamDirection = endBeatRenderer
|
|
70353
|
+
? endBeatRenderer.getBeatDirection(this.endNote.beat)
|
|
70354
|
+
: startBeamDirection;
|
|
70355
|
+
return startBeamDirection !== endBeamDirection && this.startNote.beat.graceType === GraceType.None;
|
|
70147
70356
|
}
|
|
70148
70357
|
}
|
|
70149
70358
|
|
|
@@ -70193,12 +70402,11 @@ class ScoreBeatContainerGlyph extends BeatContainerGlyph {
|
|
|
70193
70402
|
n.beat.graceType !== GraceType.BendGrace &&
|
|
70194
70403
|
n.tieDestination &&
|
|
70195
70404
|
n.tieDestination.isVisible) {
|
|
70196
|
-
|
|
70197
|
-
const tie = new ScoreTieGlyph(n, n.tieDestination, false);
|
|
70405
|
+
const tie = new ScoreTieGlyph(`score.tie.${n.id}`, n, n.tieDestination, false);
|
|
70198
70406
|
this.addTie(tie);
|
|
70199
70407
|
}
|
|
70200
70408
|
if (n.isTieDestination && !n.tieOrigin.hasBend && !n.beat.hasWhammyBar) {
|
|
70201
|
-
const tie = new ScoreTieGlyph(n.tieOrigin, n, true);
|
|
70409
|
+
const tie = new ScoreTieGlyph(`score.tie.${n.tieOrigin.id}`, n.tieOrigin, n, true);
|
|
70202
70410
|
this.addTie(tie);
|
|
70203
70411
|
}
|
|
70204
70412
|
// TODO: depending on the type we have other positioning
|
|
@@ -70208,17 +70416,16 @@ class ScoreBeatContainerGlyph extends BeatContainerGlyph {
|
|
|
70208
70416
|
this.addTie(l);
|
|
70209
70417
|
}
|
|
70210
70418
|
if (n.isSlurOrigin && n.slurDestination && n.slurDestination.isVisible) {
|
|
70211
|
-
|
|
70212
|
-
const tie = new ScoreSlurGlyph(n, n.slurDestination, false);
|
|
70419
|
+
const tie = new ScoreSlurGlyph(`score.slur.${n.id}`, n, n.slurDestination, false);
|
|
70213
70420
|
this.addTie(tie);
|
|
70214
70421
|
}
|
|
70215
70422
|
if (n.isSlurDestination) {
|
|
70216
|
-
const tie = new ScoreSlurGlyph(n.slurOrigin, n, true);
|
|
70423
|
+
const tie = new ScoreSlurGlyph(`score.slur.${n.slurOrigin.id}`, n.slurOrigin, n, true);
|
|
70217
70424
|
this.addTie(tie);
|
|
70218
70425
|
}
|
|
70219
70426
|
// start effect slur on first beat
|
|
70220
70427
|
if (!this._effectSlur && n.isEffectSlurOrigin && n.effectSlurDestination) {
|
|
70221
|
-
const effectSlur = new ScoreSlurGlyph(n, n.effectSlurDestination, false);
|
|
70428
|
+
const effectSlur = new ScoreSlurGlyph(`score.slur.effect.${n.beat.id}`, n, n.effectSlurDestination, false);
|
|
70222
70429
|
this._effectSlur = effectSlur;
|
|
70223
70430
|
this.addTie(effectSlur);
|
|
70224
70431
|
}
|
|
@@ -70227,7 +70434,7 @@ class ScoreBeatContainerGlyph extends BeatContainerGlyph {
|
|
|
70227
70434
|
const direction = this.onNotes.beamingHelper.direction;
|
|
70228
70435
|
const startNote = direction === BeamDirection.Up ? n.beat.effectSlurOrigin.minNote : n.beat.effectSlurOrigin.maxNote;
|
|
70229
70436
|
const endNote = direction === BeamDirection.Up ? n.beat.minNote : n.beat.maxNote;
|
|
70230
|
-
const effectEndSlur = new ScoreSlurGlyph(startNote, endNote, true);
|
|
70437
|
+
const effectEndSlur = new ScoreSlurGlyph(`score.slur.effect.${startNote.beat.id}`, startNote, endNote, true);
|
|
70231
70438
|
this._effectEndSlur = effectEndSlur;
|
|
70232
70439
|
this.addTie(effectEndSlur);
|
|
70233
70440
|
}
|
|
@@ -70249,7 +70456,7 @@ class ScoreBeatContainerGlyph extends BeatContainerGlyph {
|
|
|
70249
70456
|
while (destination.nextBeat && destination.nextBeat.isLegatoDestination) {
|
|
70250
70457
|
destination = destination.nextBeat;
|
|
70251
70458
|
}
|
|
70252
|
-
this.addTie(new ScoreLegatoGlyph(this.beat, destination, false));
|
|
70459
|
+
this.addTie(new ScoreLegatoGlyph(`score.legato.${this.beat.id}`, this.beat, destination, false));
|
|
70253
70460
|
}
|
|
70254
70461
|
}
|
|
70255
70462
|
else if (this.beat.isLegatoDestination) {
|
|
@@ -70259,7 +70466,7 @@ class ScoreBeatContainerGlyph extends BeatContainerGlyph {
|
|
|
70259
70466
|
while (origin.previousBeat && origin.previousBeat.isLegatoOrigin) {
|
|
70260
70467
|
origin = origin.previousBeat;
|
|
70261
70468
|
}
|
|
70262
|
-
this.addTie(new ScoreLegatoGlyph(origin, this.beat, true));
|
|
70469
|
+
this.addTie(new ScoreLegatoGlyph(`score.legato.${origin.id}`, origin, this.beat, true));
|
|
70263
70470
|
}
|
|
70264
70471
|
}
|
|
70265
70472
|
}
|
|
@@ -70639,6 +70846,9 @@ class ScoreBarRenderer extends LineBarRenderer {
|
|
|
70639
70846
|
this.addBeatGlyph(container);
|
|
70640
70847
|
}
|
|
70641
70848
|
}
|
|
70849
|
+
getNoteLine(note) {
|
|
70850
|
+
return this.accidentalHelper.getNoteSteps(note) / 2;
|
|
70851
|
+
}
|
|
70642
70852
|
getNoteSteps(n) {
|
|
70643
70853
|
return this.accidentalHelper.getNoteSteps(n);
|
|
70644
70854
|
}
|
|
@@ -70695,43 +70905,15 @@ class ScoreBarRendererFactory extends BarRendererFactory {
|
|
|
70695
70905
|
/**
|
|
70696
70906
|
* @internal
|
|
70697
70907
|
*/
|
|
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) {
|
|
70908
|
+
class SlashTieGlyph extends NoteTieGlyph {
|
|
70909
|
+
calculateTieDirection() {
|
|
70716
70910
|
return BeamDirection.Down;
|
|
70717
70911
|
}
|
|
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);
|
|
70912
|
+
getStartNotePosition() {
|
|
70913
|
+
return NoteXPosition.Right;
|
|
70732
70914
|
}
|
|
70733
|
-
|
|
70734
|
-
return
|
|
70915
|
+
getEndNotePosition() {
|
|
70916
|
+
return NoteXPosition.Left;
|
|
70735
70917
|
}
|
|
70736
70918
|
}
|
|
70737
70919
|
|
|
@@ -70746,12 +70928,12 @@ class SlashBeatContainerGlyph extends BeatContainerGlyph {
|
|
|
70746
70928
|
return;
|
|
70747
70929
|
}
|
|
70748
70930
|
if (!this._tiedNoteTie && n.isTieOrigin && n.tieDestination.isVisible) {
|
|
70749
|
-
const tie = new SlashTieGlyph(n, n.tieDestination, false);
|
|
70931
|
+
const tie = new SlashTieGlyph('slash.tie', n, n.tieDestination, false);
|
|
70750
70932
|
this._tiedNoteTie = tie;
|
|
70751
70933
|
this.addTie(tie);
|
|
70752
70934
|
}
|
|
70753
70935
|
if (!this._tiedNoteTie && n.isTieDestination) {
|
|
70754
|
-
const tie = new SlashTieGlyph(n.tieOrigin, n, true);
|
|
70936
|
+
const tie = new SlashTieGlyph('slash.tie', n.tieOrigin, n, true);
|
|
70755
70937
|
this._tiedNoteTie = tie;
|
|
70756
70938
|
this.addTie(tie);
|
|
70757
70939
|
}
|
|
@@ -70878,8 +71060,7 @@ class SlashBeatGlyph extends BeatOnNoteGlyphBase {
|
|
|
70878
71060
|
doLayout() {
|
|
70879
71061
|
// create glyphs
|
|
70880
71062
|
const sr = this.renderer;
|
|
70881
|
-
const
|
|
70882
|
-
const glyphY = sr.getLineY(line);
|
|
71063
|
+
const glyphY = sr.getLineY(0);
|
|
70883
71064
|
if (this.container.beat.deadSlapped) {
|
|
70884
71065
|
const deadSlapped = new DeadSlappedBeatGlyph();
|
|
70885
71066
|
deadSlapped.renderer = this.renderer;
|
|
@@ -70912,22 +71093,23 @@ class SlashBeatGlyph extends BeatOnNoteGlyphBase {
|
|
|
70912
71093
|
//
|
|
70913
71094
|
if (this.container.beat.dots > 0) {
|
|
70914
71095
|
for (let i = 0; i < this.container.beat.dots; i++) {
|
|
70915
|
-
this.addEffect(new AugmentationDotGlyph(0,
|
|
71096
|
+
this.addEffect(new AugmentationDotGlyph(0, glyphY - sr.getLineHeight(0.5)));
|
|
70916
71097
|
}
|
|
70917
71098
|
}
|
|
70918
71099
|
super.doLayout();
|
|
70919
71100
|
if (this.container.beat.isEmpty) {
|
|
70920
|
-
this.
|
|
71101
|
+
this.onTimeX = this.width / 2;
|
|
70921
71102
|
}
|
|
70922
71103
|
else if (this.restGlyph) {
|
|
70923
|
-
this.
|
|
71104
|
+
this.onTimeX = this.restGlyph.x + this.restGlyph.width / 2;
|
|
70924
71105
|
}
|
|
70925
71106
|
else if (this.noteHeads) {
|
|
70926
|
-
this.
|
|
71107
|
+
this.onTimeX = this.noteHeads.x + this.noteHeads.width / 2;
|
|
70927
71108
|
}
|
|
70928
71109
|
else if (this.deadSlapped) {
|
|
70929
|
-
this.
|
|
71110
|
+
this.onTimeX = this.deadSlapped.x + this.deadSlapped.width / 2;
|
|
70930
71111
|
}
|
|
71112
|
+
this.middleX = this.onTimeX;
|
|
70931
71113
|
}
|
|
70932
71114
|
}
|
|
70933
71115
|
|
|
@@ -70994,7 +71176,7 @@ class SlashBarRenderer extends LineBarRenderer {
|
|
|
70994
71176
|
this.registerOverflowTop(this.tupletSize);
|
|
70995
71177
|
}
|
|
70996
71178
|
}
|
|
70997
|
-
getNoteLine() {
|
|
71179
|
+
getNoteLine(_note) {
|
|
70998
71180
|
return 0;
|
|
70999
71181
|
}
|
|
71000
71182
|
getFlagTopY(beat, _direction) {
|
|
@@ -71331,77 +71513,6 @@ class TabSlideLineGlyph extends Glyph {
|
|
|
71331
71513
|
}
|
|
71332
71514
|
}
|
|
71333
71515
|
|
|
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
71516
|
/**
|
|
71406
71517
|
* @internal
|
|
71407
71518
|
*/
|
|
@@ -71426,15 +71537,15 @@ class TabBeatContainerGlyph extends BeatContainerGlyph {
|
|
|
71426
71537
|
}
|
|
71427
71538
|
const renderer = this.renderer;
|
|
71428
71539
|
if (n.isTieOrigin && renderer.showTiedNotes && n.tieDestination.isVisible) {
|
|
71429
|
-
const tie = new TabTieGlyph(n, n.tieDestination, false);
|
|
71540
|
+
const tie = new TabTieGlyph(`tab.tie.${n.id}`, n, n.tieDestination, false);
|
|
71430
71541
|
this.addTie(tie);
|
|
71431
71542
|
}
|
|
71432
71543
|
if (n.isTieDestination && renderer.showTiedNotes) {
|
|
71433
|
-
const tie = new TabTieGlyph(n.tieOrigin, n, true);
|
|
71544
|
+
const tie = new TabTieGlyph(`tab.tie.${n.tieOrigin.id}`, n.tieOrigin, n, true);
|
|
71434
71545
|
this.addTie(tie);
|
|
71435
71546
|
}
|
|
71436
71547
|
if (n.isLeftHandTapped && !n.isHammerPullDestination) {
|
|
71437
|
-
const tapSlur = new TabTieGlyph(n, n, false);
|
|
71548
|
+
const tapSlur = new TabTieGlyph(`tab.tie.leftHandTap.${n.id}`, n, n, false);
|
|
71438
71549
|
this.addTie(tapSlur);
|
|
71439
71550
|
}
|
|
71440
71551
|
// start effect slur on first beat
|
|
@@ -71447,7 +71558,7 @@ class TabBeatContainerGlyph extends BeatContainerGlyph {
|
|
|
71447
71558
|
}
|
|
71448
71559
|
}
|
|
71449
71560
|
if (!expanded) {
|
|
71450
|
-
const effectSlur = new TabSlurGlyph(n, n.effectSlurDestination, false, false);
|
|
71561
|
+
const effectSlur = new TabSlurGlyph(`tab.slur.effect.${n.id}`, n, n.effectSlurDestination, false, false);
|
|
71451
71562
|
this._effectSlurs.push(effectSlur);
|
|
71452
71563
|
this.addTie(effectSlur);
|
|
71453
71564
|
}
|
|
@@ -71462,7 +71573,7 @@ class TabBeatContainerGlyph extends BeatContainerGlyph {
|
|
|
71462
71573
|
}
|
|
71463
71574
|
}
|
|
71464
71575
|
if (!expanded) {
|
|
71465
|
-
const effectSlur = new TabSlurGlyph(n.effectSlurOrigin, n, false, true);
|
|
71576
|
+
const effectSlur = new TabSlurGlyph(`tab.slur.effect.${n.effectSlurOrigin.id}`, n.effectSlurOrigin, n, false, true);
|
|
71466
71577
|
this._effectSlurs.push(effectSlur);
|
|
71467
71578
|
this.addTie(effectSlur);
|
|
71468
71579
|
}
|
|
@@ -71881,7 +71992,7 @@ class TabBeatGlyph extends BeatOnNoteGlyphBase {
|
|
|
71881
71992
|
}
|
|
71882
71993
|
else {
|
|
71883
71994
|
const line = Math.floor((this.renderer.bar.staff.tuning.length - 1) / 2);
|
|
71884
|
-
const y = tabRenderer.
|
|
71995
|
+
const y = tabRenderer.getLineY(line);
|
|
71885
71996
|
const restGlyph = new TabRestGlyph(0, y, tabRenderer.showRests, this.container.beat.duration);
|
|
71886
71997
|
this.restGlyph = restGlyph;
|
|
71887
71998
|
restGlyph.beat = this.container.beat;
|
|
@@ -71911,19 +72022,20 @@ class TabBeatGlyph extends BeatOnNoteGlyphBase {
|
|
|
71911
72022
|
this.width = w;
|
|
71912
72023
|
this.computedWidth = w;
|
|
71913
72024
|
if (this.container.beat.isEmpty) {
|
|
71914
|
-
this.
|
|
72025
|
+
this.onTimeX = this.width / 2;
|
|
71915
72026
|
}
|
|
71916
72027
|
else if (this.restGlyph) {
|
|
71917
|
-
this.
|
|
72028
|
+
this.onTimeX = this.restGlyph.x + this.restGlyph.width / 2;
|
|
71918
72029
|
}
|
|
71919
72030
|
else if (this.noteNumbers) {
|
|
71920
|
-
this.
|
|
72031
|
+
this.onTimeX = this.noteNumbers.x + this.noteNumbers.noteStringWidth / 2;
|
|
71921
72032
|
}
|
|
71922
72033
|
else if (this.slash) {
|
|
71923
|
-
this.
|
|
72034
|
+
this.onTimeX = this.slash.x + this.slash.width / 2;
|
|
71924
72035
|
}
|
|
72036
|
+
this.middleX = this.onTimeX;
|
|
71925
72037
|
for (const g of centeredEffectGlyphs) {
|
|
71926
|
-
g.x = this.
|
|
72038
|
+
g.x = this.onTimeX;
|
|
71927
72039
|
}
|
|
71928
72040
|
}
|
|
71929
72041
|
updateBeamingHelper() {
|
|
@@ -71940,8 +72052,8 @@ class TabBeatGlyph extends BeatOnNoteGlyphBase {
|
|
|
71940
72052
|
_createNoteGlyph(n) {
|
|
71941
72053
|
const tr = this.renderer;
|
|
71942
72054
|
const noteNumberGlyph = new NoteNumberGlyph(0, 0, n);
|
|
71943
|
-
const l =
|
|
71944
|
-
noteNumberGlyph.y = tr.
|
|
72055
|
+
const l = tr.getNoteLine(n);
|
|
72056
|
+
noteNumberGlyph.y = tr.getLineY(l);
|
|
71945
72057
|
noteNumberGlyph.renderer = this.renderer;
|
|
71946
72058
|
noteNumberGlyph.doLayout();
|
|
71947
72059
|
this.noteNumbers.addNoteGlyph(noteNumberGlyph, n);
|
|
@@ -72132,17 +72244,8 @@ class TabBarRenderer extends LineBarRenderer {
|
|
|
72132
72244
|
}
|
|
72133
72245
|
return mode;
|
|
72134
72246
|
}
|
|
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);
|
|
72247
|
+
getNoteLine(note) {
|
|
72248
|
+
return this.bar.staff.tuning.length - note.string;
|
|
72146
72249
|
}
|
|
72147
72250
|
minString = Number.NaN;
|
|
72148
72251
|
maxString = Number.NaN;
|
|
@@ -72231,7 +72334,7 @@ class TabBarRenderer extends LineBarRenderer {
|
|
|
72231
72334
|
if (this.isFirstOfLine) {
|
|
72232
72335
|
const center = (this.bar.staff.tuning.length - 1) / 2;
|
|
72233
72336
|
this.createStartSpacing();
|
|
72234
|
-
this.addPreBeatGlyph(new TabClefGlyph(0, this.
|
|
72337
|
+
this.addPreBeatGlyph(new TabClefGlyph(0, this.getLineY(center)));
|
|
72235
72338
|
}
|
|
72236
72339
|
// Time Signature
|
|
72237
72340
|
if (this.showTimeSignature &&
|
|
@@ -72252,7 +72355,7 @@ class TabBarRenderer extends LineBarRenderer {
|
|
|
72252
72355
|
_createTimeSignatureGlyphs() {
|
|
72253
72356
|
this.addPreBeatGlyph(new SpacingGlyph(0, 0, this.smuflMetrics.oneStaffSpace));
|
|
72254
72357
|
const lines = (this.bar.staff.tuning.length + 1) / 2 - 1;
|
|
72255
|
-
this.addPreBeatGlyph(new TabTimeSignatureGlyph(0, this.
|
|
72358
|
+
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
72359
|
}
|
|
72257
72360
|
createVoiceGlyphs(v) {
|
|
72258
72361
|
super.createVoiceGlyphs(v);
|