@coderline/alphatab 1.8.0-alpha.1636 → 1.8.0-alpha.1639
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/alphaTab.core.min.mjs +2 -2
- package/dist/alphaTab.core.mjs +1042 -799
- package/dist/alphaTab.d.ts +189 -2
- package/dist/alphaTab.js +1042 -799
- package/dist/alphaTab.min.js +2 -2
- package/dist/alphaTab.min.mjs +1 -1
- package/dist/alphaTab.mjs +1 -1
- package/dist/alphaTab.worker.min.mjs +1 -1
- package/dist/alphaTab.worker.mjs +1 -1
- package/dist/alphaTab.worklet.min.mjs +1 -1
- package/dist/alphaTab.worklet.mjs +1 -1
- package/package.json +3 -3
package/dist/alphaTab.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* alphaTab v1.8.0-alpha.
|
|
2
|
+
* alphaTab v1.8.0-alpha.1639 (develop, build 1639)
|
|
3
3
|
*
|
|
4
4
|
* Copyright © 2025, Daniel Kuschny and Contributors, All rights reserved.
|
|
5
5
|
*
|
|
@@ -209,9 +209,9 @@
|
|
|
209
209
|
* @internal
|
|
210
210
|
*/
|
|
211
211
|
class VersionInfo {
|
|
212
|
-
static version = '1.8.0-alpha.
|
|
213
|
-
static date = '2025-12-
|
|
214
|
-
static commit = '
|
|
212
|
+
static version = '1.8.0-alpha.1639';
|
|
213
|
+
static date = '2025-12-09T02:16:01.440Z';
|
|
214
|
+
static commit = 'af86866e4f9d89a3ccc34006d01473a549dbbe7f';
|
|
215
215
|
static print(print) {
|
|
216
216
|
print(`alphaTab ${VersionInfo.version}`);
|
|
217
217
|
print(`commit: ${VersionInfo.commit}`);
|
|
@@ -12956,25 +12956,31 @@
|
|
|
12956
12956
|
/**
|
|
12957
12957
|
* Gets or sets the X-position of the rectangle within the music notation.
|
|
12958
12958
|
*/
|
|
12959
|
-
x
|
|
12959
|
+
x;
|
|
12960
12960
|
/**
|
|
12961
12961
|
* Gets or sets the Y-position of the rectangle within the music notation.
|
|
12962
12962
|
*/
|
|
12963
|
-
y
|
|
12963
|
+
y;
|
|
12964
12964
|
/**
|
|
12965
12965
|
* Gets or sets the width of the rectangle.
|
|
12966
12966
|
*/
|
|
12967
|
-
w
|
|
12967
|
+
w;
|
|
12968
12968
|
/**
|
|
12969
12969
|
* Gets or sets the height of the rectangle.
|
|
12970
12970
|
*/
|
|
12971
|
-
h
|
|
12971
|
+
h;
|
|
12972
12972
|
scaleWith(scale) {
|
|
12973
12973
|
this.x *= scale;
|
|
12974
12974
|
this.y *= scale;
|
|
12975
12975
|
this.w *= scale;
|
|
12976
12976
|
this.h *= scale;
|
|
12977
12977
|
}
|
|
12978
|
+
constructor(x = 0, y = 0, w = 0, h = 0) {
|
|
12979
|
+
this.x = x;
|
|
12980
|
+
this.y = y;
|
|
12981
|
+
this.h = h;
|
|
12982
|
+
this.w = w;
|
|
12983
|
+
}
|
|
12978
12984
|
}
|
|
12979
12985
|
|
|
12980
12986
|
/**
|
|
@@ -49460,16 +49466,6 @@
|
|
|
49460
49466
|
}
|
|
49461
49467
|
}
|
|
49462
49468
|
|
|
49463
|
-
/**
|
|
49464
|
-
* @internal
|
|
49465
|
-
*/
|
|
49466
|
-
class SelectionInfo {
|
|
49467
|
-
beat;
|
|
49468
|
-
bounds = null;
|
|
49469
|
-
constructor(beat) {
|
|
49470
|
-
this.beat = beat;
|
|
49471
|
-
}
|
|
49472
|
-
}
|
|
49473
49469
|
/**
|
|
49474
49470
|
* This class represents the public API of alphaTab and provides all logic to display
|
|
49475
49471
|
* a music sheet in any UI using the given {@link IUiFacade}
|
|
@@ -51569,8 +51565,8 @@
|
|
|
51569
51565
|
}
|
|
51570
51566
|
_isBeatMouseDown = false;
|
|
51571
51567
|
_isNoteMouseDown = false;
|
|
51572
|
-
_selectionStart
|
|
51573
|
-
_selectionEnd
|
|
51568
|
+
_selectionStart;
|
|
51569
|
+
_selectionEnd;
|
|
51574
51570
|
/**
|
|
51575
51571
|
* This event is fired whenever a the user presses the mouse button on a beat.
|
|
51576
51572
|
* @eventProperty
|
|
@@ -51813,8 +51809,8 @@
|
|
|
51813
51809
|
return;
|
|
51814
51810
|
}
|
|
51815
51811
|
if (this._hasCursor && this.settings.player.enableUserInteraction) {
|
|
51816
|
-
this._selectionStart =
|
|
51817
|
-
this._selectionEnd =
|
|
51812
|
+
this._selectionStart = { beat };
|
|
51813
|
+
this._selectionEnd = undefined;
|
|
51818
51814
|
}
|
|
51819
51815
|
this._isBeatMouseDown = true;
|
|
51820
51816
|
this.beatMouseDown.trigger(beat);
|
|
@@ -51834,7 +51830,7 @@
|
|
|
51834
51830
|
}
|
|
51835
51831
|
if (this.settings.player.enableUserInteraction) {
|
|
51836
51832
|
if (!this._selectionEnd || this._selectionEnd.beat !== beat) {
|
|
51837
|
-
this._selectionEnd =
|
|
51833
|
+
this._selectionEnd = { beat };
|
|
51838
51834
|
this._cursorSelectRange(this._selectionStart, this._selectionEnd);
|
|
51839
51835
|
}
|
|
51840
51836
|
}
|
|
@@ -51853,45 +51849,7 @@
|
|
|
51853
51849
|
return;
|
|
51854
51850
|
}
|
|
51855
51851
|
if (this._hasCursor && this.settings.player.enableUserInteraction) {
|
|
51856
|
-
|
|
51857
|
-
const startTick = this._tickCache?.getBeatStart(this._selectionStart.beat) ??
|
|
51858
|
-
this._selectionStart.beat.absolutePlaybackStart;
|
|
51859
|
-
const endTick = this._tickCache?.getBeatStart(this._selectionEnd.beat) ??
|
|
51860
|
-
this._selectionEnd.beat.absolutePlaybackStart;
|
|
51861
|
-
if (endTick < startTick) {
|
|
51862
|
-
const t = this._selectionStart;
|
|
51863
|
-
this._selectionStart = this._selectionEnd;
|
|
51864
|
-
this._selectionEnd = t;
|
|
51865
|
-
}
|
|
51866
|
-
}
|
|
51867
|
-
if (this._selectionStart && this._tickCache) {
|
|
51868
|
-
// get the start and stop ticks (which consider properly repeats)
|
|
51869
|
-
const tickCache = this._tickCache;
|
|
51870
|
-
const realMasterBarStart = tickCache.getMasterBarStart(this._selectionStart.beat.voice.bar.masterBar);
|
|
51871
|
-
// move to selection start
|
|
51872
|
-
this._currentBeat = null; // reset current beat so it is updating the cursor
|
|
51873
|
-
if (this._player.state === PlayerState.Paused) {
|
|
51874
|
-
this._cursorUpdateTick(this._tickCache.getBeatStart(this._selectionStart.beat), false, 1);
|
|
51875
|
-
}
|
|
51876
|
-
this.tickPosition = realMasterBarStart + this._selectionStart.beat.playbackStart;
|
|
51877
|
-
// set playback range
|
|
51878
|
-
if (this._selectionEnd && this._selectionStart.beat !== this._selectionEnd.beat) {
|
|
51879
|
-
const realMasterBarEnd = tickCache.getMasterBarStart(this._selectionEnd.beat.voice.bar.masterBar);
|
|
51880
|
-
const range = new PlaybackRange();
|
|
51881
|
-
range.startTick = realMasterBarStart + this._selectionStart.beat.playbackStart;
|
|
51882
|
-
range.endTick =
|
|
51883
|
-
realMasterBarEnd +
|
|
51884
|
-
this._selectionEnd.beat.playbackStart +
|
|
51885
|
-
this._selectionEnd.beat.playbackDuration -
|
|
51886
|
-
50;
|
|
51887
|
-
this.playbackRange = range;
|
|
51888
|
-
}
|
|
51889
|
-
else {
|
|
51890
|
-
this._selectionStart = null;
|
|
51891
|
-
this.playbackRange = null;
|
|
51892
|
-
this._cursorSelectRange(this._selectionStart, this._selectionEnd);
|
|
51893
|
-
}
|
|
51894
|
-
}
|
|
51852
|
+
this.applyPlaybackRangeFromHighlight();
|
|
51895
51853
|
}
|
|
51896
51854
|
this.beatMouseUp.trigger(beat);
|
|
51897
51855
|
this.uiFacade.triggerEvent(this.container, 'beatMouseUp', beat, originalEvent);
|
|
@@ -51913,13 +51871,13 @@
|
|
|
51913
51871
|
const startBeat = this._tickCache.findBeat(this._trackIndexLookup, range.startTick);
|
|
51914
51872
|
const endBeat = this._tickCache.findBeat(this._trackIndexLookup, range.endTick);
|
|
51915
51873
|
if (startBeat && endBeat) {
|
|
51916
|
-
const selectionStart =
|
|
51917
|
-
const selectionEnd =
|
|
51874
|
+
const selectionStart = { beat: startBeat.beat };
|
|
51875
|
+
const selectionEnd = { beat: endBeat.beat };
|
|
51918
51876
|
this._cursorSelectRange(selectionStart, selectionEnd);
|
|
51919
51877
|
}
|
|
51920
51878
|
}
|
|
51921
51879
|
else {
|
|
51922
|
-
this._cursorSelectRange(
|
|
51880
|
+
this._cursorSelectRange(undefined, undefined);
|
|
51923
51881
|
}
|
|
51924
51882
|
}
|
|
51925
51883
|
_setupClickHandling() {
|
|
@@ -51988,24 +51946,230 @@
|
|
|
51988
51946
|
this._cursorSelectRange(this._selectionStart, this._selectionEnd);
|
|
51989
51947
|
});
|
|
51990
51948
|
}
|
|
51949
|
+
/**
|
|
51950
|
+
* Places the highlight markers at the specified start and end-beat range.
|
|
51951
|
+
* @param startBeat The start beat where the selection should start
|
|
51952
|
+
* @param endBeat The end beat where the selection should end.
|
|
51953
|
+
*
|
|
51954
|
+
* @remarks
|
|
51955
|
+
* Unlike actually setting {@link playbackRange} this method only places the selection markers without actually
|
|
51956
|
+
* changing the playback range. This method can be used when building custom selection systems (e.g. having draggable handles).
|
|
51957
|
+
*
|
|
51958
|
+
* @category Methods - Player
|
|
51959
|
+
* @since 1.8.0
|
|
51960
|
+
*
|
|
51961
|
+
* @example
|
|
51962
|
+
* JavaScript
|
|
51963
|
+
* ```js
|
|
51964
|
+
* const api = new alphaTab.AlphaTabApi(document.querySelector('#alphaTab'));
|
|
51965
|
+
* const startBeat = api.score.tracks[0].staves[0].bars[0].voices[0].beats[0];
|
|
51966
|
+
* const endBeat = api.score.tracks[0].staves[0].bars[3].voices[0].beats[0];
|
|
51967
|
+
* api.highlightPlaybackRange(startBeat, endBeat);
|
|
51968
|
+
* ```
|
|
51969
|
+
*
|
|
51970
|
+
* @example
|
|
51971
|
+
* C#
|
|
51972
|
+
* ```cs
|
|
51973
|
+
* var api = new AlphaTabApi<MyControl>(...);
|
|
51974
|
+
* api.ChangeTrackVolume(new Track[] { api.Score.Tracks[0], api.Score.Tracks[1] }, 1.5);
|
|
51975
|
+
* api.ChangeTrackVolume(new Track[] { api.Score.Tracks[2] }, 0.5);
|
|
51976
|
+
* var startBeat = api.Score.Tracks[0].Staves[0].Bars[0].Voices[0].Beats[0];
|
|
51977
|
+
* var endBeat = api.Score.Tracks[0].Staves[0].Bars[3].Voices[0].Beats[0];
|
|
51978
|
+
* api.HighlightPlaybackRange(startBeat, endBeat);
|
|
51979
|
+
* ```
|
|
51980
|
+
*
|
|
51981
|
+
* @example
|
|
51982
|
+
* Android
|
|
51983
|
+
* ```kotlin
|
|
51984
|
+
* val api = AlphaTabApi<MyControl>(...)
|
|
51985
|
+
* val startBeat = api.score.tracks[0].staves[0].bars[0].voices[0].beats[0]
|
|
51986
|
+
* val endBeat = api.score.tracks[0].staves[0].bars[3].voices[0].beats[0]
|
|
51987
|
+
* api.highlightPlaybackRange(startBeat, endBeat)
|
|
51988
|
+
* ```
|
|
51989
|
+
*/
|
|
51990
|
+
highlightPlaybackRange(startBeat, endBeat) {
|
|
51991
|
+
this._selectionStart = { beat: startBeat };
|
|
51992
|
+
this._selectionEnd = { beat: endBeat };
|
|
51993
|
+
this._cursorSelectRange(this._selectionStart, this._selectionEnd);
|
|
51994
|
+
}
|
|
51995
|
+
/**
|
|
51996
|
+
* Applies the playback range from the currently highlighted range.
|
|
51997
|
+
*
|
|
51998
|
+
* @remarks
|
|
51999
|
+
* This method can be used when building custom selection systems (e.g. having draggable handles).
|
|
52000
|
+
*
|
|
52001
|
+
* @category Methods - Player
|
|
52002
|
+
* @since 1.8.0
|
|
52003
|
+
*
|
|
52004
|
+
* @example
|
|
52005
|
+
* JavaScript
|
|
52006
|
+
* ```js
|
|
52007
|
+
* const api = new alphaTab.AlphaTabApi(document.querySelector('#alphaTab'));
|
|
52008
|
+
* const startBeat = api.score.tracks[0].staves[0].bars[0].voices[0].beats[0];
|
|
52009
|
+
* const endBeat = api.score.tracks[0].staves[0].bars[3].voices[0].beats[0];
|
|
52010
|
+
* api.highlightPlaybackRange(startBeat, endBeat);
|
|
52011
|
+
* api.applyPlaybackRangeFromHighlight();
|
|
52012
|
+
* ```
|
|
52013
|
+
*
|
|
52014
|
+
* @example
|
|
52015
|
+
* C#
|
|
52016
|
+
* ```cs
|
|
52017
|
+
* var api = new AlphaTabApi<MyControl>(...);
|
|
52018
|
+
* api.ChangeTrackVolume(new Track[] { api.Score.Tracks[0], api.Score.Tracks[1] }, 1.5);
|
|
52019
|
+
* api.ChangeTrackVolume(new Track[] { api.Score.Tracks[2] }, 0.5);
|
|
52020
|
+
* var startBeat = api.Score.Tracks[0].Staves[0].Bars[0].Voices[0].Beats[0];
|
|
52021
|
+
* var endBeat = api.Score.Tracks[0].Staves[0].Bars[3].Voices[0].Beats[0];
|
|
52022
|
+
* api.HighlightPlaybackRange(startBeat, endBeat);
|
|
52023
|
+
* api.ApplyPlaybackRangeFromHighlight();
|
|
52024
|
+
* ```
|
|
52025
|
+
*
|
|
52026
|
+
* @example
|
|
52027
|
+
* Android
|
|
52028
|
+
* ```kotlin
|
|
52029
|
+
* val api = AlphaTabApi<MyControl>(...)
|
|
52030
|
+
* val startBeat = api.score.tracks[0].staves[0].bars[0].voices[0].beats[0]
|
|
52031
|
+
* val endBeat = api.score.tracks[0].staves[0].bars[3].voices[0].beats[0]
|
|
52032
|
+
* api.highlightPlaybackRange(startBeat, endBeat)
|
|
52033
|
+
* api.applyPlaybackRangeFromHighlight()
|
|
52034
|
+
* ```
|
|
52035
|
+
*/
|
|
52036
|
+
applyPlaybackRangeFromHighlight() {
|
|
52037
|
+
if (this._selectionEnd) {
|
|
52038
|
+
const startTick = this._tickCache?.getBeatStart(this._selectionStart.beat) ??
|
|
52039
|
+
this._selectionStart.beat.absolutePlaybackStart;
|
|
52040
|
+
const endTick = this._tickCache?.getBeatStart(this._selectionEnd.beat) ??
|
|
52041
|
+
this._selectionEnd.beat.absolutePlaybackStart;
|
|
52042
|
+
if (endTick < startTick) {
|
|
52043
|
+
const t = this._selectionStart;
|
|
52044
|
+
this._selectionStart = this._selectionEnd;
|
|
52045
|
+
this._selectionEnd = t;
|
|
52046
|
+
}
|
|
52047
|
+
}
|
|
52048
|
+
if (this._selectionStart && this._tickCache) {
|
|
52049
|
+
// get the start and stop ticks (which consider properly repeats)
|
|
52050
|
+
const tickCache = this._tickCache;
|
|
52051
|
+
const realMasterBarStart = tickCache.getMasterBarStart(this._selectionStart.beat.voice.bar.masterBar);
|
|
52052
|
+
// move to selection start
|
|
52053
|
+
this._currentBeat = null; // reset current beat so it is updating the cursor
|
|
52054
|
+
if (this._player.state === PlayerState.Paused) {
|
|
52055
|
+
this._cursorUpdateTick(this._tickCache.getBeatStart(this._selectionStart.beat), false, 1);
|
|
52056
|
+
}
|
|
52057
|
+
this.tickPosition = realMasterBarStart + this._selectionStart.beat.playbackStart;
|
|
52058
|
+
// set playback range
|
|
52059
|
+
if (this._selectionEnd && this._selectionStart.beat !== this._selectionEnd.beat) {
|
|
52060
|
+
const realMasterBarEnd = tickCache.getMasterBarStart(this._selectionEnd.beat.voice.bar.masterBar);
|
|
52061
|
+
const range = new PlaybackRange();
|
|
52062
|
+
range.startTick = realMasterBarStart + this._selectionStart.beat.playbackStart;
|
|
52063
|
+
range.endTick =
|
|
52064
|
+
realMasterBarEnd +
|
|
52065
|
+
this._selectionEnd.beat.playbackStart +
|
|
52066
|
+
this._selectionEnd.beat.playbackDuration -
|
|
52067
|
+
50;
|
|
52068
|
+
this.playbackRange = range;
|
|
52069
|
+
}
|
|
52070
|
+
else {
|
|
52071
|
+
this._selectionStart = undefined;
|
|
52072
|
+
this.playbackRange = null;
|
|
52073
|
+
this._cursorSelectRange(this._selectionStart, this._selectionEnd);
|
|
52074
|
+
}
|
|
52075
|
+
}
|
|
52076
|
+
}
|
|
52077
|
+
/**
|
|
52078
|
+
* Clears the highlight markers marking the currently selected playback range.
|
|
52079
|
+
*
|
|
52080
|
+
* @remarks
|
|
52081
|
+
* Unlike actually setting {@link playbackRange} this method only clears the selection markers without actually
|
|
52082
|
+
* changing the playback range. This method can be used when building custom selection systems (e.g. having draggable handles).
|
|
52083
|
+
*
|
|
52084
|
+
* @category Methods - Player
|
|
52085
|
+
* @since 1.8.0
|
|
52086
|
+
*
|
|
52087
|
+
* @example
|
|
52088
|
+
* JavaScript
|
|
52089
|
+
* ```js
|
|
52090
|
+
* const api = new alphaTab.AlphaTabApi(document.querySelector('#alphaTab'));
|
|
52091
|
+
* api.clearPlaybackRangeHighlight();
|
|
52092
|
+
* ```
|
|
52093
|
+
*
|
|
52094
|
+
* @example
|
|
52095
|
+
* C#
|
|
52096
|
+
* ```cs
|
|
52097
|
+
* var api = new AlphaTabApi<MyControl>(...);
|
|
52098
|
+
* api.clearPlaybackRangeHighlight();
|
|
52099
|
+
* ```
|
|
52100
|
+
*
|
|
52101
|
+
* @example
|
|
52102
|
+
* Android
|
|
52103
|
+
* ```kotlin
|
|
52104
|
+
* val api = AlphaTabApi<MyControl>(...)
|
|
52105
|
+
* api.clearPlaybackRangeHighlight()
|
|
52106
|
+
* ```
|
|
52107
|
+
*/
|
|
52108
|
+
clearPlaybackRangeHighlight() {
|
|
52109
|
+
this._cursorSelectRange(undefined, undefined);
|
|
52110
|
+
}
|
|
52111
|
+
/**
|
|
52112
|
+
* This event is fired the shown highlights for the selected playback range changes.
|
|
52113
|
+
*
|
|
52114
|
+
* @remarks
|
|
52115
|
+
* This event is fired already during selection and not only when the selection is completed.
|
|
52116
|
+
* This event can be used to place additional custom selection markers (like drag handles).
|
|
52117
|
+
*
|
|
52118
|
+
* @eventProperty
|
|
52119
|
+
* @category Events - Player
|
|
52120
|
+
* @since 1.8.0
|
|
52121
|
+
*
|
|
52122
|
+
* @example
|
|
52123
|
+
* JavaScript
|
|
52124
|
+
* ```js
|
|
52125
|
+
* const api = new alphaTab.AlphaTabApi(document.querySelector('#alphaTab'));
|
|
52126
|
+
* api.playbackRangeHighlightChanged.on(e => {
|
|
52127
|
+
* updateSelectionHandles(e);
|
|
52128
|
+
* });
|
|
52129
|
+
* ```
|
|
52130
|
+
*
|
|
52131
|
+
* @example
|
|
52132
|
+
* C#
|
|
52133
|
+
* ```cs
|
|
52134
|
+
* var api = new AlphaTabApi<MyControl>(...);
|
|
52135
|
+
* api.PlaybackRangeHighlightChanged.On(e =>
|
|
52136
|
+
* {
|
|
52137
|
+
* UpdateSelectionHandles(e);
|
|
52138
|
+
* });
|
|
52139
|
+
* ```
|
|
52140
|
+
*
|
|
52141
|
+
* @example
|
|
52142
|
+
* Android
|
|
52143
|
+
* ```kotlin
|
|
52144
|
+
* val api = AlphaTabApi<MyControl>(...)
|
|
52145
|
+
* api.playbackRangeHighlightChanged.on { e ->
|
|
52146
|
+
* updateSelectionHandles(e)
|
|
52147
|
+
* }
|
|
52148
|
+
* ```
|
|
52149
|
+
*
|
|
52150
|
+
*/
|
|
52151
|
+
playbackRangeHighlightChanged = new EventEmitterOfT();
|
|
51991
52152
|
_cursorSelectRange(startBeat, endBeat) {
|
|
51992
52153
|
const cache = this._renderer.boundsLookup;
|
|
51993
52154
|
if (!cache) {
|
|
52155
|
+
this.playbackRangeHighlightChanged.trigger({});
|
|
51994
52156
|
return;
|
|
51995
52157
|
}
|
|
51996
52158
|
const selectionWrapper = this._selectionWrapper;
|
|
51997
52159
|
if (!selectionWrapper) {
|
|
52160
|
+
this.playbackRangeHighlightChanged.trigger({});
|
|
51998
52161
|
return;
|
|
51999
52162
|
}
|
|
52000
52163
|
selectionWrapper.clear();
|
|
52001
52164
|
if (!startBeat || !endBeat || startBeat.beat === endBeat.beat) {
|
|
52165
|
+
this.playbackRangeHighlightChanged.trigger({});
|
|
52002
52166
|
return;
|
|
52003
52167
|
}
|
|
52004
52168
|
if (!startBeat.bounds) {
|
|
52005
|
-
startBeat.bounds = cache.findBeat(startBeat.beat);
|
|
52169
|
+
startBeat.bounds = cache.findBeat(startBeat.beat) ?? undefined;
|
|
52006
52170
|
}
|
|
52007
52171
|
if (!endBeat.bounds) {
|
|
52008
|
-
endBeat.bounds = cache.findBeat(endBeat.beat);
|
|
52172
|
+
endBeat.bounds = cache.findBeat(endBeat.beat) ?? undefined;
|
|
52009
52173
|
}
|
|
52010
52174
|
const startTick = this._tickCache?.getBeatStart(startBeat.beat) ?? startBeat.beat.absolutePlaybackStart;
|
|
52011
52175
|
const endTick = this._tickCache?.getBeatStart(endBeat.beat) ?? endBeat.beat.absolutePlaybackStart;
|
|
@@ -52014,7 +52178,17 @@
|
|
|
52014
52178
|
startBeat = endBeat;
|
|
52015
52179
|
endBeat = t;
|
|
52016
52180
|
}
|
|
52017
|
-
const
|
|
52181
|
+
const eventArgs = {
|
|
52182
|
+
startBeat: startBeat.beat,
|
|
52183
|
+
startBeatBounds: startBeat.bounds,
|
|
52184
|
+
endBeat: endBeat.beat,
|
|
52185
|
+
endBeatBounds: endBeat.bounds,
|
|
52186
|
+
highlightBlocks: []
|
|
52187
|
+
};
|
|
52188
|
+
let startX = startBeat.bounds.realBounds.x;
|
|
52189
|
+
if (startBeat.beat.index === 0) {
|
|
52190
|
+
startX = startBeat.bounds.barBounds.masterBarBounds.realBounds.x;
|
|
52191
|
+
}
|
|
52018
52192
|
let endX = endBeat.bounds.realBounds.x + endBeat.bounds.realBounds.w;
|
|
52019
52193
|
if (endBeat.beat.index === endBeat.beat.voice.beats.length - 1) {
|
|
52020
52194
|
endX =
|
|
@@ -52031,18 +52205,24 @@
|
|
|
52031
52205
|
const staffEndX = startBeat.bounds.barBounds.masterBarBounds.staffSystemBounds.visualBounds.x +
|
|
52032
52206
|
startBeat.bounds.barBounds.masterBarBounds.staffSystemBounds.visualBounds.w;
|
|
52033
52207
|
const startSelection = this.uiFacade.createSelectionElement();
|
|
52034
|
-
|
|
52208
|
+
const startSelectionBounds = new Bounds(startX, startBeat.bounds.barBounds.masterBarBounds.visualBounds.y, staffEndX - startX, startBeat.bounds.barBounds.masterBarBounds.visualBounds.h);
|
|
52209
|
+
startSelection.setBounds(startSelectionBounds.x, startSelectionBounds.y, startSelectionBounds.w, startSelectionBounds.h);
|
|
52210
|
+
eventArgs.highlightBlocks.push(startSelectionBounds);
|
|
52035
52211
|
selectionWrapper.appendChild(startSelection);
|
|
52036
52212
|
const staffStartIndex = startBeat.bounds.barBounds.masterBarBounds.staffSystemBounds.index + 1;
|
|
52037
52213
|
const staffEndIndex = endBeat.bounds.barBounds.masterBarBounds.staffSystemBounds.index;
|
|
52038
52214
|
for (let staffIndex = staffStartIndex; staffIndex < staffEndIndex; staffIndex++) {
|
|
52039
52215
|
const staffBounds = cache.staffSystems[staffIndex];
|
|
52040
52216
|
const middleSelection = this.uiFacade.createSelectionElement();
|
|
52041
|
-
|
|
52217
|
+
const middleSelectionBounds = new Bounds(staffStartX, staffBounds.visualBounds.y, staffEndX - staffStartX, staffBounds.visualBounds.h);
|
|
52218
|
+
eventArgs.highlightBlocks.push(middleSelectionBounds);
|
|
52219
|
+
middleSelection.setBounds(middleSelectionBounds.x, middleSelectionBounds.y, middleSelectionBounds.w, middleSelectionBounds.h);
|
|
52042
52220
|
selectionWrapper.appendChild(middleSelection);
|
|
52043
52221
|
}
|
|
52044
52222
|
const endSelection = this.uiFacade.createSelectionElement();
|
|
52045
|
-
|
|
52223
|
+
const endSelectionBounds = new Bounds(staffStartX, endBeat.bounds.barBounds.masterBarBounds.visualBounds.y, endX - staffStartX, endBeat.bounds.barBounds.masterBarBounds.visualBounds.h);
|
|
52224
|
+
eventArgs.highlightBlocks.push(endSelectionBounds);
|
|
52225
|
+
endSelection.setBounds(endSelectionBounds.x, endSelectionBounds.y, endSelectionBounds.w, endSelectionBounds.h);
|
|
52046
52226
|
selectionWrapper.appendChild(endSelection);
|
|
52047
52227
|
}
|
|
52048
52228
|
else {
|
|
@@ -52051,6 +52231,7 @@
|
|
|
52051
52231
|
selection.setBounds(startX, startBeat.bounds.barBounds.masterBarBounds.visualBounds.y, endX - startX, startBeat.bounds.barBounds.masterBarBounds.visualBounds.h);
|
|
52052
52232
|
selectionWrapper.appendChild(selection);
|
|
52053
52233
|
}
|
|
52234
|
+
this.playbackRangeHighlightChanged.trigger(eventArgs);
|
|
52054
52235
|
}
|
|
52055
52236
|
/**
|
|
52056
52237
|
* This event is fired whenever a new song is loaded.
|
|
@@ -56489,12 +56670,12 @@
|
|
|
56489
56670
|
this.endPosition = endPosition;
|
|
56490
56671
|
}
|
|
56491
56672
|
get isLinkedWithPrevious() {
|
|
56492
|
-
return !!this.previousGlyph && this.previousGlyph.renderer.staff
|
|
56673
|
+
return !!this.previousGlyph && this.previousGlyph.renderer.staff?.system === this.renderer.staff.system;
|
|
56493
56674
|
}
|
|
56494
56675
|
get isLinkedWithNext() {
|
|
56495
56676
|
return (!!this.nextGlyph &&
|
|
56496
56677
|
this.nextGlyph.renderer.isFinalized &&
|
|
56497
|
-
this.nextGlyph.renderer.staff
|
|
56678
|
+
this.nextGlyph.renderer.staff?.system === this.renderer.staff.system);
|
|
56498
56679
|
}
|
|
56499
56680
|
paint(cx, cy, canvas) {
|
|
56500
56681
|
// if we are linked with the previous, the first glyph of the group will also render this one.
|
|
@@ -58882,6 +59063,437 @@
|
|
|
58882
59063
|
}
|
|
58883
59064
|
}
|
|
58884
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
|
+
|
|
58885
59497
|
/**
|
|
58886
59498
|
* This glyph acts as container for handling
|
|
58887
59499
|
* multiple voice rendering
|
|
@@ -59352,6 +59964,63 @@
|
|
|
59352
59964
|
}
|
|
59353
59965
|
}
|
|
59354
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
|
+
|
|
59355
60024
|
/**
|
|
59356
60025
|
* A Staff represents a single line within a StaffSystem.
|
|
59357
60026
|
* It stores BarRenderer instances created from a given factory.
|
|
@@ -59473,7 +60142,6 @@
|
|
|
59473
60142
|
this._sharedLayoutData = new Map();
|
|
59474
60143
|
const lastBar = this.barRenderers[this.barRenderers.length - 1];
|
|
59475
60144
|
this.barRenderers.splice(this.barRenderers.length - 1, 1);
|
|
59476
|
-
this.system.layout.unregisterBarRenderer(this.staffId, lastBar);
|
|
59477
60145
|
this.topOverflow = 0;
|
|
59478
60146
|
this.bottomOverflow = 0;
|
|
59479
60147
|
for (const r of this.barRenderers) {
|
|
@@ -59566,23 +60234,23 @@
|
|
|
59566
60234
|
// changes in the overflows
|
|
59567
60235
|
let needsSecondPass = false;
|
|
59568
60236
|
let topOverflow = this.topOverflow;
|
|
59569
|
-
for (
|
|
59570
|
-
this.
|
|
59571
|
-
if (
|
|
60237
|
+
for (const renderer of this.barRenderers) {
|
|
60238
|
+
renderer.registerMultiSystemSlurs(this.system.layout.slurRegistry.getAllContinuations(renderer));
|
|
60239
|
+
if (renderer.finalizeRenderer()) {
|
|
59572
60240
|
needsSecondPass = true;
|
|
59573
60241
|
}
|
|
59574
|
-
this.height = Math.max(this.height,
|
|
60242
|
+
this.height = Math.max(this.height, renderer.height);
|
|
59575
60243
|
}
|
|
59576
60244
|
// 2nd pass: move renderers to correct position respecting the new overflows
|
|
59577
60245
|
if (needsSecondPass) {
|
|
59578
60246
|
topOverflow = this.topOverflow;
|
|
59579
60247
|
// shift all the renderers to the new position to match required spacing
|
|
59580
|
-
for (
|
|
59581
|
-
|
|
60248
|
+
for (const renderer of this.barRenderers) {
|
|
60249
|
+
renderer.y = this.topPadding + topOverflow;
|
|
59582
60250
|
}
|
|
59583
60251
|
// finalize again (to align ties)
|
|
59584
|
-
for (
|
|
59585
|
-
|
|
60252
|
+
for (const renderer of this.barRenderers) {
|
|
60253
|
+
renderer.finalizeRenderer();
|
|
59586
60254
|
}
|
|
59587
60255
|
}
|
|
59588
60256
|
if (this.height > 0) {
|
|
@@ -60188,6 +60856,7 @@
|
|
|
60188
60856
|
if (newBarDisplayScale > barDisplayScale) {
|
|
60189
60857
|
barDisplayScale = newBarDisplayScale;
|
|
60190
60858
|
}
|
|
60859
|
+
lastBar.afterReverted();
|
|
60191
60860
|
}
|
|
60192
60861
|
this.width -= width;
|
|
60193
60862
|
this.computedWidth -= width;
|
|
@@ -60707,12 +61376,16 @@
|
|
|
60707
61376
|
constructor(renderer) {
|
|
60708
61377
|
this.renderer = renderer;
|
|
60709
61378
|
}
|
|
61379
|
+
slurRegistry = new SlurRegistry();
|
|
60710
61380
|
resize() {
|
|
60711
61381
|
this._lazyPartials.clear();
|
|
61382
|
+
this.slurRegistry.clear();
|
|
60712
61383
|
this.doResize();
|
|
60713
61384
|
}
|
|
60714
61385
|
layoutAndRender() {
|
|
60715
61386
|
this._lazyPartials.clear();
|
|
61387
|
+
this.slurRegistry.clear();
|
|
61388
|
+
this._barRendererLookup.clear();
|
|
60716
61389
|
this.profile = Environment.staveProfiles.get(this.renderer.settings.display.staveProfile);
|
|
60717
61390
|
const score = this.renderer.score;
|
|
60718
61391
|
this.firstBarIndex = ModelUtils.computeFirstDisplayedBarIndex(score, this.renderer.settings);
|
|
@@ -60981,17 +61654,6 @@
|
|
|
60981
61654
|
}
|
|
60982
61655
|
}
|
|
60983
61656
|
}
|
|
60984
|
-
unregisterBarRenderer(key, renderer) {
|
|
60985
|
-
if (this._barRendererLookup.has(key)) {
|
|
60986
|
-
const lookup = this._barRendererLookup.get(key);
|
|
60987
|
-
lookup.delete(renderer.bar.id);
|
|
60988
|
-
if (renderer.additionalMultiRestBars) {
|
|
60989
|
-
for (const b of renderer.additionalMultiRestBars) {
|
|
60990
|
-
lookup.delete(b.id);
|
|
60991
|
-
}
|
|
60992
|
-
}
|
|
60993
|
-
}
|
|
60994
|
-
}
|
|
60995
61657
|
getRendererForBar(key, bar) {
|
|
60996
61658
|
const barRendererId = bar.id;
|
|
60997
61659
|
if (this._barRendererLookup.has(key) && this._barRendererLookup.get(key).has(barRendererId)) {
|
|
@@ -61980,6 +62642,7 @@
|
|
|
61980
62642
|
_voiceContainers = new Map();
|
|
61981
62643
|
_postBeatGlyphs = new LeftToRightLayoutingGlyphGroup();
|
|
61982
62644
|
_ties = [];
|
|
62645
|
+
_multiSystemSlurs;
|
|
61983
62646
|
topEffects;
|
|
61984
62647
|
bottomEffects;
|
|
61985
62648
|
get nextRenderer() {
|
|
@@ -62132,6 +62795,11 @@
|
|
|
62132
62795
|
}
|
|
62133
62796
|
}
|
|
62134
62797
|
_appliedLayoutingInfo = 0;
|
|
62798
|
+
afterReverted() {
|
|
62799
|
+
this.staff = undefined;
|
|
62800
|
+
this.registerMultiSystemSlurs(undefined);
|
|
62801
|
+
this.isFinalized = false;
|
|
62802
|
+
}
|
|
62135
62803
|
afterStaffBarReverted() {
|
|
62136
62804
|
this.topEffects.afterStaffBarReverted();
|
|
62137
62805
|
this.bottomEffects.afterStaffBarReverted();
|
|
@@ -62177,13 +62845,26 @@
|
|
|
62177
62845
|
return true;
|
|
62178
62846
|
}
|
|
62179
62847
|
isFinalized = false;
|
|
62180
|
-
|
|
62181
|
-
|
|
62848
|
+
registerMultiSystemSlurs(startedTies) {
|
|
62849
|
+
if (!startedTies) {
|
|
62850
|
+
this._multiSystemSlurs = undefined;
|
|
62851
|
+
return;
|
|
62852
|
+
}
|
|
62853
|
+
let ties = undefined;
|
|
62854
|
+
for (const g of startedTies) {
|
|
62855
|
+
const continuation = new ContinuationTieGlyph(g);
|
|
62856
|
+
continuation.renderer = this;
|
|
62857
|
+
continuation.tieDirection = g.tieDirection;
|
|
62858
|
+
if (!ties) {
|
|
62859
|
+
ties = [];
|
|
62860
|
+
}
|
|
62861
|
+
ties.push(continuation);
|
|
62862
|
+
}
|
|
62863
|
+
this._multiSystemSlurs = ties;
|
|
62864
|
+
}
|
|
62865
|
+
_finalizeTies(ties, barTop, barBottom) {
|
|
62182
62866
|
let didChangeOverflows = false;
|
|
62183
|
-
|
|
62184
|
-
const barTop = this.y;
|
|
62185
|
-
const barBottom = this.y + this.height;
|
|
62186
|
-
for (const t of this._ties) {
|
|
62867
|
+
for (const t of ties) {
|
|
62187
62868
|
const tie = t;
|
|
62188
62869
|
tie.doLayout();
|
|
62189
62870
|
if (t.checkForOverflow) {
|
|
@@ -62204,6 +62885,21 @@
|
|
|
62204
62885
|
}
|
|
62205
62886
|
}
|
|
62206
62887
|
}
|
|
62888
|
+
return didChangeOverflows;
|
|
62889
|
+
}
|
|
62890
|
+
finalizeRenderer() {
|
|
62891
|
+
this.isFinalized = true;
|
|
62892
|
+
let didChangeOverflows = false;
|
|
62893
|
+
// allow spacing to be used for tie overflows
|
|
62894
|
+
const barTop = this.y;
|
|
62895
|
+
const barBottom = this.y + this.height;
|
|
62896
|
+
if (this._finalizeTies(this._ties, barTop, barBottom)) {
|
|
62897
|
+
didChangeOverflows = true;
|
|
62898
|
+
}
|
|
62899
|
+
const multiSystemSlurs = this._multiSystemSlurs;
|
|
62900
|
+
if (multiSystemSlurs && this._finalizeTies(multiSystemSlurs, barTop, barBottom)) {
|
|
62901
|
+
didChangeOverflows = true;
|
|
62902
|
+
}
|
|
62207
62903
|
const topHeightChanged = this.topEffects.finalizeEffects();
|
|
62208
62904
|
const bottomHeightChanged = this.bottomEffects.finalizeEffects();
|
|
62209
62905
|
if (topHeightChanged || bottomHeightChanged) {
|
|
@@ -62384,6 +63080,16 @@
|
|
|
62384
63080
|
}
|
|
62385
63081
|
canvas.color = this.resources.mainGlyphColor;
|
|
62386
63082
|
this._postBeatGlyphs.paint(cx + this.x, cy + this.y, canvas);
|
|
63083
|
+
this._paintMultiSystemSlurs(cx, cy, canvas);
|
|
63084
|
+
}
|
|
63085
|
+
_paintMultiSystemSlurs(cx, cy, canvas) {
|
|
63086
|
+
const multiSystemSlurs = this._multiSystemSlurs;
|
|
63087
|
+
if (!multiSystemSlurs) {
|
|
63088
|
+
return;
|
|
63089
|
+
}
|
|
63090
|
+
for (const slur of multiSystemSlurs) {
|
|
63091
|
+
slur.paint(cx, cy, canvas);
|
|
63092
|
+
}
|
|
62387
63093
|
}
|
|
62388
63094
|
paintBackground(cx, cy, canvas) {
|
|
62389
63095
|
this.layoutingInfo.paint(cx + this.x + this._preBeatGlyphs.x + this._preBeatGlyphs.width, cy + this.y + this.height, canvas);
|
|
@@ -64462,6 +65168,13 @@
|
|
|
64462
65168
|
}
|
|
64463
65169
|
}
|
|
64464
65170
|
else {
|
|
65171
|
+
// clear out staves during re-layout, this info is outdated during
|
|
65172
|
+
// re-layout of the bars
|
|
65173
|
+
for (const r of this._allMasterBarRenderers) {
|
|
65174
|
+
for (const b of r.renderers) {
|
|
65175
|
+
b.afterReverted();
|
|
65176
|
+
}
|
|
65177
|
+
}
|
|
64465
65178
|
this._systems = [];
|
|
64466
65179
|
let currentIndex = 0;
|
|
64467
65180
|
const maxWidth = this._maxWidth;
|
|
@@ -64923,7 +65636,7 @@
|
|
|
64923
65636
|
// as during layout things are still moving
|
|
64924
65637
|
let actualLineHeight = this.height;
|
|
64925
65638
|
const thisStaff = renderer.staff;
|
|
64926
|
-
const allStaves =
|
|
65639
|
+
const allStaves = thisStaff.system.allStaves;
|
|
64927
65640
|
let isExtended = false;
|
|
64928
65641
|
if (this._extendToNextStaff && thisStaff.index < allStaves.length - 1) {
|
|
64929
65642
|
const nextStaff = allStaves[thisStaff.index + 1];
|
|
@@ -65105,7 +65818,7 @@
|
|
|
65105
65818
|
}
|
|
65106
65819
|
// during system fitting it can happen that we have fraction widths
|
|
65107
65820
|
// but to have lines until the full end-pixel we round up.
|
|
65108
|
-
// this way we avoid holes,
|
|
65821
|
+
// this way we avoid holes,
|
|
65109
65822
|
const lineWidth = this.width;
|
|
65110
65823
|
// we want the lines to be exactly virtually aligned with the respective Y-position
|
|
65111
65824
|
// for note heads to align correctly
|
|
@@ -65871,375 +66584,23 @@
|
|
|
65871
66584
|
/**
|
|
65872
66585
|
* @internal
|
|
65873
66586
|
*/
|
|
65874
|
-
class
|
|
65875
|
-
startBeat;
|
|
65876
|
-
endBeat;
|
|
65877
|
-
yOffset = 0;
|
|
65878
|
-
forEnd;
|
|
65879
|
-
startNoteRenderer = null;
|
|
65880
|
-
endNoteRenderer = null;
|
|
65881
|
-
tieDirection = BeamDirection.Up;
|
|
65882
|
-
constructor(startBeat, endBeat, forEnd) {
|
|
65883
|
-
super(0, 0);
|
|
65884
|
-
this.startBeat = startBeat;
|
|
65885
|
-
this.endBeat = endBeat;
|
|
65886
|
-
this.forEnd = forEnd;
|
|
65887
|
-
}
|
|
65888
|
-
_startX = 0;
|
|
65889
|
-
_startY = 0;
|
|
65890
|
-
_endX = 0;
|
|
65891
|
-
_endY = 0;
|
|
65892
|
-
_tieHeight = 0;
|
|
65893
|
-
_shouldDraw = false;
|
|
65894
|
-
_boundingBox;
|
|
65895
|
-
get checkForOverflow() {
|
|
65896
|
-
return this._boundingBox !== undefined;
|
|
65897
|
-
}
|
|
65898
|
-
getBoundingBoxTop() {
|
|
65899
|
-
if (this._boundingBox) {
|
|
65900
|
-
return this._boundingBox.y;
|
|
65901
|
-
}
|
|
65902
|
-
return this._startY;
|
|
65903
|
-
}
|
|
65904
|
-
getBoundingBoxBottom() {
|
|
65905
|
-
if (this._boundingBox) {
|
|
65906
|
-
return this._boundingBox.y + this._boundingBox.h;
|
|
65907
|
-
}
|
|
65908
|
-
return this._startY;
|
|
65909
|
-
}
|
|
65910
|
-
doLayout() {
|
|
65911
|
-
this.width = 0;
|
|
65912
|
-
// TODO fix nullability of start/end beat,
|
|
65913
|
-
if (!this.endBeat) {
|
|
65914
|
-
this._shouldDraw = false;
|
|
65915
|
-
return;
|
|
65916
|
-
}
|
|
65917
|
-
const startNoteRenderer = this.renderer.scoreRenderer.layout.getRendererForBar(this.renderer.staff.staffId, this.startBeat.voice.bar);
|
|
65918
|
-
this.startNoteRenderer = startNoteRenderer;
|
|
65919
|
-
const endNoteRenderer = this.renderer.scoreRenderer.layout.getRendererForBar(this.renderer.staff.staffId, this.endBeat.voice.bar);
|
|
65920
|
-
this.endNoteRenderer = endNoteRenderer;
|
|
65921
|
-
this._startX = 0;
|
|
65922
|
-
this._endX = 0;
|
|
65923
|
-
this._startY = 0;
|
|
65924
|
-
this._endY = 0;
|
|
65925
|
-
this.height = 0;
|
|
65926
|
-
this._shouldDraw = false;
|
|
65927
|
-
// if we are on the tie start, we check if we
|
|
65928
|
-
// either can draw till the end note, or we just can draw till the bar end
|
|
65929
|
-
this.tieDirection = !startNoteRenderer
|
|
65930
|
-
? this.getBeamDirection(this.endBeat, endNoteRenderer)
|
|
65931
|
-
: this.getBeamDirection(this.startBeat, startNoteRenderer);
|
|
65932
|
-
if (!this.forEnd && startNoteRenderer) {
|
|
65933
|
-
// line break or bar break
|
|
65934
|
-
if (startNoteRenderer !== endNoteRenderer) {
|
|
65935
|
-
this._startX = startNoteRenderer.x + this.getStartX();
|
|
65936
|
-
this._startY = startNoteRenderer.y + this.getStartY() + this.yOffset;
|
|
65937
|
-
// line break: to bar end
|
|
65938
|
-
if (!endNoteRenderer || startNoteRenderer.staff !== endNoteRenderer.staff) {
|
|
65939
|
-
this._endX = startNoteRenderer.x + startNoteRenderer.width;
|
|
65940
|
-
this._endY = this._startY;
|
|
65941
|
-
}
|
|
65942
|
-
else {
|
|
65943
|
-
this._endX = endNoteRenderer.x + this.getEndX();
|
|
65944
|
-
this._endY = endNoteRenderer.y + this.getEndY() + this.yOffset;
|
|
65945
|
-
}
|
|
65946
|
-
}
|
|
65947
|
-
else {
|
|
65948
|
-
this._startX = startNoteRenderer.x + this.getStartX();
|
|
65949
|
-
this._endX = endNoteRenderer.x + this.getEndX();
|
|
65950
|
-
this._startY = startNoteRenderer.y + this.getStartY() + this.yOffset;
|
|
65951
|
-
this._endY = endNoteRenderer.y + this.getEndY() + this.yOffset;
|
|
65952
|
-
}
|
|
65953
|
-
this._shouldDraw = true;
|
|
65954
|
-
}
|
|
65955
|
-
else if (!startNoteRenderer || startNoteRenderer.staff !== endNoteRenderer.staff) {
|
|
65956
|
-
this._startX = endNoteRenderer.x;
|
|
65957
|
-
this._endX = endNoteRenderer.x + this.getEndX();
|
|
65958
|
-
this._startY = endNoteRenderer.y + this.getEndY() + this.yOffset;
|
|
65959
|
-
this._endY = this._startY;
|
|
65960
|
-
this._shouldDraw = true;
|
|
65961
|
-
}
|
|
65962
|
-
this._boundingBox = undefined;
|
|
65963
|
-
if (this._shouldDraw) {
|
|
65964
|
-
this.y = Math.min(this._startY, this._endY);
|
|
65965
|
-
if (this.shouldDrawBendSlur()) {
|
|
65966
|
-
this._tieHeight = 0; // TODO: Bend slur height to be considered?
|
|
65967
|
-
}
|
|
65968
|
-
else {
|
|
65969
|
-
this._tieHeight = this.getTieHeight(this._startX, this._startY, this._endX, this._endY);
|
|
65970
|
-
const tieBoundingBox = TieGlyph.calculateActualTieHeight(1, this._startX, this._startY, this._endX, this._endY, this.tieDirection === BeamDirection.Down, this._tieHeight, this.renderer.smuflMetrics.tieMidpointThickness);
|
|
65971
|
-
this._boundingBox = tieBoundingBox;
|
|
65972
|
-
this.height = tieBoundingBox.h;
|
|
65973
|
-
if (this.tieDirection === BeamDirection.Up) {
|
|
65974
|
-
// the tie might go above `this.y` due to its shape
|
|
65975
|
-
// here we calculate how much this is so we can consider the
|
|
65976
|
-
// respective overflow
|
|
65977
|
-
const overlap = this.y - tieBoundingBox.y;
|
|
65978
|
-
if (overlap > 0) {
|
|
65979
|
-
this.y -= overlap;
|
|
65980
|
-
}
|
|
65981
|
-
}
|
|
65982
|
-
}
|
|
65983
|
-
}
|
|
65984
|
-
}
|
|
65985
|
-
paint(cx, cy, canvas) {
|
|
65986
|
-
if (this._shouldDraw) {
|
|
65987
|
-
if (this.shouldDrawBendSlur()) {
|
|
65988
|
-
TieGlyph.drawBendSlur(canvas, cx + this._startX, cy + this._startY, cx + this._endX, cy + this._endY, this.tieDirection === BeamDirection.Down, 1, this.renderer.smuflMetrics.tieHeight);
|
|
65989
|
-
}
|
|
65990
|
-
else {
|
|
65991
|
-
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);
|
|
65992
|
-
}
|
|
65993
|
-
}
|
|
65994
|
-
}
|
|
65995
|
-
shouldDrawBendSlur() {
|
|
65996
|
-
return false;
|
|
65997
|
-
}
|
|
65998
|
-
getTieHeight(_startX, _startY, _endX, _endY) {
|
|
65999
|
-
return this.renderer.smuflMetrics.tieHeight;
|
|
66000
|
-
}
|
|
66001
|
-
getBeamDirection(_beat, _noteRenderer) {
|
|
66002
|
-
return BeamDirection.Down;
|
|
66003
|
-
}
|
|
66004
|
-
getStartY() {
|
|
66005
|
-
return 0;
|
|
66006
|
-
}
|
|
66007
|
-
getEndY() {
|
|
66008
|
-
return 0;
|
|
66009
|
-
}
|
|
66010
|
-
getStartX() {
|
|
66011
|
-
return 0;
|
|
66012
|
-
}
|
|
66013
|
-
getEndX() {
|
|
66014
|
-
return 0;
|
|
66015
|
-
}
|
|
66016
|
-
static calculateActualTieHeight(scale, x1, y1, x2, y2, down, offset, size) {
|
|
66017
|
-
const cp = TieGlyph._computeBezierControlPoints(scale, x1, y1, x2, y2, down, offset, size);
|
|
66018
|
-
// For a musical tie/slur, the extrema occur predictably near the midpoint
|
|
66019
|
-
// Evaluate at midpoint (t=0.5) and check endpoints
|
|
66020
|
-
const p0x = cp[0];
|
|
66021
|
-
const p0y = cp[1];
|
|
66022
|
-
const c1x = cp[2];
|
|
66023
|
-
const c1y = cp[3];
|
|
66024
|
-
const c2x = cp[4];
|
|
66025
|
-
const c2y = cp[5];
|
|
66026
|
-
const p1x = cp[6];
|
|
66027
|
-
const p1y = cp[7];
|
|
66028
|
-
// Evaluate at t=0.5 for midpoint
|
|
66029
|
-
const midX = 0.125 * p0x + 0.375 * c1x + 0.375 * c2x + 0.125 * p1x;
|
|
66030
|
-
const midY = 0.125 * p0y + 0.375 * c1y + 0.375 * c2y + 0.125 * p1y;
|
|
66031
|
-
// Bounds are simply min/max of start, end, and midpoint
|
|
66032
|
-
const xMin = Math.min(p0x, p1x, midX);
|
|
66033
|
-
const xMax = Math.max(p0x, p1x, midX);
|
|
66034
|
-
let yMin = Math.min(p0y, p1y, midY);
|
|
66035
|
-
let yMax = Math.max(p0y, p1y, midY);
|
|
66036
|
-
// Account for thickness of the tie/slur
|
|
66037
|
-
if (down) {
|
|
66038
|
-
yMax += size;
|
|
66039
|
-
}
|
|
66040
|
-
else {
|
|
66041
|
-
yMin -= size;
|
|
66042
|
-
}
|
|
66043
|
-
const b = new Bounds();
|
|
66044
|
-
b.x = xMin;
|
|
66045
|
-
b.y = yMin;
|
|
66046
|
-
b.w = xMax - xMin;
|
|
66047
|
-
b.h = yMax - yMin;
|
|
66048
|
-
return b;
|
|
66049
|
-
}
|
|
66050
|
-
static _computeBezierControlPoints(scale, x1, y1, x2, y2, down, offset, size) {
|
|
66051
|
-
if (x1 === x2 && y1 === y2) {
|
|
66052
|
-
return [];
|
|
66053
|
-
}
|
|
66054
|
-
// ensure endX > startX
|
|
66055
|
-
if (x2 < x1) {
|
|
66056
|
-
let t = x1;
|
|
66057
|
-
x1 = x2;
|
|
66058
|
-
x2 = t;
|
|
66059
|
-
t = y1;
|
|
66060
|
-
y1 = y2;
|
|
66061
|
-
y2 = t;
|
|
66062
|
-
}
|
|
66063
|
-
//
|
|
66064
|
-
// calculate control points
|
|
66065
|
-
//
|
|
66066
|
-
offset *= scale;
|
|
66067
|
-
size *= scale;
|
|
66068
|
-
if (down) {
|
|
66069
|
-
offset *= -1;
|
|
66070
|
-
size *= -1;
|
|
66071
|
-
}
|
|
66072
|
-
if (scale >= 1) {
|
|
66073
|
-
size *= 1.2;
|
|
66074
|
-
}
|
|
66075
|
-
// calculate control points on horizontal axis then rotate:
|
|
66076
|
-
/*
|
|
66077
|
-
cp1x/cpy1 cp2x/cpy2
|
|
66078
|
-
*----------------*
|
|
66079
|
-
/ \
|
|
66080
|
-
/ \
|
|
66081
|
-
x1/y1 * * x2/y2
|
|
66082
|
-
|
|
66083
|
-
cp3 and cp4 are simply with lower height
|
|
66084
|
-
*/
|
|
66085
|
-
const dY = y2 - y1;
|
|
66086
|
-
const dX = x2 - x1;
|
|
66087
|
-
const length = Math.sqrt(dX * dX + dY * dY);
|
|
66088
|
-
let cp1x = x1 + length * 0.25;
|
|
66089
|
-
let cp1y = y1 - offset;
|
|
66090
|
-
let cp2x = x1 + length * 0.75;
|
|
66091
|
-
let cp2y = y1 - offset;
|
|
66092
|
-
let cp3x = x1 + length * 0.75;
|
|
66093
|
-
let cp3y = y1 - offset - size;
|
|
66094
|
-
let cp4x = x1 + length * 0.25;
|
|
66095
|
-
let cp4y = y1 - offset - size;
|
|
66096
|
-
const angle = Math.atan2(dY, dX);
|
|
66097
|
-
[cp1x, cp1y] = TieGlyph._rotate(cp1x, cp1y, x1, y1, angle);
|
|
66098
|
-
[cp2x, cp2y] = TieGlyph._rotate(cp2x, cp2y, x1, y1, angle);
|
|
66099
|
-
[cp3x, cp3y] = TieGlyph._rotate(cp3x, cp3y, x1, y1, angle);
|
|
66100
|
-
[cp4x, cp4y] = TieGlyph._rotate(cp4x, cp4y, x1, y1, angle);
|
|
66101
|
-
return [x1, y1, cp1x, cp1y, cp2x, cp2y, x2, y2, cp3x, cp3y, cp4x, cp4y, x1, y1];
|
|
66102
|
-
}
|
|
66103
|
-
static _rotate(x, y, rotateX, rotateY, angle) {
|
|
66104
|
-
const dx = x - rotateX;
|
|
66105
|
-
const dy = y - rotateY;
|
|
66106
|
-
const rx = dx * Math.cos(angle) - dy * Math.sin(angle);
|
|
66107
|
-
const ry = dx * Math.sin(angle) + dy * Math.cos(angle);
|
|
66108
|
-
return [rotateX + rx, rotateY + ry];
|
|
66109
|
-
}
|
|
66110
|
-
static paintTie(canvas, scale, x1, y1, x2, y2, down /*= false*/, offset /*= 22*/, size /*= 4*/) {
|
|
66111
|
-
const cps = TieGlyph._computeBezierControlPoints(scale, x1, y1, x2, y2, down, offset, size);
|
|
66112
|
-
canvas.beginPath();
|
|
66113
|
-
canvas.moveTo(cps[0], cps[1]);
|
|
66114
|
-
canvas.bezierCurveTo(cps[2], cps[3], cps[4], cps[5], cps[6], cps[7]);
|
|
66115
|
-
canvas.bezierCurveTo(cps[8], cps[9], cps[10], cps[11], cps[12], cps[13]);
|
|
66116
|
-
canvas.closePath();
|
|
66117
|
-
canvas.fill();
|
|
66118
|
-
}
|
|
66119
|
-
static calculateBendSlurTopY(x1, y1, x2, y2, down, scale, bendSlurHeight) {
|
|
66120
|
-
let normalVectorX = y2 - y1;
|
|
66121
|
-
let normalVectorY = x2 - x1;
|
|
66122
|
-
const length = Math.sqrt(normalVectorX * normalVectorX + normalVectorY * normalVectorY);
|
|
66123
|
-
if (down) {
|
|
66124
|
-
normalVectorX *= -1;
|
|
66125
|
-
}
|
|
66126
|
-
else {
|
|
66127
|
-
normalVectorY *= -1;
|
|
66128
|
-
}
|
|
66129
|
-
// make to unit vector
|
|
66130
|
-
normalVectorX /= length;
|
|
66131
|
-
normalVectorY /= length;
|
|
66132
|
-
let offset = bendSlurHeight * scale;
|
|
66133
|
-
if (x2 - x1 < 20) {
|
|
66134
|
-
offset /= 2;
|
|
66135
|
-
}
|
|
66136
|
-
const centerY = (y2 + y1) / 2;
|
|
66137
|
-
const cp1Y = centerY + offset * normalVectorY;
|
|
66138
|
-
return cp1Y;
|
|
66139
|
-
}
|
|
66140
|
-
static drawBendSlur(canvas, x1, y1, x2, y2, down, scale, bendSlurHeight, slurText) {
|
|
66141
|
-
let normalVectorX = y2 - y1;
|
|
66142
|
-
let normalVectorY = x2 - x1;
|
|
66143
|
-
const length = Math.sqrt(normalVectorX * normalVectorX + normalVectorY * normalVectorY);
|
|
66144
|
-
if (down) {
|
|
66145
|
-
normalVectorX *= -1;
|
|
66146
|
-
}
|
|
66147
|
-
else {
|
|
66148
|
-
normalVectorY *= -1;
|
|
66149
|
-
}
|
|
66150
|
-
// make to unit vector
|
|
66151
|
-
normalVectorX /= length;
|
|
66152
|
-
normalVectorY /= length;
|
|
66153
|
-
// center of connection
|
|
66154
|
-
// TODO: should be 1/3
|
|
66155
|
-
const centerX = (x2 + x1) / 2;
|
|
66156
|
-
const centerY = (y2 + y1) / 2;
|
|
66157
|
-
let offset = bendSlurHeight * scale;
|
|
66158
|
-
if (x2 - x1 < 20) {
|
|
66159
|
-
offset /= 2;
|
|
66160
|
-
}
|
|
66161
|
-
const cp1X = centerX + offset * normalVectorX;
|
|
66162
|
-
const cp1Y = centerY + offset * normalVectorY;
|
|
66163
|
-
canvas.beginPath();
|
|
66164
|
-
canvas.moveTo(x1, y1);
|
|
66165
|
-
canvas.lineTo(cp1X, cp1Y);
|
|
66166
|
-
canvas.lineTo(x2, y2);
|
|
66167
|
-
canvas.stroke();
|
|
66168
|
-
if (slurText) {
|
|
66169
|
-
const w = canvas.measureText(slurText).width;
|
|
66170
|
-
const textOffset = down ? 0 : -canvas.font.size;
|
|
66171
|
-
canvas.fillText(slurText, cp1X - w / 2, cp1Y + textOffset);
|
|
66172
|
-
}
|
|
66173
|
-
}
|
|
66174
|
-
}
|
|
66175
|
-
|
|
66176
|
-
/**
|
|
66177
|
-
* @internal
|
|
66178
|
-
*/
|
|
66179
|
-
class NumberedTieGlyph extends TieGlyph {
|
|
66180
|
-
startNote;
|
|
66181
|
-
endNote;
|
|
66182
|
-
constructor(startNote, endNote, forEnd = false) {
|
|
66183
|
-
super(!startNote ? null : startNote.beat, !endNote ? null : endNote.beat, forEnd);
|
|
66184
|
-
this.startNote = startNote;
|
|
66185
|
-
this.endNote = endNote;
|
|
66186
|
-
}
|
|
66187
|
-
get _isLeftHandTap() {
|
|
66188
|
-
return this.startNote === this.endNote;
|
|
66189
|
-
}
|
|
66587
|
+
class NumberedTieGlyph extends NoteTieGlyph {
|
|
66190
66588
|
shouldDrawBendSlur() {
|
|
66191
66589
|
return (this.renderer.settings.notation.extendBendArrowsOnTiedNotes &&
|
|
66192
66590
|
!!this.startNote.bendOrigin &&
|
|
66193
66591
|
this.startNote.isTieOrigin);
|
|
66194
66592
|
}
|
|
66195
|
-
|
|
66196
|
-
super.doLayout();
|
|
66197
|
-
}
|
|
66198
|
-
getBeamDirection(_beat, _noteRenderer) {
|
|
66593
|
+
calculateTieDirection() {
|
|
66199
66594
|
return BeamDirection.Up;
|
|
66200
66595
|
}
|
|
66201
|
-
getStartY() {
|
|
66202
|
-
return this.startNoteRenderer.getNoteY(this.startNote, NoteYPosition.Top);
|
|
66203
|
-
}
|
|
66204
|
-
getEndY() {
|
|
66205
|
-
return this.getStartY();
|
|
66206
|
-
}
|
|
66207
|
-
getStartX() {
|
|
66208
|
-
if (this._isLeftHandTap) {
|
|
66209
|
-
return this.getEndX() - this.startNoteRenderer.smuflMetrics.leftHandTabTieWidth;
|
|
66210
|
-
}
|
|
66211
|
-
return this.startNoteRenderer.getNoteX(this.startNote, NoteXPosition.Center);
|
|
66212
|
-
}
|
|
66213
|
-
getEndX() {
|
|
66214
|
-
if (this._isLeftHandTap) {
|
|
66215
|
-
return this.endNoteRenderer.getNoteX(this.endNote, NoteXPosition.Left);
|
|
66216
|
-
}
|
|
66217
|
-
return this.endNoteRenderer.getNoteX(this.endNote, NoteXPosition.Center);
|
|
66218
|
-
}
|
|
66219
66596
|
}
|
|
66220
66597
|
|
|
66221
66598
|
/**
|
|
66222
66599
|
* @internal
|
|
66223
66600
|
*/
|
|
66224
|
-
class TabTieGlyph extends
|
|
66225
|
-
|
|
66226
|
-
|
|
66227
|
-
constructor(startNote, endNote, forEnd = false) {
|
|
66228
|
-
super(startNote.beat, endNote.beat, forEnd);
|
|
66229
|
-
this.startNote = startNote;
|
|
66230
|
-
this.endNote = endNote;
|
|
66231
|
-
}
|
|
66232
|
-
get _isLeftHandTap() {
|
|
66233
|
-
return this.startNote === this.endNote;
|
|
66234
|
-
}
|
|
66235
|
-
getTieHeight(startX, startY, endX, endY) {
|
|
66236
|
-
if (this._isLeftHandTap) {
|
|
66237
|
-
return this.startNoteRenderer.smuflMetrics.tieHeight;
|
|
66238
|
-
}
|
|
66239
|
-
return super.getTieHeight(startX, startY, endX, endY);
|
|
66240
|
-
}
|
|
66241
|
-
getBeamDirection(_beat, _noteRenderer) {
|
|
66242
|
-
if (this._isLeftHandTap) {
|
|
66601
|
+
class TabTieGlyph extends NoteTieGlyph {
|
|
66602
|
+
calculateTieDirection() {
|
|
66603
|
+
if (this.isLeftHandTap) {
|
|
66243
66604
|
return BeamDirection.Up;
|
|
66244
66605
|
}
|
|
66245
66606
|
return TabTieGlyph.getBeamDirectionForNote(this.startNote);
|
|
@@ -66247,54 +66608,25 @@
|
|
|
66247
66608
|
static getBeamDirectionForNote(note) {
|
|
66248
66609
|
return note.string > 3 ? BeamDirection.Up : BeamDirection.Down;
|
|
66249
66610
|
}
|
|
66250
|
-
getStartY() {
|
|
66251
|
-
if (this._isLeftHandTap) {
|
|
66252
|
-
return this.startNoteRenderer.getNoteY(this.startNote, NoteYPosition.Center);
|
|
66253
|
-
}
|
|
66254
|
-
if (this.tieDirection === BeamDirection.Up) {
|
|
66255
|
-
return this.startNoteRenderer.getNoteY(this.startNote, NoteYPosition.Top);
|
|
66256
|
-
}
|
|
66257
|
-
return this.startNoteRenderer.getNoteY(this.startNote, NoteYPosition.Bottom);
|
|
66258
|
-
}
|
|
66259
|
-
getEndY() {
|
|
66260
|
-
return this.getStartY();
|
|
66261
|
-
}
|
|
66262
|
-
getStartX() {
|
|
66263
|
-
if (this._isLeftHandTap) {
|
|
66264
|
-
return this.getEndX() - this.renderer.smuflMetrics.leftHandTabTieWidth;
|
|
66265
|
-
}
|
|
66266
|
-
return this.startNoteRenderer.getNoteX(this.startNote, NoteXPosition.Center);
|
|
66267
|
-
}
|
|
66268
|
-
getEndX() {
|
|
66269
|
-
if (this._isLeftHandTap) {
|
|
66270
|
-
return this.endNoteRenderer.getNoteX(this.endNote, NoteXPosition.Left);
|
|
66271
|
-
}
|
|
66272
|
-
return this.endNoteRenderer.getNoteX(this.endNote, NoteXPosition.Center);
|
|
66273
|
-
}
|
|
66274
66611
|
}
|
|
66275
66612
|
|
|
66276
66613
|
/**
|
|
66277
66614
|
* @internal
|
|
66278
66615
|
*/
|
|
66279
|
-
class
|
|
66280
|
-
_direction;
|
|
66616
|
+
class TabSlurGlyph extends TabTieGlyph {
|
|
66281
66617
|
_forSlide;
|
|
66282
|
-
constructor(startNote, endNote, forSlide, forEnd
|
|
66283
|
-
super(startNote, endNote, forEnd);
|
|
66284
|
-
this._direction = BeamDirection.Up;
|
|
66618
|
+
constructor(slurEffectId, startNote, endNote, forSlide, forEnd) {
|
|
66619
|
+
super(slurEffectId, startNote, endNote, forEnd);
|
|
66285
66620
|
this._forSlide = forSlide;
|
|
66286
66621
|
}
|
|
66287
66622
|
getTieHeight(startX, _startY, endX, _endY) {
|
|
66288
|
-
return Math.log(endX - startX + 1) * this.renderer.settings.notation.slurHeight / 2;
|
|
66623
|
+
return (Math.log(endX - startX + 1) * this.renderer.settings.notation.slurHeight) / 2;
|
|
66289
66624
|
}
|
|
66290
66625
|
tryExpand(startNote, endNote, forSlide, forEnd) {
|
|
66291
66626
|
// same type required
|
|
66292
66627
|
if (this._forSlide !== forSlide) {
|
|
66293
66628
|
return false;
|
|
66294
66629
|
}
|
|
66295
|
-
if (this.forEnd !== forEnd) {
|
|
66296
|
-
return false;
|
|
66297
|
-
}
|
|
66298
66630
|
// same start and endbeat
|
|
66299
66631
|
if (this.startNote.beat.id !== startNote.beat.id) {
|
|
66300
66632
|
return false;
|
|
@@ -66302,41 +66634,43 @@
|
|
|
66302
66634
|
if (this.endNote.beat.id !== endNote.beat.id) {
|
|
66303
66635
|
return false;
|
|
66304
66636
|
}
|
|
66637
|
+
const isForEnd = this.renderer === this.lookupEndBeatRenderer();
|
|
66638
|
+
if (isForEnd !== forEnd) {
|
|
66639
|
+
return false;
|
|
66640
|
+
}
|
|
66641
|
+
// same draw direction
|
|
66642
|
+
if (this.tieDirection !== TabTieGlyph.getBeamDirectionForNote(startNote)) {
|
|
66643
|
+
return false;
|
|
66644
|
+
}
|
|
66305
66645
|
// if we can expand, expand in correct direction
|
|
66306
|
-
switch (this.
|
|
66646
|
+
switch (this.tieDirection) {
|
|
66307
66647
|
case BeamDirection.Up:
|
|
66308
66648
|
if (startNote.realValue > this.startNote.realValue) {
|
|
66309
66649
|
this.startNote = startNote;
|
|
66310
|
-
this.startBeat = startNote.beat;
|
|
66311
66650
|
}
|
|
66312
66651
|
if (endNote.realValue > this.endNote.realValue) {
|
|
66313
66652
|
this.endNote = endNote;
|
|
66314
|
-
this.endBeat = endNote.beat;
|
|
66315
66653
|
}
|
|
66316
66654
|
break;
|
|
66317
66655
|
case BeamDirection.Down:
|
|
66318
66656
|
if (startNote.realValue < this.startNote.realValue) {
|
|
66319
66657
|
this.startNote = startNote;
|
|
66320
|
-
this.startBeat = startNote.beat;
|
|
66321
66658
|
}
|
|
66322
66659
|
if (endNote.realValue < this.endNote.realValue) {
|
|
66323
66660
|
this.endNote = endNote;
|
|
66324
|
-
this.endBeat = endNote.beat;
|
|
66325
66661
|
}
|
|
66326
66662
|
break;
|
|
66327
66663
|
}
|
|
66328
66664
|
return true;
|
|
66329
66665
|
}
|
|
66330
|
-
|
|
66331
|
-
|
|
66332
|
-
|
|
66333
|
-
|
|
66334
|
-
|
|
66335
|
-
|
|
66336
|
-
|
|
66337
|
-
|
|
66338
|
-
super.paint(cx, cy, canvas);
|
|
66339
|
-
}
|
|
66666
|
+
}
|
|
66667
|
+
|
|
66668
|
+
/**
|
|
66669
|
+
* @internal
|
|
66670
|
+
*/
|
|
66671
|
+
class NumberedSlurGlyph extends TabSlurGlyph {
|
|
66672
|
+
calculateTieDirection() {
|
|
66673
|
+
return BeamDirection.Up;
|
|
66340
66674
|
}
|
|
66341
66675
|
}
|
|
66342
66676
|
|
|
@@ -66344,23 +66678,31 @@
|
|
|
66344
66678
|
* @internal
|
|
66345
66679
|
*/
|
|
66346
66680
|
class NumberedBeatContainerGlyph extends BeatContainerGlyph {
|
|
66681
|
+
_slurs = new Map();
|
|
66347
66682
|
_effectSlurs = [];
|
|
66683
|
+
doLayout() {
|
|
66684
|
+
this._slurs.clear();
|
|
66685
|
+
this._effectSlurs = [];
|
|
66686
|
+
super.doLayout();
|
|
66687
|
+
}
|
|
66348
66688
|
createTies(n) {
|
|
66349
66689
|
// create a tie if any effect requires it
|
|
66350
66690
|
if (!n.isVisible) {
|
|
66351
66691
|
return;
|
|
66352
66692
|
}
|
|
66353
|
-
if (n.isTieOrigin && n.tieDestination.isVisible) {
|
|
66354
|
-
const tie = new NumberedTieGlyph(n, n.tieDestination, false);
|
|
66693
|
+
if (n.isTieOrigin && n.tieDestination.isVisible && !this._slurs.has('numbered.tie')) {
|
|
66694
|
+
const tie = new NumberedTieGlyph(`numbered.tie.${n.beat.id}`, n, n.tieDestination, false);
|
|
66355
66695
|
this.addTie(tie);
|
|
66696
|
+
this._slurs.set(tie.slurEffectId, tie);
|
|
66356
66697
|
}
|
|
66357
66698
|
if (n.isTieDestination) {
|
|
66358
|
-
const tie = new NumberedTieGlyph(n.tieOrigin, n, true);
|
|
66699
|
+
const tie = new NumberedTieGlyph(`numbered.tie.${n.tieOrigin.beat.id}`, n.tieOrigin, n, true);
|
|
66359
66700
|
this.addTie(tie);
|
|
66360
66701
|
}
|
|
66361
|
-
if (n.isLeftHandTapped && !n.isHammerPullDestination) {
|
|
66362
|
-
const tapSlur = new NumberedTieGlyph(n, n, false);
|
|
66702
|
+
if (n.isLeftHandTapped && !n.isHammerPullDestination && !this._slurs.has(`numbered.tie.leftHandTap.${n.beat.id}`)) {
|
|
66703
|
+
const tapSlur = new NumberedTieGlyph(`numbered.tie.leftHandTap.${n.beat.id}`, n, n, false);
|
|
66363
66704
|
this.addTie(tapSlur);
|
|
66705
|
+
this._slurs.set(tapSlur.slurEffectId, tapSlur);
|
|
66364
66706
|
}
|
|
66365
66707
|
// start effect slur on first beat
|
|
66366
66708
|
if (n.isEffectSlurOrigin && n.effectSlurDestination) {
|
|
@@ -66372,9 +66714,11 @@
|
|
|
66372
66714
|
}
|
|
66373
66715
|
}
|
|
66374
66716
|
if (!expanded) {
|
|
66375
|
-
const effectSlur = new NumberedSlurGlyph(n, n.effectSlurDestination, false, false);
|
|
66717
|
+
const effectSlur = new NumberedSlurGlyph(`numbered.slur.effect`, n, n.effectSlurDestination, false, false);
|
|
66376
66718
|
this._effectSlurs.push(effectSlur);
|
|
66377
66719
|
this.addTie(effectSlur);
|
|
66720
|
+
this._slurs.set(effectSlur.slurEffectId, effectSlur);
|
|
66721
|
+
this._slurs.set('numbered.slur.effect', effectSlur);
|
|
66378
66722
|
}
|
|
66379
66723
|
}
|
|
66380
66724
|
// end effect slur on last beat
|
|
@@ -66387,9 +66731,11 @@
|
|
|
66387
66731
|
}
|
|
66388
66732
|
}
|
|
66389
66733
|
if (!expanded) {
|
|
66390
|
-
const effectSlur = new NumberedSlurGlyph(n.effectSlurOrigin, n, false, true);
|
|
66734
|
+
const effectSlur = new NumberedSlurGlyph(`numbered.slur.effect`, n.effectSlurOrigin, n, false, true);
|
|
66391
66735
|
this._effectSlurs.push(effectSlur);
|
|
66392
66736
|
this.addTie(effectSlur);
|
|
66737
|
+
this._slurs.set(effectSlur.slurEffectId, effectSlur);
|
|
66738
|
+
this._slurs.set('numbered.slur.effect', effectSlur);
|
|
66393
66739
|
}
|
|
66394
66740
|
}
|
|
66395
66741
|
}
|
|
@@ -66782,10 +67128,11 @@
|
|
|
66782
67128
|
if (sr.shortestDuration < this.container.beat.duration) {
|
|
66783
67129
|
sr.shortestDuration = this.container.beat.duration;
|
|
66784
67130
|
}
|
|
66785
|
-
const glyphY = sr.getLineY(sr.getNoteLine());
|
|
66786
67131
|
if (!this.container.beat.isEmpty) {
|
|
67132
|
+
const glyphY = sr.getLineY(0);
|
|
66787
67133
|
let numberWithinOctave = '0';
|
|
66788
67134
|
if (this.container.beat.notes.length > 0) {
|
|
67135
|
+
const note = this.container.beat.notes[0];
|
|
66789
67136
|
const kst = this.renderer.bar.keySignatureType;
|
|
66790
67137
|
const ks = this.renderer.bar.keySignature;
|
|
66791
67138
|
const ksi = ks + 7;
|
|
@@ -66793,7 +67140,6 @@
|
|
|
66793
67140
|
? NumberedBeatGlyph.minorKeySignatureOneValues
|
|
66794
67141
|
: NumberedBeatGlyph.majorKeySignatureOneValues;
|
|
66795
67142
|
const oneNoteValue = oneNoteValues[ksi];
|
|
66796
|
-
const note = this.container.beat.notes[0];
|
|
66797
67143
|
if (note.isDead) {
|
|
66798
67144
|
numberWithinOctave = 'X';
|
|
66799
67145
|
}
|
|
@@ -66840,7 +67186,7 @@
|
|
|
66840
67186
|
// Note dots
|
|
66841
67187
|
if (this.container.beat.dots > 0 && this.container.beat.duration >= Duration.Quarter) {
|
|
66842
67188
|
for (let i = 0; i < this.container.beat.dots; i++) {
|
|
66843
|
-
const dot = new AugmentationDotGlyph(0,
|
|
67189
|
+
const dot = new AugmentationDotGlyph(0, glyphY);
|
|
66844
67190
|
dot.renderer = this.renderer;
|
|
66845
67191
|
this.addEffect(dot);
|
|
66846
67192
|
}
|
|
@@ -66868,7 +67214,7 @@
|
|
|
66868
67214
|
numberOfQuarterNotes += numberOfAddedQuarters;
|
|
66869
67215
|
}
|
|
66870
67216
|
for (let i = 0; i < numberOfQuarterNotes - 1; i++) {
|
|
66871
|
-
const dash = new NumberedDashGlyph(0,
|
|
67217
|
+
const dash = new NumberedDashGlyph(0, glyphY, this.container.beat);
|
|
66872
67218
|
dash.renderer = this.renderer;
|
|
66873
67219
|
this.addNormal(dash);
|
|
66874
67220
|
}
|
|
@@ -67338,7 +67684,7 @@
|
|
|
67338
67684
|
}
|
|
67339
67685
|
}
|
|
67340
67686
|
}
|
|
67341
|
-
getNoteLine() {
|
|
67687
|
+
getNoteLine(_note) {
|
|
67342
67688
|
return 0;
|
|
67343
67689
|
}
|
|
67344
67690
|
get tupletOffset() {
|
|
@@ -69553,87 +69899,128 @@
|
|
|
69553
69899
|
* @internal
|
|
69554
69900
|
*/
|
|
69555
69901
|
class ScoreLegatoGlyph extends TieGlyph {
|
|
69556
|
-
|
|
69557
|
-
|
|
69902
|
+
startBeat;
|
|
69903
|
+
endBeat;
|
|
69904
|
+
startBeatRenderer = null;
|
|
69905
|
+
endBeatRenderer = null;
|
|
69906
|
+
constructor(slurEffectId, startBeat, endBeat, forEnd) {
|
|
69907
|
+
super(slurEffectId, forEnd);
|
|
69908
|
+
this.startBeat = startBeat;
|
|
69909
|
+
this.endBeat = endBeat;
|
|
69558
69910
|
}
|
|
69559
69911
|
doLayout() {
|
|
69560
69912
|
super.doLayout();
|
|
69561
69913
|
}
|
|
69562
|
-
|
|
69563
|
-
if (
|
|
69914
|
+
lookupStartBeatRenderer() {
|
|
69915
|
+
if (!this.startBeatRenderer) {
|
|
69916
|
+
this.startBeatRenderer = this.renderer.scoreRenderer.layout.getRendererForBar(this.renderer.staff.staffId, this.startBeat.voice.bar);
|
|
69917
|
+
}
|
|
69918
|
+
return this.startBeatRenderer;
|
|
69919
|
+
}
|
|
69920
|
+
lookupEndBeatRenderer() {
|
|
69921
|
+
if (!this.endBeatRenderer) {
|
|
69922
|
+
this.endBeatRenderer = this.renderer.scoreRenderer.layout.getRendererForBar(this.renderer.staff.staffId, this.endBeat.voice.bar);
|
|
69923
|
+
}
|
|
69924
|
+
return this.endBeatRenderer;
|
|
69925
|
+
}
|
|
69926
|
+
shouldDrawBendSlur() {
|
|
69927
|
+
return false;
|
|
69928
|
+
}
|
|
69929
|
+
calculateTieDirection() {
|
|
69930
|
+
if (this.startBeat.isRest) {
|
|
69564
69931
|
return BeamDirection.Up;
|
|
69565
69932
|
}
|
|
69566
69933
|
// invert direction (if stems go up, ties go down to not cross them)
|
|
69567
|
-
switch (
|
|
69934
|
+
switch (this.lookupStartBeatRenderer().getBeatDirection(this.startBeat)) {
|
|
69568
69935
|
case BeamDirection.Up:
|
|
69569
69936
|
return BeamDirection.Down;
|
|
69570
69937
|
default:
|
|
69571
69938
|
return BeamDirection.Up;
|
|
69572
69939
|
}
|
|
69573
69940
|
}
|
|
69574
|
-
|
|
69941
|
+
calculateStartX() {
|
|
69942
|
+
const startBeatRenderer = this.lookupStartBeatRenderer();
|
|
69943
|
+
return startBeatRenderer.x + startBeatRenderer.getBeatX(this.startBeat, BeatXPosition.MiddleNotes);
|
|
69944
|
+
}
|
|
69945
|
+
calculateStartY() {
|
|
69946
|
+
const startBeatRenderer = this.lookupStartBeatRenderer();
|
|
69575
69947
|
if (this.startBeat.isRest) {
|
|
69576
|
-
|
|
69577
|
-
|
|
69948
|
+
switch (this.tieDirection) {
|
|
69949
|
+
case BeamDirection.Up:
|
|
69950
|
+
return (startBeatRenderer.y +
|
|
69951
|
+
startBeatRenderer.getBeatContainer(this.startBeat).onNotes.getBoundingBoxTop());
|
|
69952
|
+
default:
|
|
69953
|
+
return (startBeatRenderer.y +
|
|
69954
|
+
startBeatRenderer.getBeatContainer(this.startBeat).onNotes.getBoundingBoxBottom());
|
|
69955
|
+
}
|
|
69578
69956
|
}
|
|
69579
69957
|
switch (this.tieDirection) {
|
|
69580
69958
|
case BeamDirection.Up:
|
|
69581
69959
|
// below lowest note
|
|
69582
|
-
return
|
|
69960
|
+
return startBeatRenderer.y + startBeatRenderer.getNoteY(this.startBeat.maxNote, NoteYPosition.Top);
|
|
69583
69961
|
default:
|
|
69584
|
-
return
|
|
69962
|
+
return startBeatRenderer.y + startBeatRenderer.getNoteY(this.startBeat.minNote, NoteYPosition.Bottom);
|
|
69585
69963
|
}
|
|
69586
69964
|
}
|
|
69587
|
-
|
|
69588
|
-
const
|
|
69965
|
+
calculateEndX() {
|
|
69966
|
+
const endBeatRenderer = this.lookupEndBeatRenderer();
|
|
69967
|
+
if (!endBeatRenderer) {
|
|
69968
|
+
return this.calculateStartX() + this.renderer.smuflMetrics.leftHandTabTieWidth;
|
|
69969
|
+
}
|
|
69970
|
+
const endBeamDirection = endBeatRenderer.getBeatDirection(this.endBeat);
|
|
69971
|
+
return (endBeatRenderer.x +
|
|
69972
|
+
endBeatRenderer.getBeatX(this.endBeat, this.endBeat.duration > Duration.Whole && endBeamDirection === this.tieDirection
|
|
69973
|
+
? BeatXPosition.Stem
|
|
69974
|
+
: BeatXPosition.MiddleNotes));
|
|
69975
|
+
}
|
|
69976
|
+
caclculateEndY() {
|
|
69977
|
+
const endBeatRenderer = this.lookupEndBeatRenderer();
|
|
69978
|
+
if (!endBeatRenderer) {
|
|
69979
|
+
return this.calculateStartY();
|
|
69980
|
+
}
|
|
69589
69981
|
if (this.endBeat.isRest) {
|
|
69590
69982
|
switch (this.tieDirection) {
|
|
69591
69983
|
case BeamDirection.Up:
|
|
69592
|
-
return
|
|
69984
|
+
return (endBeatRenderer.y + endBeatRenderer.getBeatContainer(this.endBeat).onNotes.getBoundingBoxTop());
|
|
69593
69985
|
default:
|
|
69594
|
-
return
|
|
69986
|
+
return (endBeatRenderer.y +
|
|
69987
|
+
endBeatRenderer.getBeatContainer(this.endBeat).onNotes.getBoundingBoxBottom());
|
|
69595
69988
|
}
|
|
69596
69989
|
}
|
|
69597
|
-
const startBeamDirection = this.
|
|
69598
|
-
const endBeamDirection =
|
|
69990
|
+
const startBeamDirection = this.lookupStartBeatRenderer().getBeatDirection(this.startBeat);
|
|
69991
|
+
const endBeamDirection = endBeatRenderer.getBeatDirection(this.endBeat);
|
|
69599
69992
|
if (startBeamDirection !== endBeamDirection && this.startBeat.graceType === GraceType.None) {
|
|
69600
69993
|
if (endBeamDirection === this.tieDirection) {
|
|
69601
69994
|
switch (this.tieDirection) {
|
|
69602
69995
|
case BeamDirection.Up:
|
|
69603
69996
|
// stem upper end
|
|
69604
|
-
return
|
|
69997
|
+
return (endBeatRenderer.y +
|
|
69998
|
+
endBeatRenderer.getNoteY(this.endBeat.maxNote, NoteYPosition.TopWithStem));
|
|
69605
69999
|
default:
|
|
69606
70000
|
// stem lower end
|
|
69607
|
-
return
|
|
70001
|
+
return (endBeatRenderer.y +
|
|
70002
|
+
endBeatRenderer.getNoteY(this.endBeat.minNote, NoteYPosition.BottomWithStem));
|
|
69608
70003
|
}
|
|
69609
70004
|
}
|
|
69610
70005
|
switch (this.tieDirection) {
|
|
69611
70006
|
case BeamDirection.Up:
|
|
69612
70007
|
// stem upper end
|
|
69613
|
-
return
|
|
70008
|
+
return (endBeatRenderer.y +
|
|
70009
|
+
endBeatRenderer.getNoteY(this.endBeat.maxNote, NoteYPosition.BottomWithStem));
|
|
69614
70010
|
default:
|
|
69615
70011
|
// stem lower end
|
|
69616
|
-
return
|
|
70012
|
+
return (endBeatRenderer.y + endBeatRenderer.getNoteY(this.endBeat.minNote, NoteYPosition.TopWithStem));
|
|
69617
70013
|
}
|
|
69618
70014
|
}
|
|
69619
70015
|
switch (this.tieDirection) {
|
|
69620
70016
|
case BeamDirection.Up:
|
|
69621
70017
|
// below lowest note
|
|
69622
|
-
return
|
|
70018
|
+
return endBeatRenderer.y + endBeatRenderer.getNoteY(this.endBeat.maxNote, NoteYPosition.Top);
|
|
69623
70019
|
default:
|
|
69624
70020
|
// above highest note
|
|
69625
|
-
return
|
|
70021
|
+
return endBeatRenderer.y + endBeatRenderer.getNoteY(this.endBeat.minNote, NoteYPosition.Bottom);
|
|
69626
70022
|
}
|
|
69627
70023
|
}
|
|
69628
|
-
getStartX() {
|
|
69629
|
-
return this.startNoteRenderer.getBeatX(this.startBeat, BeatXPosition.MiddleNotes);
|
|
69630
|
-
}
|
|
69631
|
-
getEndX() {
|
|
69632
|
-
const endBeamDirection = this.endNoteRenderer.getBeatDirection(this.endBeat);
|
|
69633
|
-
return this.endNoteRenderer.getBeatX(this.endBeat, this.endBeat.duration > Duration.Whole && endBeamDirection === this.tieDirection
|
|
69634
|
-
? BeatXPosition.Stem
|
|
69635
|
-
: BeatXPosition.MiddleNotes);
|
|
69636
|
-
}
|
|
69637
70024
|
}
|
|
69638
70025
|
|
|
69639
70026
|
/**
|
|
@@ -69833,142 +70220,106 @@
|
|
|
69833
70220
|
/**
|
|
69834
70221
|
* @internal
|
|
69835
70222
|
*/
|
|
69836
|
-
class
|
|
69837
|
-
|
|
69838
|
-
|
|
69839
|
-
|
|
69840
|
-
|
|
69841
|
-
|
|
69842
|
-
|
|
70223
|
+
class ScoreTieGlyph extends NoteTieGlyph {
|
|
70224
|
+
shouldDrawBendSlur() {
|
|
70225
|
+
return (this.renderer.settings.notation.extendBendArrowsOnTiedNotes &&
|
|
70226
|
+
!!this.startNote.bendOrigin &&
|
|
70227
|
+
this.startNote.isTieOrigin);
|
|
70228
|
+
}
|
|
70229
|
+
calculateStartX() {
|
|
70230
|
+
if (this.isLeftHandTap) {
|
|
70231
|
+
return this.calculateEndX() - this.renderer.smuflMetrics.leftHandTabTieWidth;
|
|
70232
|
+
}
|
|
70233
|
+
return this.renderer.x + this.renderer.getBeatX(this.startNote.beat, BeatXPosition.PostNotes);
|
|
69843
70234
|
}
|
|
70235
|
+
calculateEndX() {
|
|
70236
|
+
const endNoteRenderer = this.lookupEndBeatRenderer();
|
|
70237
|
+
if (!endNoteRenderer) {
|
|
70238
|
+
return this.calculateStartX() + this.renderer.smuflMetrics.leftHandTabTieWidth;
|
|
70239
|
+
}
|
|
70240
|
+
if (this.isLeftHandTap) {
|
|
70241
|
+
return endNoteRenderer.x + endNoteRenderer.getNoteX(this.endNote, NoteXPosition.Left);
|
|
70242
|
+
}
|
|
70243
|
+
return endNoteRenderer.x + endNoteRenderer.getBeatX(this.endNote.beat, BeatXPosition.PreNotes);
|
|
70244
|
+
}
|
|
70245
|
+
}
|
|
70246
|
+
|
|
70247
|
+
/**
|
|
70248
|
+
* @internal
|
|
70249
|
+
*/
|
|
70250
|
+
class ScoreSlurGlyph extends ScoreTieGlyph {
|
|
69844
70251
|
getTieHeight(startX, _startY, endX, _endY) {
|
|
69845
|
-
return Math.log2(endX - startX + 1) * this.renderer.settings.notation.slurHeight / 2;
|
|
70252
|
+
return (Math.log2(endX - startX + 1) * this.renderer.settings.notation.slurHeight) / 2;
|
|
69846
70253
|
}
|
|
69847
|
-
|
|
70254
|
+
calculateStartX() {
|
|
70255
|
+
return (this.renderer.x +
|
|
70256
|
+
(this._isStartCentered()
|
|
70257
|
+
? this.renderer.getBeatX(this.startNote.beat, BeatXPosition.MiddleNotes)
|
|
70258
|
+
: this.renderer.getNoteX(this.startNote, NoteXPosition.Right)));
|
|
70259
|
+
}
|
|
70260
|
+
calculateStartY() {
|
|
69848
70261
|
if (this._isStartCentered()) {
|
|
69849
70262
|
switch (this.tieDirection) {
|
|
69850
70263
|
case BeamDirection.Up:
|
|
69851
|
-
|
|
69852
|
-
return this.startNoteRenderer.getNoteY(this._startNote, NoteYPosition.Top);
|
|
70264
|
+
return this.renderer.y + this.renderer.getNoteY(this.startNote, NoteYPosition.Top);
|
|
69853
70265
|
default:
|
|
69854
|
-
return this.
|
|
70266
|
+
return this.renderer.y + this.renderer.getNoteY(this.startNote, NoteYPosition.Bottom);
|
|
69855
70267
|
}
|
|
69856
70268
|
}
|
|
69857
|
-
return this.
|
|
70269
|
+
return this.renderer.y + this.renderer.getNoteY(this.startNote, NoteYPosition.Center);
|
|
69858
70270
|
}
|
|
69859
|
-
|
|
70271
|
+
calculateEndX() {
|
|
70272
|
+
const endNoteRenderer = this.lookupEndBeatRenderer();
|
|
70273
|
+
if (!endNoteRenderer) {
|
|
70274
|
+
return this.calculateStartX() + this.renderer.smuflMetrics.leftHandTabTieWidth;
|
|
70275
|
+
}
|
|
70276
|
+
if (this._isEndCentered()) {
|
|
70277
|
+
if (this._isEndOnStem()) {
|
|
70278
|
+
return endNoteRenderer.x + endNoteRenderer.getBeatX(this.endNote.beat, BeatXPosition.Stem);
|
|
70279
|
+
}
|
|
70280
|
+
return endNoteRenderer.x + endNoteRenderer.getNoteX(this.endNote, NoteXPosition.Center);
|
|
70281
|
+
}
|
|
70282
|
+
return endNoteRenderer.x + endNoteRenderer.getBeatX(this.endNote.beat, BeatXPosition.PreNotes);
|
|
70283
|
+
}
|
|
70284
|
+
caclculateEndY() {
|
|
70285
|
+
const endNoteRenderer = this.lookupEndBeatRenderer();
|
|
70286
|
+
if (!endNoteRenderer) {
|
|
70287
|
+
return this.calculateStartY();
|
|
70288
|
+
}
|
|
69860
70289
|
if (this._isEndCentered()) {
|
|
69861
70290
|
if (this._isEndOnStem()) {
|
|
69862
70291
|
switch (this.tieDirection) {
|
|
69863
70292
|
case BeamDirection.Up:
|
|
69864
|
-
return
|
|
70293
|
+
return endNoteRenderer.y + endNoteRenderer.getNoteY(this.endNote, NoteYPosition.TopWithStem);
|
|
69865
70294
|
default:
|
|
69866
|
-
return
|
|
70295
|
+
return endNoteRenderer.y + endNoteRenderer.getNoteY(this.endNote, NoteYPosition.BottomWithStem);
|
|
69867
70296
|
}
|
|
69868
70297
|
}
|
|
69869
70298
|
switch (this.tieDirection) {
|
|
69870
70299
|
case BeamDirection.Up:
|
|
69871
|
-
return
|
|
70300
|
+
return endNoteRenderer.y + endNoteRenderer.getNoteY(this.endNote, NoteYPosition.Top);
|
|
69872
70301
|
default:
|
|
69873
|
-
return
|
|
70302
|
+
return endNoteRenderer.y + endNoteRenderer.getNoteY(this.endNote, NoteYPosition.Bottom);
|
|
69874
70303
|
}
|
|
69875
70304
|
}
|
|
69876
|
-
return
|
|
70305
|
+
return endNoteRenderer.y + endNoteRenderer.getNoteY(this.endNote, NoteYPosition.Center);
|
|
69877
70306
|
}
|
|
69878
70307
|
_isStartCentered() {
|
|
69879
|
-
return ((this.
|
|
69880
|
-
(this.
|
|
70308
|
+
return ((this.startNote === this.startNote.beat.maxNote && this.tieDirection === BeamDirection.Up) ||
|
|
70309
|
+
(this.startNote === this.startNote.beat.minNote && this.tieDirection === BeamDirection.Down));
|
|
69881
70310
|
}
|
|
69882
70311
|
_isEndCentered() {
|
|
69883
|
-
return (this.
|
|
69884
|
-
((this.
|
|
69885
|
-
(this.
|
|
70312
|
+
return (this.startNote.beat.graceType === GraceType.None &&
|
|
70313
|
+
((this.endNote === this.endNote.beat.maxNote && this.tieDirection === BeamDirection.Up) ||
|
|
70314
|
+
(this.endNote === this.endNote.beat.minNote && this.tieDirection === BeamDirection.Down)));
|
|
69886
70315
|
}
|
|
69887
70316
|
_isEndOnStem() {
|
|
69888
|
-
const
|
|
69889
|
-
const
|
|
69890
|
-
const endBeamDirection =
|
|
69891
|
-
|
|
69892
|
-
|
|
69893
|
-
|
|
69894
|
-
return this._isStartCentered()
|
|
69895
|
-
? this.startNoteRenderer.getBeatX(this._startNote.beat, BeatXPosition.MiddleNotes)
|
|
69896
|
-
: this.startNoteRenderer.getNoteX(this._startNote, NoteXPosition.Right);
|
|
69897
|
-
}
|
|
69898
|
-
getEndX() {
|
|
69899
|
-
if (this._isEndCentered()) {
|
|
69900
|
-
if (this._isEndOnStem()) {
|
|
69901
|
-
return this.endNoteRenderer.getBeatX(this._endNote.beat, BeatXPosition.Stem);
|
|
69902
|
-
}
|
|
69903
|
-
return this.endNoteRenderer.getNoteX(this._endNote, NoteXPosition.Center);
|
|
69904
|
-
}
|
|
69905
|
-
return this.endNoteRenderer.getBeatX(this._endNote.beat, BeatXPosition.PreNotes);
|
|
69906
|
-
}
|
|
69907
|
-
}
|
|
69908
|
-
|
|
69909
|
-
/**
|
|
69910
|
-
* @internal
|
|
69911
|
-
*/
|
|
69912
|
-
class ScoreTieGlyph extends TieGlyph {
|
|
69913
|
-
startNote;
|
|
69914
|
-
endNote;
|
|
69915
|
-
constructor(startNote, endNote, forEnd = false) {
|
|
69916
|
-
super(!startNote ? null : startNote.beat, !endNote ? null : endNote.beat, forEnd);
|
|
69917
|
-
this.startNote = startNote;
|
|
69918
|
-
this.endNote = endNote;
|
|
69919
|
-
}
|
|
69920
|
-
shouldDrawBendSlur() {
|
|
69921
|
-
return (this.renderer.settings.notation.extendBendArrowsOnTiedNotes &&
|
|
69922
|
-
!!this.startNote.bendOrigin &&
|
|
69923
|
-
this.startNote.isTieOrigin);
|
|
69924
|
-
}
|
|
69925
|
-
doLayout() {
|
|
69926
|
-
super.doLayout();
|
|
69927
|
-
}
|
|
69928
|
-
getBeamDirection(beat, noteRenderer) {
|
|
69929
|
-
// invert direction (if stems go up, ties go down to not cross them)
|
|
69930
|
-
switch (noteRenderer.getBeatDirection(beat)) {
|
|
69931
|
-
case BeamDirection.Up:
|
|
69932
|
-
return BeamDirection.Down;
|
|
69933
|
-
default:
|
|
69934
|
-
return BeamDirection.Up;
|
|
69935
|
-
}
|
|
69936
|
-
}
|
|
69937
|
-
getStartY() {
|
|
69938
|
-
if (this.startBeat.isRest) {
|
|
69939
|
-
// below all lines
|
|
69940
|
-
return this.startNoteRenderer.getScoreY(9);
|
|
69941
|
-
}
|
|
69942
|
-
switch (this.tieDirection) {
|
|
69943
|
-
case BeamDirection.Up:
|
|
69944
|
-
// below lowest note
|
|
69945
|
-
return this.startNoteRenderer.getNoteY(this.startNote, NoteYPosition.Top);
|
|
69946
|
-
default:
|
|
69947
|
-
return this.startNoteRenderer.getNoteY(this.startNote, NoteYPosition.Bottom);
|
|
69948
|
-
}
|
|
69949
|
-
}
|
|
69950
|
-
getEndY() {
|
|
69951
|
-
const endNoteScoreRenderer = this.endNoteRenderer;
|
|
69952
|
-
if (this.endBeat.isRest) {
|
|
69953
|
-
switch (this.tieDirection) {
|
|
69954
|
-
case BeamDirection.Up:
|
|
69955
|
-
return endNoteScoreRenderer.getScoreY(9);
|
|
69956
|
-
default:
|
|
69957
|
-
return endNoteScoreRenderer.getScoreY(0);
|
|
69958
|
-
}
|
|
69959
|
-
}
|
|
69960
|
-
switch (this.tieDirection) {
|
|
69961
|
-
case BeamDirection.Up:
|
|
69962
|
-
return endNoteScoreRenderer.getNoteY(this.endNote, NoteYPosition.Top);
|
|
69963
|
-
default:
|
|
69964
|
-
return endNoteScoreRenderer.getNoteY(this.endNote, NoteYPosition.Bottom);
|
|
69965
|
-
}
|
|
69966
|
-
}
|
|
69967
|
-
getStartX() {
|
|
69968
|
-
return this.startNoteRenderer.getBeatX(this.startNote.beat, BeatXPosition.PostNotes);
|
|
69969
|
-
}
|
|
69970
|
-
getEndX() {
|
|
69971
|
-
return this.endNoteRenderer.getBeatX(this.endNote.beat, BeatXPosition.PreNotes);
|
|
70317
|
+
const startBeamDirection = this.lookupStartBeatRenderer().getBeatDirection(this.startNote.beat);
|
|
70318
|
+
const endBeatRenderer = this.lookupEndBeatRenderer();
|
|
70319
|
+
const endBeamDirection = endBeatRenderer
|
|
70320
|
+
? endBeatRenderer.getBeatDirection(this.endNote.beat)
|
|
70321
|
+
: startBeamDirection;
|
|
70322
|
+
return startBeamDirection !== endBeamDirection && this.startNote.beat.graceType === GraceType.None;
|
|
69972
70323
|
}
|
|
69973
70324
|
}
|
|
69974
70325
|
|
|
@@ -70018,12 +70369,11 @@
|
|
|
70018
70369
|
n.beat.graceType !== GraceType.BendGrace &&
|
|
70019
70370
|
n.tieDestination &&
|
|
70020
70371
|
n.tieDestination.isVisible) {
|
|
70021
|
-
|
|
70022
|
-
const tie = new ScoreTieGlyph(n, n.tieDestination, false);
|
|
70372
|
+
const tie = new ScoreTieGlyph(`score.tie.${n.id}`, n, n.tieDestination, false);
|
|
70023
70373
|
this.addTie(tie);
|
|
70024
70374
|
}
|
|
70025
70375
|
if (n.isTieDestination && !n.tieOrigin.hasBend && !n.beat.hasWhammyBar) {
|
|
70026
|
-
const tie = new ScoreTieGlyph(n.tieOrigin, n, true);
|
|
70376
|
+
const tie = new ScoreTieGlyph(`score.tie.${n.tieOrigin.id}`, n.tieOrigin, n, true);
|
|
70027
70377
|
this.addTie(tie);
|
|
70028
70378
|
}
|
|
70029
70379
|
// TODO: depending on the type we have other positioning
|
|
@@ -70033,17 +70383,16 @@
|
|
|
70033
70383
|
this.addTie(l);
|
|
70034
70384
|
}
|
|
70035
70385
|
if (n.isSlurOrigin && n.slurDestination && n.slurDestination.isVisible) {
|
|
70036
|
-
|
|
70037
|
-
const tie = new ScoreSlurGlyph(n, n.slurDestination, false);
|
|
70386
|
+
const tie = new ScoreSlurGlyph(`score.slur.${n.id}`, n, n.slurDestination, false);
|
|
70038
70387
|
this.addTie(tie);
|
|
70039
70388
|
}
|
|
70040
70389
|
if (n.isSlurDestination) {
|
|
70041
|
-
const tie = new ScoreSlurGlyph(n.slurOrigin, n, true);
|
|
70390
|
+
const tie = new ScoreSlurGlyph(`score.slur.${n.slurOrigin.id}`, n.slurOrigin, n, true);
|
|
70042
70391
|
this.addTie(tie);
|
|
70043
70392
|
}
|
|
70044
70393
|
// start effect slur on first beat
|
|
70045
70394
|
if (!this._effectSlur && n.isEffectSlurOrigin && n.effectSlurDestination) {
|
|
70046
|
-
const effectSlur = new ScoreSlurGlyph(n, n.effectSlurDestination, false);
|
|
70395
|
+
const effectSlur = new ScoreSlurGlyph(`score.slur.effect.${n.beat.id}`, n, n.effectSlurDestination, false);
|
|
70047
70396
|
this._effectSlur = effectSlur;
|
|
70048
70397
|
this.addTie(effectSlur);
|
|
70049
70398
|
}
|
|
@@ -70052,7 +70401,7 @@
|
|
|
70052
70401
|
const direction = this.onNotes.beamingHelper.direction;
|
|
70053
70402
|
const startNote = direction === BeamDirection.Up ? n.beat.effectSlurOrigin.minNote : n.beat.effectSlurOrigin.maxNote;
|
|
70054
70403
|
const endNote = direction === BeamDirection.Up ? n.beat.minNote : n.beat.maxNote;
|
|
70055
|
-
const effectEndSlur = new ScoreSlurGlyph(startNote, endNote, true);
|
|
70404
|
+
const effectEndSlur = new ScoreSlurGlyph(`score.slur.effect.${startNote.beat.id}`, startNote, endNote, true);
|
|
70056
70405
|
this._effectEndSlur = effectEndSlur;
|
|
70057
70406
|
this.addTie(effectEndSlur);
|
|
70058
70407
|
}
|
|
@@ -70074,7 +70423,7 @@
|
|
|
70074
70423
|
while (destination.nextBeat && destination.nextBeat.isLegatoDestination) {
|
|
70075
70424
|
destination = destination.nextBeat;
|
|
70076
70425
|
}
|
|
70077
|
-
this.addTie(new ScoreLegatoGlyph(this.beat, destination, false));
|
|
70426
|
+
this.addTie(new ScoreLegatoGlyph(`score.legato.${this.beat.id}`, this.beat, destination, false));
|
|
70078
70427
|
}
|
|
70079
70428
|
}
|
|
70080
70429
|
else if (this.beat.isLegatoDestination) {
|
|
@@ -70084,7 +70433,7 @@
|
|
|
70084
70433
|
while (origin.previousBeat && origin.previousBeat.isLegatoOrigin) {
|
|
70085
70434
|
origin = origin.previousBeat;
|
|
70086
70435
|
}
|
|
70087
|
-
this.addTie(new ScoreLegatoGlyph(origin, this.beat, true));
|
|
70436
|
+
this.addTie(new ScoreLegatoGlyph(`score.legato.${origin.id}`, origin, this.beat, true));
|
|
70088
70437
|
}
|
|
70089
70438
|
}
|
|
70090
70439
|
}
|
|
@@ -70464,6 +70813,9 @@
|
|
|
70464
70813
|
this.addBeatGlyph(container);
|
|
70465
70814
|
}
|
|
70466
70815
|
}
|
|
70816
|
+
getNoteLine(note) {
|
|
70817
|
+
return this.accidentalHelper.getNoteSteps(note) / 2;
|
|
70818
|
+
}
|
|
70467
70819
|
getNoteSteps(n) {
|
|
70468
70820
|
return this.accidentalHelper.getNoteSteps(n);
|
|
70469
70821
|
}
|
|
@@ -70520,43 +70872,15 @@
|
|
|
70520
70872
|
/**
|
|
70521
70873
|
* @internal
|
|
70522
70874
|
*/
|
|
70523
|
-
class SlashTieGlyph extends
|
|
70524
|
-
|
|
70525
|
-
endNote;
|
|
70526
|
-
constructor(startNote, endNote, forEnd = false) {
|
|
70527
|
-
super(startNote.beat, endNote.beat, forEnd);
|
|
70528
|
-
this.startNote = startNote;
|
|
70529
|
-
this.endNote = endNote;
|
|
70530
|
-
}
|
|
70531
|
-
get _isLeftHandTap() {
|
|
70532
|
-
return this.startNote === this.endNote;
|
|
70533
|
-
}
|
|
70534
|
-
getTieHeight(startX, startY, endX, endY) {
|
|
70535
|
-
if (this._isLeftHandTap) {
|
|
70536
|
-
return this.startNoteRenderer.smuflMetrics.tieHeight;
|
|
70537
|
-
}
|
|
70538
|
-
return super.getTieHeight(startX, startY, endX, endY);
|
|
70539
|
-
}
|
|
70540
|
-
getBeamDirection(_beat, _noteRenderer) {
|
|
70541
|
-
return BeamDirection.Down;
|
|
70542
|
-
}
|
|
70543
|
-
static getBeamDirectionForNote(_note) {
|
|
70875
|
+
class SlashTieGlyph extends NoteTieGlyph {
|
|
70876
|
+
calculateTieDirection() {
|
|
70544
70877
|
return BeamDirection.Down;
|
|
70545
70878
|
}
|
|
70546
|
-
|
|
70547
|
-
return
|
|
70879
|
+
getStartNotePosition() {
|
|
70880
|
+
return NoteXPosition.Right;
|
|
70548
70881
|
}
|
|
70549
|
-
|
|
70550
|
-
return
|
|
70551
|
-
}
|
|
70552
|
-
getStartX() {
|
|
70553
|
-
if (this._isLeftHandTap) {
|
|
70554
|
-
return this.getEndX() - this.renderer.smuflMetrics.leftHandTabTieWidth;
|
|
70555
|
-
}
|
|
70556
|
-
return this.startNoteRenderer.getNoteX(this.startNote, NoteXPosition.Right);
|
|
70557
|
-
}
|
|
70558
|
-
getEndX() {
|
|
70559
|
-
return this.endNoteRenderer.getNoteX(this.endNote, NoteXPosition.Left);
|
|
70882
|
+
getEndNotePosition() {
|
|
70883
|
+
return NoteXPosition.Left;
|
|
70560
70884
|
}
|
|
70561
70885
|
}
|
|
70562
70886
|
|
|
@@ -70571,12 +70895,12 @@
|
|
|
70571
70895
|
return;
|
|
70572
70896
|
}
|
|
70573
70897
|
if (!this._tiedNoteTie && n.isTieOrigin && n.tieDestination.isVisible) {
|
|
70574
|
-
const tie = new SlashTieGlyph(n, n.tieDestination, false);
|
|
70898
|
+
const tie = new SlashTieGlyph('slash.tie', n, n.tieDestination, false);
|
|
70575
70899
|
this._tiedNoteTie = tie;
|
|
70576
70900
|
this.addTie(tie);
|
|
70577
70901
|
}
|
|
70578
70902
|
if (!this._tiedNoteTie && n.isTieDestination) {
|
|
70579
|
-
const tie = new SlashTieGlyph(n.tieOrigin, n, true);
|
|
70903
|
+
const tie = new SlashTieGlyph('slash.tie', n.tieOrigin, n, true);
|
|
70580
70904
|
this._tiedNoteTie = tie;
|
|
70581
70905
|
this.addTie(tie);
|
|
70582
70906
|
}
|
|
@@ -70703,8 +71027,7 @@
|
|
|
70703
71027
|
doLayout() {
|
|
70704
71028
|
// create glyphs
|
|
70705
71029
|
const sr = this.renderer;
|
|
70706
|
-
const
|
|
70707
|
-
const glyphY = sr.getLineY(line);
|
|
71030
|
+
const glyphY = sr.getLineY(0);
|
|
70708
71031
|
if (this.container.beat.deadSlapped) {
|
|
70709
71032
|
const deadSlapped = new DeadSlappedBeatGlyph();
|
|
70710
71033
|
deadSlapped.renderer = this.renderer;
|
|
@@ -70737,7 +71060,7 @@
|
|
|
70737
71060
|
//
|
|
70738
71061
|
if (this.container.beat.dots > 0) {
|
|
70739
71062
|
for (let i = 0; i < this.container.beat.dots; i++) {
|
|
70740
|
-
this.addEffect(new AugmentationDotGlyph(0,
|
|
71063
|
+
this.addEffect(new AugmentationDotGlyph(0, glyphY - sr.getLineHeight(0.5)));
|
|
70741
71064
|
}
|
|
70742
71065
|
}
|
|
70743
71066
|
super.doLayout();
|
|
@@ -70819,7 +71142,7 @@
|
|
|
70819
71142
|
this.registerOverflowTop(this.tupletSize);
|
|
70820
71143
|
}
|
|
70821
71144
|
}
|
|
70822
|
-
getNoteLine() {
|
|
71145
|
+
getNoteLine(_note) {
|
|
70823
71146
|
return 0;
|
|
70824
71147
|
}
|
|
70825
71148
|
getFlagTopY(beat, _direction) {
|
|
@@ -71156,77 +71479,6 @@
|
|
|
71156
71479
|
}
|
|
71157
71480
|
}
|
|
71158
71481
|
|
|
71159
|
-
/**
|
|
71160
|
-
* @internal
|
|
71161
|
-
*/
|
|
71162
|
-
class TabSlurGlyph extends TabTieGlyph {
|
|
71163
|
-
_direction;
|
|
71164
|
-
_forSlide;
|
|
71165
|
-
constructor(startNote, endNote, forSlide, forEnd = false) {
|
|
71166
|
-
super(startNote, endNote, forEnd);
|
|
71167
|
-
this._direction = TabTieGlyph.getBeamDirectionForNote(startNote);
|
|
71168
|
-
this._forSlide = forSlide;
|
|
71169
|
-
}
|
|
71170
|
-
getTieHeight(startX, _startY, endX, _endY) {
|
|
71171
|
-
return Math.log(endX - startX + 1) * this.renderer.settings.notation.slurHeight / 2;
|
|
71172
|
-
}
|
|
71173
|
-
tryExpand(startNote, endNote, forSlide, forEnd) {
|
|
71174
|
-
// same type required
|
|
71175
|
-
if (this._forSlide !== forSlide) {
|
|
71176
|
-
return false;
|
|
71177
|
-
}
|
|
71178
|
-
if (this.forEnd !== forEnd) {
|
|
71179
|
-
return false;
|
|
71180
|
-
}
|
|
71181
|
-
// same start and endbeat
|
|
71182
|
-
if (this.startNote.beat.id !== startNote.beat.id) {
|
|
71183
|
-
return false;
|
|
71184
|
-
}
|
|
71185
|
-
if (this.endNote.beat.id !== endNote.beat.id) {
|
|
71186
|
-
return false;
|
|
71187
|
-
}
|
|
71188
|
-
// same draw direction
|
|
71189
|
-
if (this._direction !== TabTieGlyph.getBeamDirectionForNote(startNote)) {
|
|
71190
|
-
return false;
|
|
71191
|
-
}
|
|
71192
|
-
// if we can expand, expand in correct direction
|
|
71193
|
-
switch (this._direction) {
|
|
71194
|
-
case BeamDirection.Up:
|
|
71195
|
-
if (startNote.realValue > this.startNote.realValue) {
|
|
71196
|
-
this.startNote = startNote;
|
|
71197
|
-
this.startBeat = startNote.beat;
|
|
71198
|
-
}
|
|
71199
|
-
if (endNote.realValue > this.endNote.realValue) {
|
|
71200
|
-
this.endNote = endNote;
|
|
71201
|
-
this.endBeat = endNote.beat;
|
|
71202
|
-
}
|
|
71203
|
-
break;
|
|
71204
|
-
case BeamDirection.Down:
|
|
71205
|
-
if (startNote.realValue < this.startNote.realValue) {
|
|
71206
|
-
this.startNote = startNote;
|
|
71207
|
-
this.startBeat = startNote.beat;
|
|
71208
|
-
}
|
|
71209
|
-
if (endNote.realValue < this.endNote.realValue) {
|
|
71210
|
-
this.endNote = endNote;
|
|
71211
|
-
this.endBeat = endNote.beat;
|
|
71212
|
-
}
|
|
71213
|
-
break;
|
|
71214
|
-
}
|
|
71215
|
-
return true;
|
|
71216
|
-
}
|
|
71217
|
-
paint(cx, cy, canvas) {
|
|
71218
|
-
const startNoteRenderer = this.renderer.scoreRenderer.layout.getRendererForBar(this.renderer.staff.staffId, this.startBeat.voice.bar);
|
|
71219
|
-
const direction = this.getBeamDirection(this.startBeat, startNoteRenderer);
|
|
71220
|
-
const slurId = `tab.slur.${this.startNote.beat.id}.${this.endNote.beat.id}.${direction}`;
|
|
71221
|
-
const renderer = this.renderer;
|
|
71222
|
-
const isSlurRendered = renderer.staff.getSharedLayoutData(slurId, false);
|
|
71223
|
-
if (!isSlurRendered) {
|
|
71224
|
-
renderer.staff.setSharedLayoutData(slurId, true);
|
|
71225
|
-
super.paint(cx, cy, canvas);
|
|
71226
|
-
}
|
|
71227
|
-
}
|
|
71228
|
-
}
|
|
71229
|
-
|
|
71230
71482
|
/**
|
|
71231
71483
|
* @internal
|
|
71232
71484
|
*/
|
|
@@ -71251,15 +71503,15 @@
|
|
|
71251
71503
|
}
|
|
71252
71504
|
const renderer = this.renderer;
|
|
71253
71505
|
if (n.isTieOrigin && renderer.showTiedNotes && n.tieDestination.isVisible) {
|
|
71254
|
-
const tie = new TabTieGlyph(n, n.tieDestination, false);
|
|
71506
|
+
const tie = new TabTieGlyph(`tab.tie.${n.id}`, n, n.tieDestination, false);
|
|
71255
71507
|
this.addTie(tie);
|
|
71256
71508
|
}
|
|
71257
71509
|
if (n.isTieDestination && renderer.showTiedNotes) {
|
|
71258
|
-
const tie = new TabTieGlyph(n.tieOrigin, n, true);
|
|
71510
|
+
const tie = new TabTieGlyph(`tab.tie.${n.tieOrigin.id}`, n.tieOrigin, n, true);
|
|
71259
71511
|
this.addTie(tie);
|
|
71260
71512
|
}
|
|
71261
71513
|
if (n.isLeftHandTapped && !n.isHammerPullDestination) {
|
|
71262
|
-
const tapSlur = new TabTieGlyph(n, n, false);
|
|
71514
|
+
const tapSlur = new TabTieGlyph(`tab.tie.leftHandTap.${n.id}`, n, n, false);
|
|
71263
71515
|
this.addTie(tapSlur);
|
|
71264
71516
|
}
|
|
71265
71517
|
// start effect slur on first beat
|
|
@@ -71272,7 +71524,7 @@
|
|
|
71272
71524
|
}
|
|
71273
71525
|
}
|
|
71274
71526
|
if (!expanded) {
|
|
71275
|
-
const effectSlur = new TabSlurGlyph(n, n.effectSlurDestination, false, false);
|
|
71527
|
+
const effectSlur = new TabSlurGlyph(`tab.slur.effect.${n.id}`, n, n.effectSlurDestination, false, false);
|
|
71276
71528
|
this._effectSlurs.push(effectSlur);
|
|
71277
71529
|
this.addTie(effectSlur);
|
|
71278
71530
|
}
|
|
@@ -71287,7 +71539,7 @@
|
|
|
71287
71539
|
}
|
|
71288
71540
|
}
|
|
71289
71541
|
if (!expanded) {
|
|
71290
|
-
const effectSlur = new TabSlurGlyph(n.effectSlurOrigin, n, false, true);
|
|
71542
|
+
const effectSlur = new TabSlurGlyph(`tab.slur.effect.${n.effectSlurOrigin.id}`, n.effectSlurOrigin, n, false, true);
|
|
71291
71543
|
this._effectSlurs.push(effectSlur);
|
|
71292
71544
|
this.addTie(effectSlur);
|
|
71293
71545
|
}
|
|
@@ -71706,7 +71958,7 @@
|
|
|
71706
71958
|
}
|
|
71707
71959
|
else {
|
|
71708
71960
|
const line = Math.floor((this.renderer.bar.staff.tuning.length - 1) / 2);
|
|
71709
|
-
const y = tabRenderer.
|
|
71961
|
+
const y = tabRenderer.getLineY(line);
|
|
71710
71962
|
const restGlyph = new TabRestGlyph(0, y, tabRenderer.showRests, this.container.beat.duration);
|
|
71711
71963
|
this.restGlyph = restGlyph;
|
|
71712
71964
|
restGlyph.beat = this.container.beat;
|
|
@@ -71765,8 +72017,8 @@
|
|
|
71765
72017
|
_createNoteGlyph(n) {
|
|
71766
72018
|
const tr = this.renderer;
|
|
71767
72019
|
const noteNumberGlyph = new NoteNumberGlyph(0, 0, n);
|
|
71768
|
-
const l =
|
|
71769
|
-
noteNumberGlyph.y = tr.
|
|
72020
|
+
const l = tr.getNoteLine(n);
|
|
72021
|
+
noteNumberGlyph.y = tr.getLineY(l);
|
|
71770
72022
|
noteNumberGlyph.renderer = this.renderer;
|
|
71771
72023
|
noteNumberGlyph.doLayout();
|
|
71772
72024
|
this.noteNumbers.addNoteGlyph(noteNumberGlyph, n);
|
|
@@ -71957,17 +72209,8 @@
|
|
|
71957
72209
|
}
|
|
71958
72210
|
return mode;
|
|
71959
72211
|
}
|
|
71960
|
-
|
|
71961
|
-
|
|
71962
|
-
* @param line the line of the particular string where 0 is the most top line
|
|
71963
|
-
* @param correction
|
|
71964
|
-
* @returns
|
|
71965
|
-
*/
|
|
71966
|
-
getTabY(line) {
|
|
71967
|
-
return super.getLineY(line);
|
|
71968
|
-
}
|
|
71969
|
-
getTabHeight(line) {
|
|
71970
|
-
return super.getLineHeight(line);
|
|
72212
|
+
getNoteLine(note) {
|
|
72213
|
+
return this.bar.staff.tuning.length - note.string;
|
|
71971
72214
|
}
|
|
71972
72215
|
minString = Number.NaN;
|
|
71973
72216
|
maxString = Number.NaN;
|
|
@@ -72056,7 +72299,7 @@
|
|
|
72056
72299
|
if (this.isFirstOfLine) {
|
|
72057
72300
|
const center = (this.bar.staff.tuning.length - 1) / 2;
|
|
72058
72301
|
this.createStartSpacing();
|
|
72059
|
-
this.addPreBeatGlyph(new TabClefGlyph(0, this.
|
|
72302
|
+
this.addPreBeatGlyph(new TabClefGlyph(0, this.getLineY(center)));
|
|
72060
72303
|
}
|
|
72061
72304
|
// Time Signature
|
|
72062
72305
|
if (this.showTimeSignature &&
|
|
@@ -72077,7 +72320,7 @@
|
|
|
72077
72320
|
_createTimeSignatureGlyphs() {
|
|
72078
72321
|
this.addPreBeatGlyph(new SpacingGlyph(0, 0, this.smuflMetrics.oneStaffSpace));
|
|
72079
72322
|
const lines = (this.bar.staff.tuning.length + 1) / 2 - 1;
|
|
72080
|
-
this.addPreBeatGlyph(new TabTimeSignatureGlyph(0, this.
|
|
72323
|
+
this.addPreBeatGlyph(new TabTimeSignatureGlyph(0, this.getLineY(lines), this.bar.masterBar.timeSignatureNumerator, this.bar.masterBar.timeSignatureDenominator, this.bar.masterBar.timeSignatureCommon, this.bar.masterBar.isFreeTime));
|
|
72081
72324
|
}
|
|
72082
72325
|
createVoiceGlyphs(v) {
|
|
72083
72326
|
super.createVoiceGlyphs(v);
|