@coderline/alphatab 1.8.0-alpha.1646 → 1.8.0-alpha.1647
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 +2117 -1797
- package/dist/alphaTab.d.ts +7 -3
- package/dist/alphaTab.js +2117 -1797
- 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 +1 -1
package/dist/alphaTab.core.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* alphaTab v1.8.0-alpha.
|
|
2
|
+
* alphaTab v1.8.0-alpha.1647 (develop, build 1647)
|
|
3
3
|
*
|
|
4
4
|
* Copyright © 2025, Daniel Kuschny and Contributors, All rights reserved.
|
|
5
5
|
*
|
|
@@ -203,9 +203,9 @@ class AlphaTabError extends Error {
|
|
|
203
203
|
* @internal
|
|
204
204
|
*/
|
|
205
205
|
class VersionInfo {
|
|
206
|
-
static version = '1.8.0-alpha.
|
|
207
|
-
static date = '2025-12-
|
|
208
|
-
static commit = '
|
|
206
|
+
static version = '1.8.0-alpha.1647';
|
|
207
|
+
static date = '2025-12-17T02:10:13.730Z';
|
|
208
|
+
static commit = 'a1bd11d4a3eef22409f1f49a5dd172ace16108cc';
|
|
209
209
|
static print(print) {
|
|
210
210
|
print(`alphaTab ${VersionInfo.version}`);
|
|
211
211
|
print(`commit: ${VersionInfo.commit}`);
|
|
@@ -1311,6 +1311,10 @@ var NotationElement;
|
|
|
1311
1311
|
* The whammy bar line effect shown above the tab staff
|
|
1312
1312
|
*/
|
|
1313
1313
|
NotationElement[NotationElement["EffectWhammyBarLine"] = 50] = "EffectWhammyBarLine";
|
|
1314
|
+
/**
|
|
1315
|
+
* The key signature for numbered notation staff.
|
|
1316
|
+
*/
|
|
1317
|
+
NotationElement[NotationElement["EffectNumberedNotationKeySignature"] = 51] = "EffectNumberedNotationKeySignature";
|
|
1314
1318
|
})(NotationElement || (NotationElement = {}));
|
|
1315
1319
|
/**
|
|
1316
1320
|
* The notation settings control how various music notation elements are shown and behaving
|
|
@@ -39715,7 +39719,7 @@ class EngravingSettings {
|
|
|
39715
39719
|
//
|
|
39716
39720
|
// custom alphatab sizes
|
|
39717
39721
|
this.numberedBarRendererBarSize = this.staffLineThickness * 2;
|
|
39718
|
-
this.numberedBarRendererBarSpacing = this.beamSpacing
|
|
39722
|
+
this.numberedBarRendererBarSpacing = this.beamSpacing;
|
|
39719
39723
|
this.preNoteEffectPadding = 0.4 * this.oneStaffSpace;
|
|
39720
39724
|
this.postNoteEffectPadding = 0.2 * this.oneStaffSpace;
|
|
39721
39725
|
this.lineRangedGlyphDashGap = 0.5 * this.oneStaffSpace;
|
|
@@ -39784,7 +39788,7 @@ class EngravingSettings {
|
|
|
39784
39788
|
*/
|
|
39785
39789
|
numberedBarRendererBarSpacing = 0;
|
|
39786
39790
|
/**
|
|
39787
|
-
* The
|
|
39791
|
+
* The padding minimum between the duration dashes.
|
|
39788
39792
|
*/
|
|
39789
39793
|
numberedDashGlyphPadding = 0;
|
|
39790
39794
|
/**
|
|
@@ -48565,10 +48569,13 @@ class BeatContainerGlyphBase extends Glyph {
|
|
|
48565
48569
|
*/
|
|
48566
48570
|
class BeatContainerGlyph extends BeatContainerGlyphBase {
|
|
48567
48571
|
_ties = [];
|
|
48572
|
+
_tieWidth = 0;
|
|
48568
48573
|
beat;
|
|
48569
48574
|
preNotes;
|
|
48570
48575
|
onNotes;
|
|
48571
|
-
|
|
48576
|
+
get beatId() {
|
|
48577
|
+
return this.beat.id;
|
|
48578
|
+
}
|
|
48572
48579
|
get isLastOfVoice() {
|
|
48573
48580
|
return this.beat.isLastOfVoice;
|
|
48574
48581
|
}
|
|
@@ -48629,7 +48636,7 @@ class BeatContainerGlyph extends BeatContainerGlyphBase {
|
|
|
48629
48636
|
return helper.hasFlag(false, undefined);
|
|
48630
48637
|
}
|
|
48631
48638
|
get postBeatStretch() {
|
|
48632
|
-
return this.onNotes.computedWidth - this.onNotes.onTimeX;
|
|
48639
|
+
return (this.onNotes.computedWidth + this._tieWidth) - this.onNotes.onTimeX;
|
|
48633
48640
|
}
|
|
48634
48641
|
registerLayoutingInfo(layoutings) {
|
|
48635
48642
|
const preBeatStretch = this.preNotes.computedWidth + this.onNotes.onTimeX;
|
|
@@ -48659,16 +48666,19 @@ class BeatContainerGlyph extends BeatContainerGlyphBase {
|
|
|
48659
48666
|
this.onNotes.renderer = this.renderer;
|
|
48660
48667
|
this.onNotes.container = this;
|
|
48661
48668
|
this.onNotes.doLayout();
|
|
48669
|
+
this.createBeatTies();
|
|
48670
|
+
this.updateWidth();
|
|
48671
|
+
}
|
|
48672
|
+
createBeatTies() {
|
|
48662
48673
|
let i = this.beat.notes.length - 1;
|
|
48663
48674
|
while (i >= 0) {
|
|
48664
48675
|
this.createTies(this.beat.notes[i--]);
|
|
48665
48676
|
}
|
|
48666
|
-
this.updateWidth();
|
|
48667
48677
|
}
|
|
48668
48678
|
doMultiVoiceLayout() {
|
|
48669
48679
|
}
|
|
48670
48680
|
updateWidth() {
|
|
48671
|
-
|
|
48681
|
+
let width = this.preNotes.width + this.onNotes.width;
|
|
48672
48682
|
let tieWidth = 0;
|
|
48673
48683
|
for (const tie of this._ties) {
|
|
48674
48684
|
const tg = tie;
|
|
@@ -48676,8 +48686,9 @@ class BeatContainerGlyph extends BeatContainerGlyphBase {
|
|
|
48676
48686
|
tieWidth = tg.width;
|
|
48677
48687
|
}
|
|
48678
48688
|
}
|
|
48679
|
-
this.
|
|
48680
|
-
|
|
48689
|
+
this._tieWidth = tieWidth;
|
|
48690
|
+
width += tieWidth;
|
|
48691
|
+
this.width = width;
|
|
48681
48692
|
}
|
|
48682
48693
|
createTies(_n) {
|
|
48683
48694
|
}
|
|
@@ -58583,6 +58594,244 @@ class NoteOrnamentEffectInfo extends EffectInfo {
|
|
|
58583
58594
|
}
|
|
58584
58595
|
}
|
|
58585
58596
|
|
|
58597
|
+
/**
|
|
58598
|
+
* @internal
|
|
58599
|
+
*/
|
|
58600
|
+
class AccidentalGlyph extends MusicFontGlyph {
|
|
58601
|
+
constructor(x, y, accidentalType, scale) {
|
|
58602
|
+
super(x, y, scale, AccidentalGlyph.getMusicSymbol(accidentalType));
|
|
58603
|
+
}
|
|
58604
|
+
static getMusicSymbol(accidentalType) {
|
|
58605
|
+
switch (accidentalType) {
|
|
58606
|
+
case AccidentalType.Natural:
|
|
58607
|
+
return MusicFontSymbol.AccidentalNatural;
|
|
58608
|
+
case AccidentalType.Sharp:
|
|
58609
|
+
return MusicFontSymbol.AccidentalSharp;
|
|
58610
|
+
case AccidentalType.Flat:
|
|
58611
|
+
return MusicFontSymbol.AccidentalFlat;
|
|
58612
|
+
case AccidentalType.NaturalQuarterNoteUp:
|
|
58613
|
+
return MusicFontSymbol.AccidentalQuarterToneSharpNaturalArrowUp;
|
|
58614
|
+
case AccidentalType.SharpQuarterNoteUp:
|
|
58615
|
+
return MusicFontSymbol.AccidentalThreeQuarterTonesSharpArrowUp;
|
|
58616
|
+
case AccidentalType.FlatQuarterNoteUp:
|
|
58617
|
+
return MusicFontSymbol.AccidentalQuarterToneFlatArrowUp;
|
|
58618
|
+
case AccidentalType.DoubleSharp:
|
|
58619
|
+
return MusicFontSymbol.AccidentalDoubleSharp;
|
|
58620
|
+
case AccidentalType.DoubleFlat:
|
|
58621
|
+
return MusicFontSymbol.AccidentalDoubleFlat;
|
|
58622
|
+
}
|
|
58623
|
+
return MusicFontSymbol.None;
|
|
58624
|
+
}
|
|
58625
|
+
}
|
|
58626
|
+
|
|
58627
|
+
/**
|
|
58628
|
+
* @internal
|
|
58629
|
+
*/
|
|
58630
|
+
class NumberedKeySignatureGlyph extends EffectGlyph {
|
|
58631
|
+
_keySignature;
|
|
58632
|
+
_keySignatureType;
|
|
58633
|
+
_text = '';
|
|
58634
|
+
_accidental = AccidentalType.None;
|
|
58635
|
+
_accidentalOffset = 0;
|
|
58636
|
+
_padding = 0;
|
|
58637
|
+
constructor(x, y, keySignature, keySignatureType) {
|
|
58638
|
+
super(x, y);
|
|
58639
|
+
this._keySignature = keySignature;
|
|
58640
|
+
this._keySignatureType = keySignatureType;
|
|
58641
|
+
}
|
|
58642
|
+
doLayout() {
|
|
58643
|
+
super.doLayout();
|
|
58644
|
+
const text = '1 = ';
|
|
58645
|
+
let text2 = '';
|
|
58646
|
+
let accidental = AccidentalType.None;
|
|
58647
|
+
switch (this._keySignatureType) {
|
|
58648
|
+
case KeySignatureType.Major:
|
|
58649
|
+
switch (this._keySignature) {
|
|
58650
|
+
case KeySignature.Cb:
|
|
58651
|
+
text2 = ' C';
|
|
58652
|
+
accidental = AccidentalType.Flat;
|
|
58653
|
+
break;
|
|
58654
|
+
case KeySignature.Gb:
|
|
58655
|
+
text2 = ' G';
|
|
58656
|
+
accidental = AccidentalType.Flat;
|
|
58657
|
+
break;
|
|
58658
|
+
case KeySignature.Db:
|
|
58659
|
+
text2 = ' D';
|
|
58660
|
+
accidental = AccidentalType.Flat;
|
|
58661
|
+
break;
|
|
58662
|
+
case KeySignature.Ab:
|
|
58663
|
+
text2 = ' A';
|
|
58664
|
+
accidental = AccidentalType.Flat;
|
|
58665
|
+
break;
|
|
58666
|
+
case KeySignature.Eb:
|
|
58667
|
+
text2 = ' E';
|
|
58668
|
+
accidental = AccidentalType.Flat;
|
|
58669
|
+
break;
|
|
58670
|
+
case KeySignature.Bb:
|
|
58671
|
+
text2 = ' B';
|
|
58672
|
+
accidental = AccidentalType.Flat;
|
|
58673
|
+
break;
|
|
58674
|
+
case KeySignature.F:
|
|
58675
|
+
text2 = 'F';
|
|
58676
|
+
break;
|
|
58677
|
+
case KeySignature.C:
|
|
58678
|
+
text2 = 'C';
|
|
58679
|
+
accidental = AccidentalType.None;
|
|
58680
|
+
break;
|
|
58681
|
+
case KeySignature.G:
|
|
58682
|
+
text2 = 'G';
|
|
58683
|
+
accidental = AccidentalType.None;
|
|
58684
|
+
break;
|
|
58685
|
+
case KeySignature.D:
|
|
58686
|
+
text2 = 'D';
|
|
58687
|
+
accidental = AccidentalType.None;
|
|
58688
|
+
break;
|
|
58689
|
+
case KeySignature.A:
|
|
58690
|
+
text2 = 'A';
|
|
58691
|
+
accidental = AccidentalType.None;
|
|
58692
|
+
break;
|
|
58693
|
+
case KeySignature.E:
|
|
58694
|
+
text2 = 'E';
|
|
58695
|
+
accidental = AccidentalType.None;
|
|
58696
|
+
break;
|
|
58697
|
+
case KeySignature.B:
|
|
58698
|
+
text2 = 'B';
|
|
58699
|
+
accidental = AccidentalType.None;
|
|
58700
|
+
break;
|
|
58701
|
+
case KeySignature.FSharp:
|
|
58702
|
+
text2 = ' F';
|
|
58703
|
+
accidental = AccidentalType.Sharp;
|
|
58704
|
+
break;
|
|
58705
|
+
case KeySignature.CSharp:
|
|
58706
|
+
text2 = ' C';
|
|
58707
|
+
accidental = AccidentalType.Sharp;
|
|
58708
|
+
break;
|
|
58709
|
+
}
|
|
58710
|
+
break;
|
|
58711
|
+
case KeySignatureType.Minor:
|
|
58712
|
+
switch (this._keySignature) {
|
|
58713
|
+
case KeySignature.Cb:
|
|
58714
|
+
text2 = ' a';
|
|
58715
|
+
accidental = AccidentalType.Flat;
|
|
58716
|
+
break;
|
|
58717
|
+
case KeySignature.Gb:
|
|
58718
|
+
text2 = ' e';
|
|
58719
|
+
accidental = AccidentalType.Flat;
|
|
58720
|
+
break;
|
|
58721
|
+
case KeySignature.Db:
|
|
58722
|
+
text2 = ' b';
|
|
58723
|
+
accidental = AccidentalType.Flat;
|
|
58724
|
+
break;
|
|
58725
|
+
case KeySignature.Ab:
|
|
58726
|
+
text2 = 'f';
|
|
58727
|
+
accidental = AccidentalType.None;
|
|
58728
|
+
break;
|
|
58729
|
+
case KeySignature.Eb:
|
|
58730
|
+
text2 = 'c';
|
|
58731
|
+
accidental = AccidentalType.None;
|
|
58732
|
+
break;
|
|
58733
|
+
case KeySignature.Bb:
|
|
58734
|
+
text2 = 'g';
|
|
58735
|
+
accidental = AccidentalType.None;
|
|
58736
|
+
break;
|
|
58737
|
+
case KeySignature.F:
|
|
58738
|
+
text2 = 'd';
|
|
58739
|
+
break;
|
|
58740
|
+
case KeySignature.C:
|
|
58741
|
+
text2 = 'a';
|
|
58742
|
+
accidental = AccidentalType.None;
|
|
58743
|
+
break;
|
|
58744
|
+
case KeySignature.G:
|
|
58745
|
+
text2 = 'e';
|
|
58746
|
+
accidental = AccidentalType.None;
|
|
58747
|
+
break;
|
|
58748
|
+
case KeySignature.D:
|
|
58749
|
+
text2 = 'b';
|
|
58750
|
+
accidental = AccidentalType.None;
|
|
58751
|
+
break;
|
|
58752
|
+
case KeySignature.A:
|
|
58753
|
+
text2 = ' f';
|
|
58754
|
+
accidental = AccidentalType.Sharp;
|
|
58755
|
+
break;
|
|
58756
|
+
case KeySignature.E:
|
|
58757
|
+
text2 = ' c';
|
|
58758
|
+
accidental = AccidentalType.Sharp;
|
|
58759
|
+
break;
|
|
58760
|
+
case KeySignature.B:
|
|
58761
|
+
text2 = ' g';
|
|
58762
|
+
accidental = AccidentalType.Sharp;
|
|
58763
|
+
break;
|
|
58764
|
+
case KeySignature.FSharp:
|
|
58765
|
+
text2 = ' d';
|
|
58766
|
+
accidental = AccidentalType.Sharp;
|
|
58767
|
+
break;
|
|
58768
|
+
case KeySignature.CSharp:
|
|
58769
|
+
text2 = ' a';
|
|
58770
|
+
accidental = AccidentalType.Sharp;
|
|
58771
|
+
break;
|
|
58772
|
+
}
|
|
58773
|
+
break;
|
|
58774
|
+
}
|
|
58775
|
+
this._text = text + text2;
|
|
58776
|
+
this._accidental = accidental;
|
|
58777
|
+
const c = this.renderer.scoreRenderer.canvas;
|
|
58778
|
+
const settings = this.renderer.settings;
|
|
58779
|
+
const res = settings.display.resources;
|
|
58780
|
+
c.font = res.numberedNotationFont;
|
|
58781
|
+
this._accidentalOffset = c.measureText(text).width;
|
|
58782
|
+
const fullSize = c.measureText(text + text2);
|
|
58783
|
+
this._padding =
|
|
58784
|
+
this.renderer.index === 0 ? settings.display.firstStaffPaddingLeft : settings.display.staffPaddingLeft;
|
|
58785
|
+
this.width = this._padding + fullSize.width;
|
|
58786
|
+
this.height = fullSize.height;
|
|
58787
|
+
}
|
|
58788
|
+
paint(cx, cy, canvas) {
|
|
58789
|
+
const _ = ElementStyleHelper.bar(canvas, BarSubElement.NumberedKeySignature, this.renderer.bar);
|
|
58790
|
+
try {
|
|
58791
|
+
const res = this.renderer.resources;
|
|
58792
|
+
canvas.font = res.numberedNotationFont;
|
|
58793
|
+
canvas.textBaseline = TextBaseline.Alphabetic;
|
|
58794
|
+
canvas.fillText(this._text, cx + this.x + this._padding, cy + this.y + this.height);
|
|
58795
|
+
if (this._accidental !== AccidentalType.None) {
|
|
58796
|
+
CanvasHelper.fillMusicFontSymbolSafe(canvas, cx + this.x + this._padding + this._accidentalOffset, cy + this.y + this.height, 1, AccidentalGlyph.getMusicSymbol(this._accidental), false);
|
|
58797
|
+
}
|
|
58798
|
+
}
|
|
58799
|
+
finally {
|
|
58800
|
+
_?.[Symbol.dispose]?.();
|
|
58801
|
+
}
|
|
58802
|
+
}
|
|
58803
|
+
}
|
|
58804
|
+
|
|
58805
|
+
/**
|
|
58806
|
+
* @internal
|
|
58807
|
+
*/
|
|
58808
|
+
class NumberedBarKeySignatureEffectInfo extends EffectInfo {
|
|
58809
|
+
get notationElement() {
|
|
58810
|
+
return NotationElement.EffectNumberedNotationKeySignature;
|
|
58811
|
+
}
|
|
58812
|
+
get hideOnMultiTrack() {
|
|
58813
|
+
return false;
|
|
58814
|
+
}
|
|
58815
|
+
get canShareBand() {
|
|
58816
|
+
return false;
|
|
58817
|
+
}
|
|
58818
|
+
get sizingMode() {
|
|
58819
|
+
return EffectBarGlyphSizing.FullBar;
|
|
58820
|
+
}
|
|
58821
|
+
shouldCreateGlyph(_settings, beat) {
|
|
58822
|
+
const bar = beat.voice.bar;
|
|
58823
|
+
return (beat.index === 0 &&
|
|
58824
|
+
beat.voice.index === 0 &&
|
|
58825
|
+
(!bar.previousBar || bar.keySignature !== bar.previousBar.keySignature));
|
|
58826
|
+
}
|
|
58827
|
+
createNewGlyph(renderer, _beat) {
|
|
58828
|
+
return new NumberedKeySignatureGlyph(0, 0, renderer.bar.keySignature, renderer.bar.keySignatureType);
|
|
58829
|
+
}
|
|
58830
|
+
canExpand(_from, _to) {
|
|
58831
|
+
return false;
|
|
58832
|
+
}
|
|
58833
|
+
}
|
|
58834
|
+
|
|
58586
58835
|
/**
|
|
58587
58836
|
* @internal
|
|
58588
58837
|
*/
|
|
@@ -59335,6 +59584,7 @@ class LeftToRightLayoutingGlyphGroup extends GlyphGroup {
|
|
|
59335
59584
|
class MultiVoiceContainerGlyph extends Glyph {
|
|
59336
59585
|
static KeySizeBeat = 'Beat';
|
|
59337
59586
|
voiceDrawOrder;
|
|
59587
|
+
_beatGlyphLookup = new Map();
|
|
59338
59588
|
beatGlyphs = new Map();
|
|
59339
59589
|
tupletGroups = new Map();
|
|
59340
59590
|
constructor() {
|
|
@@ -59467,6 +59717,10 @@ class MultiVoiceContainerGlyph extends Glyph {
|
|
|
59467
59717
|
beatGlyphs.length === 0 ? 0 : beatGlyphs[beatGlyphs.length - 1].x + beatGlyphs[beatGlyphs.length - 1].width;
|
|
59468
59718
|
bg.renderer = this.renderer;
|
|
59469
59719
|
beatGlyphs.push(bg);
|
|
59720
|
+
const id = bg.beatId;
|
|
59721
|
+
if (id >= 0) {
|
|
59722
|
+
this._beatGlyphLookup.set(id, bg);
|
|
59723
|
+
}
|
|
59470
59724
|
const newWidth = bg.x + bg.width;
|
|
59471
59725
|
if (newWidth > this.width) {
|
|
59472
59726
|
this.width = newWidth;
|
|
@@ -59512,11 +59766,10 @@ class MultiVoiceContainerGlyph extends Glyph {
|
|
|
59512
59766
|
return Number.NaN;
|
|
59513
59767
|
}
|
|
59514
59768
|
getBeatContainer(beat) {
|
|
59515
|
-
if (!this.
|
|
59769
|
+
if (!this._beatGlyphLookup.has(beat.id)) {
|
|
59516
59770
|
return undefined;
|
|
59517
59771
|
}
|
|
59518
|
-
|
|
59519
|
-
return beat.index < beats.length ? beats[beat.index] : undefined;
|
|
59772
|
+
return this._beatGlyphLookup.get(beat.id);
|
|
59520
59773
|
}
|
|
59521
59774
|
buildBoundingsLookup(barBounds, cx, cy) {
|
|
59522
59775
|
for (const [index, c] of this.beatGlyphs) {
|
|
@@ -62139,6 +62392,9 @@ class MultiBarRestBeatContainerGlyph extends BeatContainerGlyphBase {
|
|
|
62139
62392
|
get absoluteDisplayStart() {
|
|
62140
62393
|
return this.renderer.bar.masterBar.start;
|
|
62141
62394
|
}
|
|
62395
|
+
get beatId() {
|
|
62396
|
+
return -1;
|
|
62397
|
+
}
|
|
62142
62398
|
get onTimeX() {
|
|
62143
62399
|
return 0;
|
|
62144
62400
|
}
|
|
@@ -62210,7 +62466,6 @@ class MultiBarRestBeatContainerGlyph extends BeatContainerGlyphBase {
|
|
|
62210
62466
|
case BeatXPosition.OnNotes:
|
|
62211
62467
|
case BeatXPosition.MiddleNotes:
|
|
62212
62468
|
case BeatXPosition.Stem:
|
|
62213
|
-
return g.x + g.width / 2;
|
|
62214
62469
|
case BeatXPosition.PostNotes:
|
|
62215
62470
|
return g.x + g.width;
|
|
62216
62471
|
case BeatXPosition.EndBeat:
|
|
@@ -63302,13 +63557,13 @@ class BarRendererBase {
|
|
|
63302
63557
|
getBeatX(beat, requestedPosition = BeatXPosition.PreNotes, useSharedSizes = false) {
|
|
63303
63558
|
return this.beatGlyphsStart + this.voiceContainer.getBeatX(beat, requestedPosition, useSharedSizes);
|
|
63304
63559
|
}
|
|
63305
|
-
getRatioPositionX(
|
|
63560
|
+
getRatioPositionX(ratio) {
|
|
63306
63561
|
const firstOnNoteX = this.bar.isEmpty
|
|
63307
63562
|
? this.beatGlyphsStart
|
|
63308
63563
|
: this.getBeatX(this.bar.voices[0].beats[0], BeatXPosition.MiddleNotes);
|
|
63309
63564
|
const x = firstOnNoteX;
|
|
63310
63565
|
const w = this.postBeatGlyphsStart - firstOnNoteX;
|
|
63311
|
-
return x + w *
|
|
63566
|
+
return x + w * ratio;
|
|
63312
63567
|
}
|
|
63313
63568
|
getNoteX(note, requestedPosition) {
|
|
63314
63569
|
return this.beatGlyphsStart + this.voiceContainer.getNoteX(note, requestedPosition);
|
|
@@ -63995,6 +64250,7 @@ class TabWhammyBarGlyph extends EffectGlyph {
|
|
|
63995
64250
|
this.originalTopOffset = topY;
|
|
63996
64251
|
this.originalBottomOffset = bottomY;
|
|
63997
64252
|
this.height = topY + bottomY;
|
|
64253
|
+
this.width = 0;
|
|
63998
64254
|
}
|
|
63999
64255
|
_getOffset(value) {
|
|
64000
64256
|
if (value === 0) {
|
|
@@ -65821,6 +66077,12 @@ class BarNumberGlyph extends Glyph {
|
|
|
65821
66077
|
this._number = `${num} `;
|
|
65822
66078
|
}
|
|
65823
66079
|
doLayout() {
|
|
66080
|
+
// TODO: activate this and update paddings accordingly.
|
|
66081
|
+
// if (!this.renderer.staff!.isFirstInSystem) {
|
|
66082
|
+
// this.width = 0;
|
|
66083
|
+
// this.height = 0;
|
|
66084
|
+
// return;
|
|
66085
|
+
// }
|
|
65824
66086
|
this.renderer.scoreRenderer.canvas.font = this.renderer.resources.barNumberFont;
|
|
65825
66087
|
const size = this.renderer.scoreRenderer.canvas.measureText(this._number);
|
|
65826
66088
|
this.width = size.width;
|
|
@@ -65836,6 +66098,7 @@ class BarNumberGlyph extends Glyph {
|
|
|
65836
66098
|
const res = this.renderer.resources;
|
|
65837
66099
|
const baseline = canvas.textBaseline;
|
|
65838
66100
|
canvas.font = res.barNumberFont;
|
|
66101
|
+
canvas.textBaseline = TextBaseline.Top;
|
|
65839
66102
|
canvas.fillText(this._number, cx + this.x, cy + this.y);
|
|
65840
66103
|
canvas.textBaseline = baseline;
|
|
65841
66104
|
}
|
|
@@ -65848,47 +66111,87 @@ class BarNumberGlyph extends Glyph {
|
|
|
65848
66111
|
/**
|
|
65849
66112
|
* @internal
|
|
65850
66113
|
*/
|
|
65851
|
-
class
|
|
65852
|
-
|
|
65853
|
-
|
|
66114
|
+
class NumberedTieGlyph extends NoteTieGlyph {
|
|
66115
|
+
shouldDrawBendSlur() {
|
|
66116
|
+
return (this.renderer.settings.notation.extendBendArrowsOnTiedNotes &&
|
|
66117
|
+
!!this.startNote.bendOrigin &&
|
|
66118
|
+
this.startNote.isTieOrigin);
|
|
65854
66119
|
}
|
|
65855
|
-
|
|
65856
|
-
|
|
65857
|
-
|
|
66120
|
+
calculateTieDirection() {
|
|
66121
|
+
return BeamDirection.Up;
|
|
66122
|
+
}
|
|
66123
|
+
}
|
|
66124
|
+
|
|
66125
|
+
/**
|
|
66126
|
+
* @internal
|
|
66127
|
+
*/
|
|
66128
|
+
class AccidentalColumnInfo {
|
|
66129
|
+
x = 0;
|
|
66130
|
+
y = -3e3;
|
|
66131
|
+
width = 0;
|
|
66132
|
+
}
|
|
66133
|
+
/**
|
|
66134
|
+
* @internal
|
|
66135
|
+
*/
|
|
66136
|
+
class AccidentalGroupGlyph extends GlyphGroup {
|
|
66137
|
+
constructor() {
|
|
66138
|
+
super(0, 0);
|
|
66139
|
+
}
|
|
66140
|
+
doLayout() {
|
|
66141
|
+
if (!this.glyphs || this.glyphs.length === 0) {
|
|
66142
|
+
this.width = 0;
|
|
66143
|
+
return;
|
|
65858
66144
|
}
|
|
65859
|
-
|
|
65860
|
-
|
|
65861
|
-
|
|
65862
|
-
|
|
65863
|
-
|
|
65864
|
-
|
|
65865
|
-
|
|
65866
|
-
|
|
65867
|
-
|
|
65868
|
-
|
|
65869
|
-
|
|
65870
|
-
|
|
65871
|
-
|
|
65872
|
-
|
|
65873
|
-
|
|
65874
|
-
|
|
66145
|
+
//
|
|
66146
|
+
// Determine Columns for accidentals
|
|
66147
|
+
//
|
|
66148
|
+
this.glyphs.sort((a, b) => {
|
|
66149
|
+
if (a.y < b.y) {
|
|
66150
|
+
return -1;
|
|
66151
|
+
}
|
|
66152
|
+
if (a.y > b.y) {
|
|
66153
|
+
return 1;
|
|
66154
|
+
}
|
|
66155
|
+
return 0;
|
|
66156
|
+
});
|
|
66157
|
+
// defines the reserved y position of the columns
|
|
66158
|
+
const columns = [];
|
|
66159
|
+
columns.push(new AccidentalColumnInfo());
|
|
66160
|
+
for (let i = 0, j = this.glyphs.length; i < j; i++) {
|
|
66161
|
+
const g = this.glyphs[i];
|
|
66162
|
+
g.renderer = this.renderer;
|
|
66163
|
+
g.doLayout();
|
|
66164
|
+
// find column where glyph fits into
|
|
66165
|
+
// as long the glyph does not fit into the current column
|
|
66166
|
+
let gColumn = 0;
|
|
66167
|
+
while (columns[gColumn].y > g.y) {
|
|
66168
|
+
// move to next column
|
|
66169
|
+
gColumn++;
|
|
66170
|
+
// and create the new column if needed
|
|
66171
|
+
if (gColumn === columns.length) {
|
|
66172
|
+
columns.push(new AccidentalColumnInfo());
|
|
66173
|
+
}
|
|
66174
|
+
}
|
|
66175
|
+
// temporary save column as X
|
|
66176
|
+
g.x = gColumn;
|
|
66177
|
+
columns[gColumn].y = g.y + g.height;
|
|
66178
|
+
if (columns[gColumn].width < g.width) {
|
|
66179
|
+
columns[gColumn].width = g.width;
|
|
65875
66180
|
}
|
|
65876
66181
|
}
|
|
65877
|
-
|
|
65878
|
-
|
|
65879
|
-
|
|
65880
|
-
|
|
65881
|
-
|
|
65882
|
-
|
|
65883
|
-
|
|
65884
|
-
|
|
65885
|
-
|
|
65886
|
-
|
|
65887
|
-
|
|
65888
|
-
|
|
65889
|
-
|
|
65890
|
-
default:
|
|
65891
|
-
return MusicFontSymbol.Flag8thDown;
|
|
66182
|
+
//
|
|
66183
|
+
// Place accidentals in columns
|
|
66184
|
+
//
|
|
66185
|
+
this.width = 0;
|
|
66186
|
+
const padding = this.renderer.smuflMetrics.accidentalPadding;
|
|
66187
|
+
for (const column of columns) {
|
|
66188
|
+
this.width += column.width + padding;
|
|
66189
|
+
column.x = this.width;
|
|
66190
|
+
}
|
|
66191
|
+
for (let i = 0, j = this.glyphs.length; i < j; i++) {
|
|
66192
|
+
const g = this.glyphs[i];
|
|
66193
|
+
const column = columns[g.x];
|
|
66194
|
+
g.x = this.width - column.x;
|
|
65892
66195
|
}
|
|
65893
66196
|
}
|
|
65894
66197
|
}
|
|
@@ -65896,31 +66199,76 @@ class FlagGlyph extends MusicFontGlyph {
|
|
|
65896
66199
|
/**
|
|
65897
66200
|
* @internal
|
|
65898
66201
|
*/
|
|
65899
|
-
class
|
|
65900
|
-
|
|
65901
|
-
|
|
65902
|
-
super(x, y);
|
|
65903
|
-
this._count = 0;
|
|
65904
|
-
this._count = count;
|
|
66202
|
+
class AugmentationDotGlyph extends MusicFontGlyph {
|
|
66203
|
+
constructor(x, y) {
|
|
66204
|
+
super(x, y, 1, MusicFontSymbol.AugmentationDot);
|
|
65905
66205
|
}
|
|
65906
66206
|
doLayout() {
|
|
65907
|
-
|
|
65908
|
-
|
|
65909
|
-
this.width
|
|
65910
|
-
|
|
65911
|
-
|
|
66207
|
+
super.doLayout();
|
|
66208
|
+
this.offsetX = this.width / 2;
|
|
66209
|
+
this.width *= 1.5;
|
|
66210
|
+
}
|
|
66211
|
+
}
|
|
66212
|
+
|
|
66213
|
+
/**
|
|
66214
|
+
* @internal
|
|
66215
|
+
*/
|
|
66216
|
+
class BeatGlyphBase extends GlyphGroup {
|
|
66217
|
+
_effectGlyphs = [];
|
|
66218
|
+
_normalGlyphs = [];
|
|
66219
|
+
container;
|
|
66220
|
+
computedWidth = 0;
|
|
66221
|
+
constructor() {
|
|
66222
|
+
super(0, 0);
|
|
66223
|
+
}
|
|
66224
|
+
doLayout() {
|
|
66225
|
+
// left to right layout
|
|
66226
|
+
let w = 0;
|
|
66227
|
+
if (this.glyphs) {
|
|
66228
|
+
for (let i = 0, j = this.glyphs.length; i < j; i++) {
|
|
66229
|
+
const g = this.glyphs[i];
|
|
66230
|
+
g.x = w;
|
|
66231
|
+
g.renderer = this.renderer;
|
|
66232
|
+
g.doLayout();
|
|
66233
|
+
w += g.width;
|
|
66234
|
+
}
|
|
66235
|
+
}
|
|
66236
|
+
this.width = w;
|
|
66237
|
+
this.computedWidth = w;
|
|
66238
|
+
}
|
|
66239
|
+
noteLoop(action) {
|
|
66240
|
+
for (let i = this.container.beat.notes.length - 1; i >= 0; i--) {
|
|
66241
|
+
action(this.container.beat.notes[i]);
|
|
66242
|
+
}
|
|
66243
|
+
}
|
|
66244
|
+
addEffect(g) {
|
|
66245
|
+
super.addGlyph(g);
|
|
66246
|
+
this._effectGlyphs.push(g);
|
|
66247
|
+
}
|
|
66248
|
+
addNormal(g) {
|
|
66249
|
+
super.addGlyph(g);
|
|
66250
|
+
this._normalGlyphs.push(g);
|
|
66251
|
+
}
|
|
66252
|
+
get effectElement() {
|
|
66253
|
+
return undefined;
|
|
65912
66254
|
}
|
|
65913
66255
|
paint(cx, cy, canvas) {
|
|
65914
|
-
|
|
66256
|
+
this._paintEffects(cx, cy, canvas);
|
|
66257
|
+
this._paintNormal(cx, cy, canvas);
|
|
66258
|
+
}
|
|
66259
|
+
_paintNormal(cx, cy, canvas) {
|
|
66260
|
+
for (const g of this._normalGlyphs) {
|
|
66261
|
+
g.paint(cx + this.x, cy + this.y, canvas);
|
|
66262
|
+
}
|
|
66263
|
+
}
|
|
66264
|
+
_paintEffects(cx, cy, canvas) {
|
|
66265
|
+
const _ = this.effectElement
|
|
66266
|
+
? ElementStyleHelper.beat(canvas, this.effectElement, this.container.beat)
|
|
66267
|
+
: undefined;
|
|
65915
66268
|
try {
|
|
65916
|
-
const
|
|
65917
|
-
|
|
65918
|
-
|
|
65919
|
-
canvas.textAlign = TextAlign.Right;
|
|
65920
|
-
const s = `x${this._count}`;
|
|
65921
|
-
const w = canvas.measureText(s).width / 1.5;
|
|
65922
|
-
canvas.fillText(s, cx + this.x - w, cy + this.y);
|
|
65923
|
-
canvas.textAlign = oldAlign;
|
|
66269
|
+
for (const g of this._effectGlyphs) {
|
|
66270
|
+
g.paint(cx + this.x, cy + this.y, canvas);
|
|
66271
|
+
}
|
|
65924
66272
|
}
|
|
65925
66273
|
finally {
|
|
65926
66274
|
_?.[Symbol.dispose]?.();
|
|
@@ -65929,1847 +66277,1789 @@ class RepeatCountGlyph extends Glyph {
|
|
|
65929
66277
|
}
|
|
65930
66278
|
|
|
65931
66279
|
/**
|
|
65932
|
-
* This simple glyph allows to put an empty region in to a BarRenderer.
|
|
65933
66280
|
* @internal
|
|
65934
66281
|
*/
|
|
65935
|
-
class
|
|
65936
|
-
|
|
65937
|
-
|
|
65938
|
-
|
|
66282
|
+
class BeatOnNoteGlyphBase extends BeatGlyphBase {
|
|
66283
|
+
onTimeX = 0;
|
|
66284
|
+
middleX = 0;
|
|
66285
|
+
stemX = 0;
|
|
66286
|
+
}
|
|
66287
|
+
|
|
66288
|
+
/**
|
|
66289
|
+
* @internal
|
|
66290
|
+
*/
|
|
66291
|
+
class DeadSlappedBeatGlyph extends Glyph {
|
|
66292
|
+
_topY = 0;
|
|
66293
|
+
constructor() {
|
|
66294
|
+
super(0, 0);
|
|
65939
66295
|
}
|
|
65940
66296
|
getBoundingBoxTop() {
|
|
65941
|
-
return
|
|
66297
|
+
return this._topY;
|
|
65942
66298
|
}
|
|
65943
66299
|
getBoundingBoxBottom() {
|
|
65944
|
-
return
|
|
66300
|
+
return this._topY + this.height;
|
|
66301
|
+
}
|
|
66302
|
+
doLayout() {
|
|
66303
|
+
this.width = this.renderer.smuflMetrics.glyphWidths.get(MusicFontSymbol.NoteheadSlashWhiteHalf);
|
|
66304
|
+
const renderer = this.renderer;
|
|
66305
|
+
const crossHeight = renderer.getLineHeight(renderer.heightLineCount - 1);
|
|
66306
|
+
const staffTop = renderer.getLineY(0);
|
|
66307
|
+
const staffHeight = renderer.drawnLineCount > 0 ? renderer.getLineHeight(renderer.drawnLineCount - 1) : 0;
|
|
66308
|
+
const topY = staffTop + staffHeight / 2 - crossHeight / 2;
|
|
66309
|
+
this.height = crossHeight;
|
|
66310
|
+
this._topY = topY;
|
|
66311
|
+
}
|
|
66312
|
+
paint(cx, cy, canvas) {
|
|
66313
|
+
const crossHeight = this.height;
|
|
66314
|
+
const topY = this._topY;
|
|
66315
|
+
const lw = canvas.lineWidth;
|
|
66316
|
+
canvas.lineWidth = this.renderer.smuflMetrics.deadSlappedLineWidth;
|
|
66317
|
+
canvas.moveTo(cx + this.x, cy + topY);
|
|
66318
|
+
canvas.lineTo(cx + this.x + this.width, cy + topY + crossHeight);
|
|
66319
|
+
canvas.moveTo(cx + this.x, cy + topY + crossHeight);
|
|
66320
|
+
canvas.lineTo(cx + this.x + this.width, cy + topY);
|
|
66321
|
+
canvas.stroke();
|
|
66322
|
+
canvas.lineWidth = lw;
|
|
65945
66323
|
}
|
|
65946
66324
|
}
|
|
65947
66325
|
|
|
65948
66326
|
/**
|
|
65949
|
-
* This is a base class for any bar renderer which renders music notation on a staff
|
|
65950
|
-
* with lines like Standard Notation, Guitar Tablatures and Slash Notation.
|
|
65951
|
-
*
|
|
65952
|
-
* This base class takes care of the typical bits like drawing lines,
|
|
65953
|
-
* allowing note positioning and creating glyphs like repeats, bar numbers etc..
|
|
65954
66327
|
* @internal
|
|
65955
66328
|
*/
|
|
65956
|
-
class
|
|
65957
|
-
|
|
65958
|
-
|
|
65959
|
-
|
|
65960
|
-
|
|
65961
|
-
|
|
65962
|
-
|
|
65963
|
-
|
|
65964
|
-
|
|
65965
|
-
|
|
65966
|
-
|
|
65967
|
-
|
|
65968
|
-
|
|
65969
|
-
get bottomGlyphOverflow() {
|
|
65970
|
-
return 0;
|
|
65971
|
-
}
|
|
65972
|
-
initLineBasedSizes() {
|
|
65973
|
-
this.height = this.lineOffset * (this.heightLineCount - 1);
|
|
66329
|
+
class NumberedNoteHeadGlyph extends Glyph {
|
|
66330
|
+
_isGrace;
|
|
66331
|
+
_beat;
|
|
66332
|
+
_number;
|
|
66333
|
+
_octaveDots;
|
|
66334
|
+
_octaveDotsY = 0;
|
|
66335
|
+
_octaveDotHeight = 0;
|
|
66336
|
+
constructor(x, y, number, isGrace, beat, octaveDots) {
|
|
66337
|
+
super(x, y);
|
|
66338
|
+
this._isGrace = isGrace;
|
|
66339
|
+
this._number = number;
|
|
66340
|
+
this._beat = beat;
|
|
66341
|
+
this._octaveDots = octaveDots;
|
|
65974
66342
|
}
|
|
65975
|
-
|
|
65976
|
-
this.
|
|
65977
|
-
this.
|
|
65978
|
-
|
|
65979
|
-
|
|
66343
|
+
getBoundingBoxTop() {
|
|
66344
|
+
let y = -this.height / 2;
|
|
66345
|
+
if (this._octaveDots > 0 && this._octaveDotsY < y) {
|
|
66346
|
+
y = this._octaveDotsY;
|
|
66347
|
+
}
|
|
66348
|
+
return this.y + y;
|
|
65980
66349
|
}
|
|
65981
|
-
|
|
66350
|
+
getBoundingBoxBottom() {
|
|
66351
|
+
let y = this.height / 2;
|
|
66352
|
+
const dotsBottom = this._octaveDotsY + Math.abs(this._octaveDots) * this._octaveDotHeight * 2;
|
|
66353
|
+
if (this._octaveDots < 0 && y < dotsBottom) {
|
|
66354
|
+
y = dotsBottom;
|
|
66355
|
+
}
|
|
66356
|
+
return this.y + y;
|
|
65982
66357
|
}
|
|
65983
|
-
|
|
65984
|
-
const
|
|
65985
|
-
|
|
65986
|
-
|
|
65987
|
-
|
|
65988
|
-
|
|
65989
|
-
doLayout() {
|
|
65990
|
-
this.initLineBasedSizes();
|
|
65991
|
-
this.updateFirstLineY();
|
|
65992
|
-
this.tupletSize = this.smuflMetrics.glyphHeights.get(MusicFontSymbol.Tuplet0);
|
|
65993
|
-
super.doLayout();
|
|
65994
|
-
}
|
|
65995
|
-
getLineY(line) {
|
|
65996
|
-
return this.firstLineY + this.getLineHeight(line);
|
|
65997
|
-
}
|
|
65998
|
-
getLineHeight(line) {
|
|
65999
|
-
return this.lineOffset * line;
|
|
66000
|
-
}
|
|
66001
|
-
paintContent(cx, cy, canvas) {
|
|
66002
|
-
super.paintContent(cx, cy, canvas);
|
|
66003
|
-
this.paintBeams(cx, cy, canvas, this.flagsSubElement, this.beamsSubElement);
|
|
66004
|
-
this.paintTuplets(cx, cy, canvas, this.tupletSubElement);
|
|
66005
|
-
}
|
|
66006
|
-
paintBackground(cx, cy, canvas) {
|
|
66007
|
-
super.paintBackground(cx, cy, canvas);
|
|
66008
|
-
// canvas.color = Color.random(100);
|
|
66009
|
-
// canvas.fillRect(cx + this.x, cy + this.y, this.width, this.height);
|
|
66010
|
-
//
|
|
66011
|
-
// draw string lines
|
|
66012
|
-
//
|
|
66013
|
-
this.paintStaffLines(cx, cy, canvas);
|
|
66014
|
-
this.paintSimileMark(cx, cy, canvas);
|
|
66015
|
-
}
|
|
66016
|
-
paintStaffLines(cx, cy, canvas) {
|
|
66017
|
-
const _ = ElementStyleHelper.bar(canvas, this.staffLineBarSubElement, this.bar, true);
|
|
66358
|
+
paint(cx, cy, canvas) {
|
|
66359
|
+
const _ = this._beat.isRest
|
|
66360
|
+
? ElementStyleHelper.beat(canvas, BeatSubElement.NumberedRests, this._beat)
|
|
66361
|
+
: this._beat.notes.length > 0
|
|
66362
|
+
? ElementStyleHelper.note(canvas, NoteSubElement.NumberedNumber, this._beat.notes[0])
|
|
66363
|
+
: undefined;
|
|
66018
66364
|
try {
|
|
66019
|
-
|
|
66020
|
-
|
|
66021
|
-
|
|
66022
|
-
|
|
66023
|
-
|
|
66024
|
-
|
|
66025
|
-
|
|
66026
|
-
|
|
66027
|
-
|
|
66028
|
-
|
|
66029
|
-
|
|
66030
|
-
|
|
66031
|
-
line.sort((a, b) => {
|
|
66032
|
-
return a[0] > b[0] ? 1 : a[0] < b[0] ? -1 : 0;
|
|
66033
|
-
});
|
|
66034
|
-
}
|
|
66035
|
-
// during system fitting it can happen that we have fraction widths
|
|
66036
|
-
// but to have lines until the full end-pixel we round up.
|
|
66037
|
-
// this way we avoid holes,
|
|
66038
|
-
const lineWidth = this.width;
|
|
66039
|
-
// we want the lines to be exactly virtually aligned with the respective Y-position
|
|
66040
|
-
// for note heads to align correctly
|
|
66041
|
-
const lineYOffset = this.smuflMetrics.staffLineThickness / 2;
|
|
66042
|
-
for (let i = 0; i < this.drawnLineCount; i++) {
|
|
66043
|
-
const lineY = this.getLineY(i) - lineYOffset;
|
|
66044
|
-
let lineX = 0;
|
|
66045
|
-
for (const line of spaces[i]) {
|
|
66046
|
-
canvas.fillRect(cx + this.x + lineX, cy + this.y + lineY, line[0] - lineX, this.smuflMetrics.staffLineThickness);
|
|
66047
|
-
lineX = line[0] + line[1];
|
|
66048
|
-
}
|
|
66049
|
-
canvas.fillRect(cx + this.x + lineX, cy + this.y + lineY, lineWidth - lineX, this.smuflMetrics.staffLineThickness);
|
|
66365
|
+
const res = this.renderer.resources;
|
|
66366
|
+
canvas.font = this._isGrace ? res.numberedNotationGraceFont : res.numberedNotationFont;
|
|
66367
|
+
const baseline = canvas.textBaseline;
|
|
66368
|
+
canvas.textBaseline = TextBaseline.Middle;
|
|
66369
|
+
canvas.textAlign = TextAlign.Left;
|
|
66370
|
+
canvas.fillText(this._number.toString(), cx + this.x, cy + this.y);
|
|
66371
|
+
canvas.textBaseline = baseline;
|
|
66372
|
+
const dotCount = Math.abs(this._octaveDots);
|
|
66373
|
+
let dotsY = this._octaveDotsY + res.engravingSettings.glyphTop.get(MusicFontSymbol.AugmentationDot);
|
|
66374
|
+
for (let d = 0; d < dotCount; d++) {
|
|
66375
|
+
CanvasHelper.fillMusicFontSymbolSafe(canvas, cx + this.x + this.width / 2, cy + this.y + dotsY, 1, MusicFontSymbol.AugmentationDot, true);
|
|
66376
|
+
dotsY += this._octaveDotHeight * 2;
|
|
66050
66377
|
}
|
|
66051
66378
|
}
|
|
66052
66379
|
finally {
|
|
66053
66380
|
_?.[Symbol.dispose]?.();
|
|
66054
66381
|
}
|
|
66055
66382
|
}
|
|
66056
|
-
|
|
66383
|
+
doLayout() {
|
|
66384
|
+
const res = this.renderer.resources;
|
|
66385
|
+
const font = this._isGrace ? res.numberedNotationGraceFont : res.numberedNotationFont;
|
|
66386
|
+
const c = this.renderer.scoreRenderer.canvas;
|
|
66387
|
+
c.font = font;
|
|
66388
|
+
const size = c.measureText(`${this._number}`);
|
|
66389
|
+
this.height = size.height;
|
|
66390
|
+
this.width = size.width;
|
|
66391
|
+
const dotCount = this._octaveDots;
|
|
66392
|
+
const dotHeight = res.engravingSettings.glyphHeights.get(MusicFontSymbol.AugmentationDot);
|
|
66393
|
+
const allDotsHeight = Math.abs(dotCount) * dotHeight * 2;
|
|
66394
|
+
if (dotCount > 0) {
|
|
66395
|
+
this._octaveDotsY =
|
|
66396
|
+
-(this.height / 2) -
|
|
66397
|
+
allDotsHeight -
|
|
66398
|
+
res.engravingSettings.glyphTop.get(MusicFontSymbol.AugmentationDot);
|
|
66399
|
+
}
|
|
66400
|
+
else if (dotCount < 0) {
|
|
66401
|
+
this._octaveDotsY =
|
|
66402
|
+
this.height / 2 +
|
|
66403
|
+
// one for the padding
|
|
66404
|
+
dotHeight +
|
|
66405
|
+
// align the dots
|
|
66406
|
+
res.engravingSettings.glyphTop.get(MusicFontSymbol.AugmentationDot);
|
|
66407
|
+
}
|
|
66408
|
+
this._octaveDotHeight = dotHeight;
|
|
66057
66409
|
}
|
|
66058
|
-
|
|
66059
|
-
|
|
66410
|
+
}
|
|
66411
|
+
|
|
66412
|
+
/**
|
|
66413
|
+
* This simple glyph allows to put an empty region in to a BarRenderer.
|
|
66414
|
+
* @internal
|
|
66415
|
+
*/
|
|
66416
|
+
class SpacingGlyph extends Glyph {
|
|
66417
|
+
constructor(x, y, width) {
|
|
66418
|
+
super(x, y);
|
|
66419
|
+
this.width = width;
|
|
66420
|
+
}
|
|
66421
|
+
getBoundingBoxTop() {
|
|
66422
|
+
return Number.NaN;
|
|
66423
|
+
}
|
|
66424
|
+
getBoundingBoxBottom() {
|
|
66425
|
+
return Number.NaN;
|
|
66426
|
+
}
|
|
66427
|
+
}
|
|
66428
|
+
|
|
66429
|
+
/**
|
|
66430
|
+
* @internal
|
|
66431
|
+
*/
|
|
66432
|
+
class NumberedBeatPreNotesGlyph extends BeatGlyphBase {
|
|
66433
|
+
isNaturalizeAccidental = false;
|
|
66434
|
+
accidental = AccidentalType.None;
|
|
66435
|
+
skipLayout = false;
|
|
66436
|
+
get effectElement() {
|
|
66437
|
+
return BeatSubElement.NumberedEffects;
|
|
66438
|
+
}
|
|
66439
|
+
doLayout() {
|
|
66440
|
+
if (this.skipLayout) {
|
|
66060
66441
|
return;
|
|
66061
66442
|
}
|
|
66062
|
-
|
|
66063
|
-
|
|
66064
|
-
|
|
66065
|
-
|
|
66066
|
-
|
|
66067
|
-
|
|
66068
|
-
|
|
66069
|
-
|
|
66070
|
-
|
|
66071
|
-
|
|
66443
|
+
if (!this.container.beat.isRest && !this.container.beat.isEmpty) {
|
|
66444
|
+
const accidentals = new AccidentalGroupGlyph();
|
|
66445
|
+
accidentals.renderer = this.renderer;
|
|
66446
|
+
if (this.container.beat.notes.length > 0) {
|
|
66447
|
+
const note = this.container.beat.notes[0];
|
|
66448
|
+
// Notes
|
|
66449
|
+
// - Compared to standard notation accidentals:
|
|
66450
|
+
// - Flat keysigs: When there is a naturalize symbol (against key signature, not naturalizing same line) we have a # in Numbered notation
|
|
66451
|
+
// - Flat keysigs: When there is a flat symbol standard notation we also have a flat in Numbered notation
|
|
66452
|
+
// - C keysig: A sharp on standard notation is a sharp on numbered notation
|
|
66453
|
+
// - # keysigs: When there is a # symbol on standard notation we also a sharp in numbered notation
|
|
66454
|
+
// - # keysigs: When there is a naturalize symbol (against key signature, not naturalizing same line) we have a flat in Numbered notation
|
|
66455
|
+
// Or generally:
|
|
66456
|
+
// - numbered notation has the same accidentals as standard notation if applied
|
|
66457
|
+
// - when the standard notation naturalizes the accidental from the key signature, the numbered notation has the reversed accidental
|
|
66458
|
+
const accidentalMode = note ? note.accidentalMode : NoteAccidentalMode.Default;
|
|
66459
|
+
const noteValue = AccidentalHelper.getNoteValue(note);
|
|
66460
|
+
let accidentalToSet = ModelUtils.computeAccidental(this.renderer.bar.keySignature, accidentalMode, noteValue, note.hasQuarterToneOffset);
|
|
66461
|
+
if (accidentalToSet === AccidentalType.Natural) {
|
|
66462
|
+
const ks = this.renderer.bar.keySignature;
|
|
66463
|
+
const ksi = ks + 7;
|
|
66464
|
+
const naturalizeAccidentalForKeySignature = ksi < 7 ? AccidentalType.Sharp : AccidentalType.Flat;
|
|
66465
|
+
accidentalToSet = naturalizeAccidentalForKeySignature;
|
|
66466
|
+
this.isNaturalizeAccidental = true;
|
|
66467
|
+
}
|
|
66468
|
+
// do we need an accidental on the note?
|
|
66469
|
+
if (accidentalToSet !== AccidentalType.None) {
|
|
66470
|
+
this.accidental = accidentalToSet;
|
|
66471
|
+
const sr = this.renderer;
|
|
66472
|
+
const color = ElementStyleHelper.noteColor(sr.resources, NoteSubElement.NumberedAccidentals, note);
|
|
66473
|
+
const g = new AccidentalGlyph(0, sr.getLineY(0), accidentalToSet, note.beat.graceType !== GraceType.None
|
|
66474
|
+
? EngravingSettings.GraceScale * EngravingSettings.GraceScale
|
|
66475
|
+
: EngravingSettings.GraceScale);
|
|
66476
|
+
g.colorOverride = color;
|
|
66477
|
+
g.renderer = this.renderer;
|
|
66478
|
+
accidentals.addGlyph(g);
|
|
66479
|
+
this.addNormal(accidentals);
|
|
66480
|
+
this.addNormal(new SpacingGlyph(0, 0, this.renderer.smuflMetrics.preNoteEffectPadding));
|
|
66072
66481
|
}
|
|
66073
66482
|
}
|
|
66074
66483
|
}
|
|
66484
|
+
super.doLayout();
|
|
66075
66485
|
}
|
|
66076
|
-
|
|
66077
|
-
|
|
66486
|
+
}
|
|
66487
|
+
/**
|
|
66488
|
+
* @internal
|
|
66489
|
+
*/
|
|
66490
|
+
class NumberedBeatGlyph extends BeatOnNoteGlyphBase {
|
|
66491
|
+
noteHeads = null;
|
|
66492
|
+
deadSlapped = null;
|
|
66493
|
+
get effectElement() {
|
|
66494
|
+
return BeatSubElement.NumberedEffects;
|
|
66078
66495
|
}
|
|
66079
|
-
|
|
66080
|
-
|
|
66081
|
-
|
|
66082
|
-
|
|
66083
|
-
canvas.color = h.voice.index === 0 ? this.resources.mainGlyphColor : this.resources.secondaryGlyphColor;
|
|
66084
|
-
canvas.textAlign = TextAlign.Center;
|
|
66085
|
-
canvas.textBaseline = TextBaseline.Middle;
|
|
66086
|
-
let s;
|
|
66087
|
-
const num = h.beats[0].tupletNumerator;
|
|
66088
|
-
const den = h.beats[0].tupletDenominator;
|
|
66089
|
-
// list as in Guitar Pro 7. for certain tuplets only the numerator is shown
|
|
66090
|
-
if (num === 2 && den === 3) {
|
|
66091
|
-
s = [MusicFontSymbol.Tuplet2];
|
|
66092
|
-
}
|
|
66093
|
-
else if (num === 3 && den === 2) {
|
|
66094
|
-
s = [MusicFontSymbol.Tuplet3];
|
|
66095
|
-
}
|
|
66096
|
-
else if (num === 4 && den === 6) {
|
|
66097
|
-
s = [MusicFontSymbol.Tuplet4];
|
|
66098
|
-
}
|
|
66099
|
-
else if (num === 5 && den === 4) {
|
|
66100
|
-
s = [MusicFontSymbol.Tuplet5];
|
|
66101
|
-
}
|
|
66102
|
-
else if (num === 6 && den === 4) {
|
|
66103
|
-
s = [MusicFontSymbol.Tuplet6];
|
|
66104
|
-
}
|
|
66105
|
-
else if (num === 7 && den === 4) {
|
|
66106
|
-
s = [MusicFontSymbol.Tuplet7];
|
|
66496
|
+
getNoteX(_note, requestedPosition) {
|
|
66497
|
+
let g = null;
|
|
66498
|
+
if (this.noteHeads) {
|
|
66499
|
+
g = this.noteHeads;
|
|
66107
66500
|
}
|
|
66108
|
-
else if (
|
|
66109
|
-
|
|
66501
|
+
else if (this.deadSlapped) {
|
|
66502
|
+
g = this.deadSlapped;
|
|
66110
66503
|
}
|
|
66111
|
-
|
|
66112
|
-
|
|
66504
|
+
if (g) {
|
|
66505
|
+
let pos = g.x;
|
|
66506
|
+
switch (requestedPosition) {
|
|
66507
|
+
case NoteXPosition.Left:
|
|
66508
|
+
break;
|
|
66509
|
+
case NoteXPosition.Center:
|
|
66510
|
+
pos += g.width / 2;
|
|
66511
|
+
break;
|
|
66512
|
+
case NoteXPosition.Right:
|
|
66513
|
+
pos += g.width;
|
|
66514
|
+
break;
|
|
66515
|
+
}
|
|
66516
|
+
return pos;
|
|
66113
66517
|
}
|
|
66114
|
-
|
|
66115
|
-
|
|
66518
|
+
return 0;
|
|
66519
|
+
}
|
|
66520
|
+
buildBoundingsLookup(beatBounds, cx, cy) {
|
|
66521
|
+
if (this.noteHeads && this.container.beat.notes.length > 0) {
|
|
66522
|
+
const noteBounds = new NoteBounds();
|
|
66523
|
+
noteBounds.note = this.container.beat.notes[0];
|
|
66524
|
+
noteBounds.noteHeadBounds = new Bounds();
|
|
66525
|
+
noteBounds.noteHeadBounds.x = cx + this.x + this.noteHeads.x;
|
|
66526
|
+
noteBounds.noteHeadBounds.y = cy + this.y + this.noteHeads.y - this.noteHeads.height / 2;
|
|
66527
|
+
noteBounds.noteHeadBounds.w = this.width;
|
|
66528
|
+
noteBounds.noteHeadBounds.h = this.height;
|
|
66529
|
+
beatBounds.addNote(noteBounds);
|
|
66116
66530
|
}
|
|
66117
|
-
|
|
66118
|
-
|
|
66531
|
+
}
|
|
66532
|
+
getLowestNoteY() {
|
|
66533
|
+
return this._internalGetNoteY(NoteYPosition.Center);
|
|
66534
|
+
}
|
|
66535
|
+
getHighestNoteY() {
|
|
66536
|
+
return this._internalGetNoteY(NoteYPosition.Center);
|
|
66537
|
+
}
|
|
66538
|
+
getNoteY(_note, requestedPosition) {
|
|
66539
|
+
return this._internalGetNoteY(requestedPosition);
|
|
66540
|
+
}
|
|
66541
|
+
getRestY(requestedPosition) {
|
|
66542
|
+
return this._internalGetNoteY(requestedPosition);
|
|
66543
|
+
}
|
|
66544
|
+
_internalGetNoteY(requestedPosition) {
|
|
66545
|
+
let g = null;
|
|
66546
|
+
if (this.noteHeads) {
|
|
66547
|
+
g = this.noteHeads;
|
|
66119
66548
|
}
|
|
66120
|
-
else if (
|
|
66121
|
-
|
|
66549
|
+
else if (this.deadSlapped) {
|
|
66550
|
+
g = this.deadSlapped;
|
|
66122
66551
|
}
|
|
66123
|
-
|
|
66124
|
-
|
|
66125
|
-
|
|
66126
|
-
|
|
66127
|
-
|
|
66128
|
-
|
|
66129
|
-
|
|
66130
|
-
|
|
66131
|
-
|
|
66132
|
-
|
|
66133
|
-
|
|
66134
|
-
|
|
66135
|
-
|
|
66136
|
-
|
|
66137
|
-
|
|
66138
|
-
|
|
66139
|
-
s.push((zero + den));
|
|
66552
|
+
if (g) {
|
|
66553
|
+
let pos = this.y + g.y;
|
|
66554
|
+
switch (requestedPosition) {
|
|
66555
|
+
case NoteYPosition.Top:
|
|
66556
|
+
case NoteYPosition.TopWithStem:
|
|
66557
|
+
pos -= g.height / 2;
|
|
66558
|
+
break;
|
|
66559
|
+
case NoteYPosition.Center:
|
|
66560
|
+
break;
|
|
66561
|
+
case NoteYPosition.Bottom:
|
|
66562
|
+
case NoteYPosition.BottomWithStem:
|
|
66563
|
+
pos += g.height / 2;
|
|
66564
|
+
break;
|
|
66565
|
+
case NoteYPosition.StemUp:
|
|
66566
|
+
case NoteYPosition.StemDown:
|
|
66567
|
+
break;
|
|
66140
66568
|
}
|
|
66569
|
+
return pos;
|
|
66141
66570
|
}
|
|
66142
|
-
|
|
66143
|
-
|
|
66144
|
-
|
|
66145
|
-
|
|
66146
|
-
|
|
66147
|
-
|
|
66148
|
-
|
|
66149
|
-
|
|
66150
|
-
|
|
66151
|
-
|
|
66152
|
-
|
|
66153
|
-
|
|
66154
|
-
|
|
66155
|
-
|
|
66156
|
-
|
|
66157
|
-
|
|
66158
|
-
|
|
66159
|
-
|
|
66160
|
-
|
|
66571
|
+
return 0;
|
|
66572
|
+
}
|
|
66573
|
+
static majorKeySignatureOneValues = [
|
|
66574
|
+
// Flats
|
|
66575
|
+
59, 66, 61, 68, 63, 58, 65,
|
|
66576
|
+
// natural
|
|
66577
|
+
60,
|
|
66578
|
+
// sharps (where the value is true, a flat accidental is required for the notes)
|
|
66579
|
+
67, 62, 69, 64, 71, 66, 61
|
|
66580
|
+
];
|
|
66581
|
+
static minorKeySignatureOneValues = [
|
|
66582
|
+
// Flats
|
|
66583
|
+
71, 66, 73, 68, 63, 70, 65,
|
|
66584
|
+
// natural
|
|
66585
|
+
72,
|
|
66586
|
+
// sharps (where the value is true, a flat accidental is required for the notes)
|
|
66587
|
+
67, 74, 69, 64, 71, 66, 73
|
|
66588
|
+
];
|
|
66589
|
+
doLayout() {
|
|
66590
|
+
// create glyphs
|
|
66591
|
+
const sr = this.renderer;
|
|
66592
|
+
if (sr.shortestDuration < this.container.beat.duration) {
|
|
66593
|
+
sr.shortestDuration = this.container.beat.duration;
|
|
66594
|
+
}
|
|
66595
|
+
let octaveDots = 0;
|
|
66596
|
+
if (!this.container.beat.isEmpty) {
|
|
66597
|
+
const glyphY = sr.getLineY(0);
|
|
66598
|
+
let numberWithinOctave = '0';
|
|
66599
|
+
if (this.container.beat.notes.length > 0) {
|
|
66600
|
+
const note = this.container.beat.notes[0];
|
|
66601
|
+
const kst = this.renderer.bar.keySignatureType;
|
|
66602
|
+
const ks = this.renderer.bar.keySignature;
|
|
66603
|
+
const ksi = ks + 7;
|
|
66604
|
+
const oneNoteValues = kst === KeySignatureType.Minor
|
|
66605
|
+
? NumberedBeatGlyph.minorKeySignatureOneValues
|
|
66606
|
+
: NumberedBeatGlyph.majorKeySignatureOneValues;
|
|
66607
|
+
const oneNoteValue = oneNoteValues[ksi];
|
|
66608
|
+
if (note.isDead) {
|
|
66609
|
+
numberWithinOctave = 'X';
|
|
66610
|
+
}
|
|
66611
|
+
else {
|
|
66612
|
+
const noteValue = note.displayValue - oneNoteValue;
|
|
66613
|
+
const index = noteValue < 0 ? ((noteValue % 12) + 12) % 12 : noteValue % 12;
|
|
66614
|
+
octaveDots = noteValue < 0 ? ((Math.abs(noteValue) + 12) / 12) | 0 : (noteValue / 12) | 0;
|
|
66615
|
+
if (noteValue < 0) {
|
|
66616
|
+
octaveDots *= -1;
|
|
66161
66617
|
}
|
|
66162
|
-
|
|
66163
|
-
|
|
66618
|
+
const stepList = ModelUtils.keySignatureIsSharp(ks) || ModelUtils.keySignatureIsNatural(ks)
|
|
66619
|
+
? AccidentalHelper.flatNoteSteps
|
|
66620
|
+
: AccidentalHelper.sharpNoteSteps;
|
|
66621
|
+
let steps = stepList[index] + 1;
|
|
66622
|
+
const hasAccidental = ModelUtils.accidentalNotes[index];
|
|
66623
|
+
if (hasAccidental &&
|
|
66624
|
+
!this.container.preNotes.isNaturalizeAccidental) {
|
|
66625
|
+
if (ksi < 7) {
|
|
66626
|
+
steps++;
|
|
66627
|
+
}
|
|
66628
|
+
else {
|
|
66629
|
+
steps--;
|
|
66630
|
+
}
|
|
66164
66631
|
}
|
|
66165
|
-
|
|
66632
|
+
numberWithinOctave = steps.toString();
|
|
66166
66633
|
}
|
|
66167
66634
|
}
|
|
66635
|
+
if (this.container.beat.deadSlapped) {
|
|
66636
|
+
const deadSlapped = new DeadSlappedBeatGlyph();
|
|
66637
|
+
deadSlapped.renderer = this.renderer;
|
|
66638
|
+
deadSlapped.doLayout();
|
|
66639
|
+
this.deadSlapped = deadSlapped;
|
|
66640
|
+
this.addEffect(deadSlapped);
|
|
66641
|
+
}
|
|
66168
66642
|
else {
|
|
66169
|
-
const
|
|
66170
|
-
const
|
|
66171
|
-
|
|
66172
|
-
|
|
66173
|
-
|
|
66174
|
-
|
|
66175
|
-
|
|
66176
|
-
|
|
66177
|
-
|
|
66178
|
-
|
|
66179
|
-
|
|
66180
|
-
|
|
66181
|
-
lastNonRestBeat = h.beats[i];
|
|
66182
|
-
break;
|
|
66183
|
-
}
|
|
66184
|
-
}
|
|
66185
|
-
let isRestOnly = false;
|
|
66186
|
-
if (!firstNonRestBeat) {
|
|
66187
|
-
firstNonRestBeat = firstBeat;
|
|
66188
|
-
isRestOnly = true;
|
|
66189
|
-
}
|
|
66190
|
-
if (!lastNonRestBeat) {
|
|
66191
|
-
lastNonRestBeat = lastBeat;
|
|
66192
|
-
}
|
|
66193
|
-
//
|
|
66194
|
-
// Calculate the overall area of the tuplet bracket
|
|
66195
|
-
const startX = this.getBeatX(firstBeat, BeatXPosition.OnNotes);
|
|
66196
|
-
const endX = this.getBeatX(lastBeat, BeatXPosition.PostNotes);
|
|
66197
|
-
//
|
|
66198
|
-
// calculate the y positions for our bracket
|
|
66199
|
-
const firstNonRestBeamingHelper = this.helpers.getBeamingHelperForBeat(firstNonRestBeat);
|
|
66200
|
-
const lastNonRestBeamingHelper = this.helpers.getBeamingHelperForBeat(lastNonRestBeat);
|
|
66201
|
-
const direction = this.getTupletBeamDirection(firstNonRestBeamingHelper);
|
|
66202
|
-
let startY = this.calculateBeamYWithDirection(firstNonRestBeamingHelper, startX, direction);
|
|
66203
|
-
let endY = this.calculateBeamYWithDirection(lastNonRestBeamingHelper, endX, direction);
|
|
66204
|
-
if (isRestOnly) {
|
|
66205
|
-
startY = Math.max(startY, endY);
|
|
66206
|
-
endY = startY;
|
|
66207
|
-
}
|
|
66208
|
-
// align line centered in available space
|
|
66209
|
-
if (direction === BeamDirection.Down) {
|
|
66210
|
-
startY += shift;
|
|
66211
|
-
endY += shift;
|
|
66212
|
-
}
|
|
66213
|
-
else {
|
|
66214
|
-
startY -= shift;
|
|
66215
|
-
endY -= shift;
|
|
66216
|
-
}
|
|
66217
|
-
//
|
|
66218
|
-
// Calculate how many space the text will need
|
|
66219
|
-
const sw = s.reduce((acc, sym) => acc + res.engravingSettings.glyphWidths.get(sym), 0);
|
|
66220
|
-
const sp = res.engravingSettings.oneStaffSpace * 0.5;
|
|
66221
|
-
//
|
|
66222
|
-
// Calculate the offsets where to break the bracket
|
|
66223
|
-
const middleX = (startX + endX) / 2;
|
|
66224
|
-
const offset1X = middleX - sw / 2 - sp;
|
|
66225
|
-
const offset2X = middleX + sw / 2 + sp;
|
|
66226
|
-
const k = (endY - startY) / (endX - startX);
|
|
66227
|
-
const d = startY - k * startX;
|
|
66228
|
-
const offset1Y = k * offset1X + d;
|
|
66229
|
-
const middleY = k * middleX + d;
|
|
66230
|
-
const offset2Y = k * offset2X + d;
|
|
66231
|
-
const angleStartY = direction === BeamDirection.Down ? startY - size * 0.5 : startY + size * 0.5;
|
|
66232
|
-
const angleEndY = direction === BeamDirection.Down ? endY - size * 0.5 : endY + size * 0.5;
|
|
66233
|
-
//
|
|
66234
|
-
// draw the bracket
|
|
66235
|
-
const pixelAlignment = canvas.lineWidth % 2 === 0 ? 0 : 0.5;
|
|
66236
|
-
cx += pixelAlignment;
|
|
66237
|
-
cy += pixelAlignment;
|
|
66238
|
-
if (offset1X > startX) {
|
|
66239
|
-
canvas.beginPath();
|
|
66240
|
-
canvas.moveTo(cx + this.x + startX, cy + this.y + angleStartY);
|
|
66241
|
-
if (bracketsAsArcs) {
|
|
66242
|
-
canvas.quadraticCurveTo(cx + this.x + (offset1X + startX) / 2, cy + this.y + offset1Y, cx + this.x + offset1X, cy + this.y + offset1Y);
|
|
66243
|
-
}
|
|
66244
|
-
else {
|
|
66245
|
-
canvas.lineTo(cx + this.x + startX, cy + this.y + startY);
|
|
66246
|
-
canvas.lineTo(cx + this.x + offset1X, cy + this.y + offset1Y);
|
|
66247
|
-
}
|
|
66248
|
-
canvas.moveTo(cx + this.x + offset2X, cy + this.y + offset2Y);
|
|
66249
|
-
if (bracketsAsArcs) {
|
|
66250
|
-
canvas.quadraticCurveTo(cx + this.x + (endX + offset2X) / 2, cy + this.y + offset2Y, cx + this.x + endX, cy + this.y + angleEndY);
|
|
66251
|
-
}
|
|
66252
|
-
else {
|
|
66253
|
-
canvas.lineTo(cx + this.x + endX, cy + this.y + endY);
|
|
66254
|
-
canvas.lineTo(cx + this.x + endX, cy + this.y + angleEndY);
|
|
66255
|
-
}
|
|
66256
|
-
canvas.stroke();
|
|
66643
|
+
const isGrace = this.container.beat.graceType !== GraceType.None;
|
|
66644
|
+
const noteHeadGlyph = new NumberedNoteHeadGlyph(0, glyphY, numberWithinOctave, isGrace, this.container.beat, octaveDots);
|
|
66645
|
+
this.noteHeads = noteHeadGlyph;
|
|
66646
|
+
this.addNormal(noteHeadGlyph);
|
|
66647
|
+
}
|
|
66648
|
+
//
|
|
66649
|
+
// Note dots
|
|
66650
|
+
if (this.container.beat.dots > 0 && this.container.beat.duration >= Duration.Quarter) {
|
|
66651
|
+
for (let i = 0; i < this.container.beat.dots; i++) {
|
|
66652
|
+
const dot = new AugmentationDotGlyph(0, glyphY);
|
|
66653
|
+
dot.renderer = this.renderer;
|
|
66654
|
+
this.addEffect(dot);
|
|
66257
66655
|
}
|
|
66258
|
-
//
|
|
66259
|
-
// Draw the string
|
|
66260
|
-
canvas.fillMusicFontSymbols(cx + this.x + middleX, cy + this.y + middleY + size * 0.5, 1, s, true);
|
|
66261
66656
|
}
|
|
66262
|
-
canvas.textAlign = oldAlign;
|
|
66263
|
-
canvas.textBaseline = oldBaseLine;
|
|
66264
|
-
canvas.lineWidth = l;
|
|
66265
66657
|
}
|
|
66266
|
-
|
|
66267
|
-
|
|
66658
|
+
super.doLayout();
|
|
66659
|
+
if (this.container.beat.isEmpty) {
|
|
66660
|
+
this.onTimeX = this.width / 2;
|
|
66268
66661
|
}
|
|
66269
|
-
|
|
66270
|
-
|
|
66271
|
-
for (const v of this.voiceContainer.voiceDrawOrder) {
|
|
66272
|
-
for (const h of this.helpers.beamHelpers[v]) {
|
|
66273
|
-
this.paintBeamHelper(cx, cy, canvas, h, flagsElement, beamsElement);
|
|
66274
|
-
}
|
|
66662
|
+
else if (this.noteHeads) {
|
|
66663
|
+
this.onTimeX = this.noteHeads.x + this.noteHeads.width / 2;
|
|
66275
66664
|
}
|
|
66276
|
-
|
|
66277
|
-
|
|
66278
|
-
return h.beats.length === 1;
|
|
66279
|
-
}
|
|
66280
|
-
hasFlag(beat) {
|
|
66281
|
-
if (beat.isRest) {
|
|
66282
|
-
return false;
|
|
66665
|
+
else if (this.deadSlapped) {
|
|
66666
|
+
this.onTimeX = this.deadSlapped.x + this.deadSlapped.width / 2;
|
|
66283
66667
|
}
|
|
66284
|
-
|
|
66285
|
-
|
|
66286
|
-
return helper.hasFlag(this.drawBeamHelperAsFlags(helper), beat);
|
|
66287
|
-
}
|
|
66288
|
-
return BeamingHelper.beatHasFlag(beat);
|
|
66668
|
+
this.middleX = this.onTimeX;
|
|
66669
|
+
this.stemX = this.middleX;
|
|
66289
66670
|
}
|
|
66290
|
-
|
|
66291
|
-
|
|
66292
|
-
|
|
66293
|
-
|
|
66294
|
-
|
|
66295
|
-
|
|
66296
|
-
|
|
66671
|
+
}
|
|
66672
|
+
|
|
66673
|
+
/**
|
|
66674
|
+
* @internal
|
|
66675
|
+
*/
|
|
66676
|
+
class TabTieGlyph extends NoteTieGlyph {
|
|
66677
|
+
calculateTieDirection() {
|
|
66678
|
+
if (this.isLeftHandTap) {
|
|
66679
|
+
return BeamDirection.Up;
|
|
66297
66680
|
}
|
|
66298
|
-
return
|
|
66681
|
+
return TabTieGlyph.getBeamDirectionForNote(this.startNote);
|
|
66299
66682
|
}
|
|
66300
|
-
|
|
66301
|
-
|
|
66302
|
-
if (!h.isRestBeamHelper) {
|
|
66303
|
-
if (this.drawBeamHelperAsFlags(h)) {
|
|
66304
|
-
this.paintFlag(cx, cy, canvas, h, flagsElement);
|
|
66305
|
-
}
|
|
66306
|
-
else {
|
|
66307
|
-
this.paintBar(cx, cy, canvas, h, beamsElement);
|
|
66308
|
-
}
|
|
66309
|
-
}
|
|
66683
|
+
static getBeamDirectionForNote(note) {
|
|
66684
|
+
return note.string > 3 ? BeamDirection.Up : BeamDirection.Down;
|
|
66310
66685
|
}
|
|
66311
|
-
|
|
66312
|
-
|
|
66313
|
-
|
|
66686
|
+
}
|
|
66687
|
+
|
|
66688
|
+
/**
|
|
66689
|
+
* @internal
|
|
66690
|
+
*/
|
|
66691
|
+
class TabSlurGlyph extends TabTieGlyph {
|
|
66692
|
+
_forSlide;
|
|
66693
|
+
constructor(slurEffectId, startNote, endNote, forSlide, forEnd) {
|
|
66694
|
+
super(slurEffectId, startNote, endNote, forEnd);
|
|
66695
|
+
this._forSlide = forSlide;
|
|
66696
|
+
}
|
|
66697
|
+
getTieHeight(startX, _startY, endX, _endY) {
|
|
66698
|
+
return (Math.log(endX - startX + 1) * this.renderer.settings.notation.slurHeight) / 2;
|
|
66699
|
+
}
|
|
66700
|
+
tryExpand(startNote, endNote, forSlide, forEnd) {
|
|
66701
|
+
// same type required
|
|
66702
|
+
if (this._forSlide !== forSlide) {
|
|
66314
66703
|
return false;
|
|
66315
66704
|
}
|
|
66316
|
-
|
|
66705
|
+
// same start and endbeat
|
|
66706
|
+
if (this.startNote.beat.id !== startNote.beat.id) {
|
|
66317
66707
|
return false;
|
|
66318
66708
|
}
|
|
66319
|
-
|
|
66320
|
-
if (beat.graceType !== GraceType.None && this.settings.notation.notationMode === NotationMode.SongBook) {
|
|
66709
|
+
if (this.endNote.beat.id !== endNote.beat.id) {
|
|
66321
66710
|
return false;
|
|
66322
66711
|
}
|
|
66323
|
-
|
|
66324
|
-
if (
|
|
66325
|
-
beat.duration === Duration.DoubleWhole ||
|
|
66326
|
-
beat.duration === Duration.QuadrupleWhole) {
|
|
66712
|
+
const isForEnd = this.renderer === this.lookupEndBeatRenderer();
|
|
66713
|
+
if (isForEnd !== forEnd) {
|
|
66327
66714
|
return false;
|
|
66328
66715
|
}
|
|
66329
|
-
|
|
66330
|
-
|
|
66331
|
-
|
|
66332
|
-
|
|
66333
|
-
|
|
66334
|
-
|
|
66335
|
-
|
|
66336
|
-
|
|
66337
|
-
|
|
66338
|
-
// draw line
|
|
66339
|
-
//
|
|
66340
|
-
const beatLineX = this.getBeatX(beat, BeatXPosition.Stem);
|
|
66341
|
-
const direction = this.getBeamDirection(h);
|
|
66342
|
-
const topY = cy + this.y + this.getFlagTopY(beat, direction);
|
|
66343
|
-
const bottomY = cy + this.y + this.getFlagBottomY(beat, direction);
|
|
66344
|
-
let flagY = 0;
|
|
66345
|
-
if (direction === BeamDirection.Down) {
|
|
66346
|
-
flagY = bottomY;
|
|
66347
|
-
}
|
|
66348
|
-
else {
|
|
66349
|
-
flagY = topY;
|
|
66350
|
-
}
|
|
66351
|
-
if (!h.hasStem(true, beat)) {
|
|
66352
|
-
continue;
|
|
66353
|
-
}
|
|
66354
|
-
this.paintBeamingStem(beat, cy + this.y, cx + this.x + beatLineX, topY, bottomY, canvas);
|
|
66355
|
-
const _ = ElementStyleHelper.beat(canvas, flagsElement, beat);
|
|
66356
|
-
try {
|
|
66357
|
-
let flagWidth = 0;
|
|
66358
|
-
//
|
|
66359
|
-
// Draw flag
|
|
66360
|
-
//
|
|
66361
|
-
if (h.hasFlag(true, beat)) {
|
|
66362
|
-
const glyph = new FlagGlyph(cx + this.x + beatLineX, flagY, beat.duration, direction, isGrace);
|
|
66363
|
-
glyph.renderer = this;
|
|
66364
|
-
glyph.doLayout();
|
|
66365
|
-
glyph.paint(0, 0, canvas);
|
|
66366
|
-
flagWidth = glyph.width / 2;
|
|
66716
|
+
// same draw direction
|
|
66717
|
+
if (this.tieDirection !== TabTieGlyph.getBeamDirectionForNote(startNote)) {
|
|
66718
|
+
return false;
|
|
66719
|
+
}
|
|
66720
|
+
// if we can expand, expand in correct direction
|
|
66721
|
+
switch (this.tieDirection) {
|
|
66722
|
+
case BeamDirection.Up:
|
|
66723
|
+
if (startNote.realValue > this.startNote.realValue) {
|
|
66724
|
+
this.startNote = startNote;
|
|
66367
66725
|
}
|
|
66368
|
-
if (
|
|
66369
|
-
|
|
66370
|
-
CanvasHelper.fillMusicFontSymbolSafe(canvas, cx + this.x + beatLineX + flagWidth / 2, (topY + bottomY - this.smuflMetrics.glyphHeights.get(MusicFontSymbol.GraceNoteSlashStemDown)) /
|
|
66371
|
-
2, EngravingSettings.GraceScale, MusicFontSymbol.GraceNoteSlashStemDown, true);
|
|
66372
|
-
}
|
|
66373
|
-
else {
|
|
66374
|
-
CanvasHelper.fillMusicFontSymbolSafe(canvas, cx + this.x + beatLineX + flagWidth / 2, (topY + bottomY + this.smuflMetrics.glyphHeights.get(MusicFontSymbol.GraceNoteSlashStemUp)) /
|
|
66375
|
-
2, EngravingSettings.GraceScale, MusicFontSymbol.GraceNoteSlashStemUp, true);
|
|
66376
|
-
}
|
|
66726
|
+
if (endNote.realValue > this.endNote.realValue) {
|
|
66727
|
+
this.endNote = endNote;
|
|
66377
66728
|
}
|
|
66378
|
-
}
|
|
66379
|
-
finally {
|
|
66380
|
-
_?.[Symbol.dispose]?.();
|
|
66381
|
-
}
|
|
66382
|
-
}
|
|
66383
|
-
}
|
|
66384
|
-
getFlagStemSize(duration, forceMinStem = false) {
|
|
66385
|
-
let size = 0;
|
|
66386
|
-
switch (duration) {
|
|
66387
|
-
case Duration.QuadrupleWhole:
|
|
66388
|
-
case Duration.Half:
|
|
66389
|
-
case Duration.Quarter:
|
|
66390
|
-
case Duration.Eighth:
|
|
66391
|
-
case Duration.Sixteenth:
|
|
66392
|
-
case Duration.ThirtySecond:
|
|
66393
|
-
case Duration.SixtyFourth:
|
|
66394
|
-
case Duration.OneHundredTwentyEighth:
|
|
66395
|
-
case Duration.TwoHundredFiftySixth:
|
|
66396
|
-
size = this.smuflMetrics.standardStemLength + this.smuflMetrics.stemFlagOffsets.get(duration);
|
|
66397
66729
|
break;
|
|
66398
|
-
|
|
66399
|
-
|
|
66730
|
+
case BeamDirection.Down:
|
|
66731
|
+
if (startNote.realValue < this.startNote.realValue) {
|
|
66732
|
+
this.startNote = startNote;
|
|
66733
|
+
}
|
|
66734
|
+
if (endNote.realValue < this.endNote.realValue) {
|
|
66735
|
+
this.endNote = endNote;
|
|
66736
|
+
}
|
|
66400
66737
|
break;
|
|
66401
66738
|
}
|
|
66402
|
-
return
|
|
66403
|
-
}
|
|
66404
|
-
recreatePreBeatGlyphs() {
|
|
66405
|
-
this._startSpacing = false;
|
|
66406
|
-
super.recreatePreBeatGlyphs();
|
|
66407
|
-
}
|
|
66408
|
-
calculateBeamY(h, x) {
|
|
66409
|
-
return this.calculateBeamYWithDirection(h, x, this.getBeamDirection(h));
|
|
66410
|
-
}
|
|
66411
|
-
createPreBeatGlyphs() {
|
|
66412
|
-
super.createPreBeatGlyphs();
|
|
66413
|
-
this.addPreBeatGlyph(new BarLineGlyph(false, this.bar.staff.track.score.stylesheet.extendBarLines));
|
|
66414
|
-
this.createLinePreBeatGlyphs();
|
|
66415
|
-
this.addPreBeatGlyph(new BarNumberGlyph(0, this.getLineHeight(-0.5), this.bar.index + 1));
|
|
66739
|
+
return true;
|
|
66416
66740
|
}
|
|
66417
|
-
|
|
66418
|
-
|
|
66419
|
-
|
|
66420
|
-
|
|
66421
|
-
|
|
66422
|
-
|
|
66423
|
-
|
|
66741
|
+
}
|
|
66742
|
+
|
|
66743
|
+
/**
|
|
66744
|
+
* @internal
|
|
66745
|
+
*/
|
|
66746
|
+
class NumberedSlurGlyph extends TabSlurGlyph {
|
|
66747
|
+
calculateTieDirection() {
|
|
66748
|
+
return BeamDirection.Up;
|
|
66424
66749
|
}
|
|
66425
|
-
|
|
66426
|
-
|
|
66427
|
-
|
|
66428
|
-
|
|
66429
|
-
|
|
66430
|
-
|
|
66431
|
-
|
|
66432
|
-
|
|
66433
|
-
|
|
66434
|
-
|
|
66435
|
-
|
|
66436
|
-
|
|
66437
|
-
|
|
66438
|
-
|
|
66439
|
-
}
|
|
66440
|
-
const beatLineX = this.getBeatX(beat, BeatXPosition.Stem);
|
|
66441
|
-
const y1 = cy + this.y + this.getBarLineStart(beat, direction);
|
|
66442
|
-
// ensure we are pixel aligned on the end of the stem to avoid anti-aliasing artifacts
|
|
66443
|
-
// when combining stems and beams on sub-pixel level
|
|
66444
|
-
const y2 = (cy + this.y + this.calculateBeamY(h, beatLineX)) | 0;
|
|
66445
|
-
if (y1 < y2) {
|
|
66446
|
-
this.paintBeamingStem(beat, cy + this.y, cx + this.x + beatLineX, y1, y2, canvas);
|
|
66447
|
-
}
|
|
66448
|
-
else {
|
|
66449
|
-
this.paintBeamingStem(beat, cy + this.y, cx + this.x + beatLineX, y2, y1, canvas);
|
|
66450
|
-
}
|
|
66451
|
-
const _ = ElementStyleHelper.beat(canvas, beamsElement, beat);
|
|
66452
|
-
try {
|
|
66453
|
-
const brokenBarOffset = this.smuflMetrics.brokenBeamWidth * scaleMod;
|
|
66454
|
-
const barCount = ModelUtils.getIndex(beat.duration) - 2;
|
|
66455
|
-
const barStart = cy + this.y;
|
|
66456
|
-
for (let barIndex = 0; barIndex < barCount; barIndex++) {
|
|
66457
|
-
let barStartX = 0;
|
|
66458
|
-
let barEndX = 0;
|
|
66459
|
-
let barStartY = 0;
|
|
66460
|
-
let barEndY = 0;
|
|
66461
|
-
const barY = barStart + barIndex * barSpacing;
|
|
66462
|
-
//
|
|
66463
|
-
// Bar to Next?
|
|
66464
|
-
//
|
|
66465
|
-
if (i < h.beats.length - 1) {
|
|
66466
|
-
const isFullBarJoin = BeamingHelper.isFullBarJoin(beat, h.beats[i + 1], barIndex);
|
|
66467
|
-
// force two broken bars on secondary (last) beam?
|
|
66468
|
-
if (barIndex === barCount - 1 &&
|
|
66469
|
-
isFullBarJoin &&
|
|
66470
|
-
beat.beamingMode === BeatBeamingMode.ForceSplitOnSecondaryToNext) {
|
|
66471
|
-
// start part
|
|
66472
|
-
barStartX = beatLineX;
|
|
66473
|
-
barEndX = barStartX + brokenBarOffset;
|
|
66474
|
-
barStartY = barY + this.calculateBeamY(h, barStartX);
|
|
66475
|
-
barEndY = barY + this.calculateBeamY(h, barEndX);
|
|
66476
|
-
LineBarRenderer.paintSingleBar(canvas, cx + this.x + barStartX, barStartY, cx + this.x + barEndX, barEndY, barSize);
|
|
66477
|
-
// end part
|
|
66478
|
-
barEndX = this.getBeatX(h.beats[i + 1], BeatXPosition.Stem);
|
|
66479
|
-
barStartX = barEndX - brokenBarOffset;
|
|
66480
|
-
barStartY = barY + this.calculateBeamY(h, barStartX);
|
|
66481
|
-
barEndY = barY + this.calculateBeamY(h, barEndX);
|
|
66482
|
-
LineBarRenderer.paintSingleBar(canvas, cx + this.x + barStartX, barStartY, cx + this.x + barEndX, barEndY, barSize);
|
|
66483
|
-
}
|
|
66484
|
-
else {
|
|
66485
|
-
if (isFullBarJoin) {
|
|
66486
|
-
// full bar?
|
|
66487
|
-
barStartX = beatLineX;
|
|
66488
|
-
barEndX = this.getBeatX(h.beats[i + 1], BeatXPosition.Stem);
|
|
66489
|
-
}
|
|
66490
|
-
else if (i === 0 || !BeamingHelper.isFullBarJoin(h.beats[i - 1], beat, barIndex)) {
|
|
66491
|
-
barStartX = beatLineX;
|
|
66492
|
-
barEndX = barStartX + brokenBarOffset;
|
|
66493
|
-
}
|
|
66494
|
-
else {
|
|
66495
|
-
continue;
|
|
66496
|
-
}
|
|
66497
|
-
barStartY = barY + this.calculateBeamY(h, barStartX);
|
|
66498
|
-
barEndY = barY + this.calculateBeamY(h, barEndX);
|
|
66499
|
-
// ensure we are pixel aligned on the end of the stem to avoid anti-aliasing artifacts
|
|
66500
|
-
// when combining stems and beams on sub-pixel level
|
|
66501
|
-
if (barIndex === 0) {
|
|
66502
|
-
barStartY = barStartY | 0;
|
|
66503
|
-
barEndY = barEndY | 0;
|
|
66504
|
-
}
|
|
66505
|
-
LineBarRenderer.paintSingleBar(canvas, cx + this.x + barStartX, barStartY, cx + this.x + barEndX, barEndY, barSize);
|
|
66506
|
-
}
|
|
66507
|
-
}
|
|
66508
|
-
else if (i > 0 && !BeamingHelper.isFullBarJoin(beat, h.beats[i - 1], barIndex)) {
|
|
66509
|
-
barStartX = beatLineX - brokenBarOffset;
|
|
66510
|
-
barEndX = beatLineX;
|
|
66511
|
-
barEndX = beatLineX;
|
|
66512
|
-
barStartY = barY + this.calculateBeamY(h, barStartX);
|
|
66513
|
-
barEndY = barY + this.calculateBeamY(h, barEndX);
|
|
66514
|
-
LineBarRenderer.paintSingleBar(canvas, cx + this.x + barStartX, barStartY, cx + this.x + barEndX, barEndY, barSize);
|
|
66515
|
-
}
|
|
66516
|
-
}
|
|
66517
|
-
}
|
|
66518
|
-
finally {
|
|
66519
|
-
_?.[Symbol.dispose]?.();
|
|
66520
|
-
}
|
|
66750
|
+
}
|
|
66751
|
+
|
|
66752
|
+
/**
|
|
66753
|
+
* @internal
|
|
66754
|
+
*/
|
|
66755
|
+
class NumberedBeatContainerGlyph extends BeatContainerGlyph {
|
|
66756
|
+
_slurs = new Map();
|
|
66757
|
+
_effectSlurs = [];
|
|
66758
|
+
_dashes;
|
|
66759
|
+
hasAdditionalNumbers = false;
|
|
66760
|
+
*iterateAdditionalNumbers() {
|
|
66761
|
+
const dashes = this._dashes;
|
|
66762
|
+
if (!dashes) {
|
|
66763
|
+
return;
|
|
66521
66764
|
}
|
|
66522
|
-
|
|
66523
|
-
|
|
66524
|
-
|
|
66525
|
-
let slashY = (cy + this.y + this.calculateBeamY(h, beatLineX)) | 0;
|
|
66526
|
-
slashY += barSize + barSpacing;
|
|
66527
|
-
if (direction === BeamDirection.Down) {
|
|
66528
|
-
CanvasHelper.fillMusicFontSymbolSafe(canvas, cx + this.x + beatLineX + flagWidth / 2, slashY, EngravingSettings.GraceScale, MusicFontSymbol.GraceNoteSlashStemDown, true);
|
|
66529
|
-
}
|
|
66530
|
-
else {
|
|
66531
|
-
CanvasHelper.fillMusicFontSymbolSafe(canvas, cx + this.x + beatLineX + flagWidth / 2, slashY, EngravingSettings.GraceScale, MusicFontSymbol.GraceNoteSlashStemUp, true);
|
|
66765
|
+
for (const d of dashes) {
|
|
66766
|
+
if (d instanceof NumberedNoteBeatContainerGlyphBase) {
|
|
66767
|
+
yield d;
|
|
66532
66768
|
}
|
|
66533
66769
|
}
|
|
66534
66770
|
}
|
|
66535
|
-
|
|
66536
|
-
|
|
66537
|
-
|
|
66538
|
-
|
|
66539
|
-
canvas.lineTo(x2, y2 + size);
|
|
66540
|
-
canvas.lineTo(x1, y1 + size);
|
|
66541
|
-
canvas.closePath();
|
|
66542
|
-
canvas.fill();
|
|
66771
|
+
constructor(beat) {
|
|
66772
|
+
super(beat);
|
|
66773
|
+
this.preNotes = new NumberedBeatPreNotesGlyph();
|
|
66774
|
+
this.onNotes = new NumberedBeatGlyph();
|
|
66543
66775
|
}
|
|
66544
|
-
|
|
66545
|
-
let
|
|
66546
|
-
|
|
66547
|
-
|
|
66548
|
-
|
|
66549
|
-
for (const h of v) {
|
|
66550
|
-
if (h.isRestBeamHelper) ;
|
|
66551
|
-
else if (h.beats.length === 1 && h.beats[0].duration >= Duration.Half) {
|
|
66552
|
-
if (h.direction === BeamDirection.Up) {
|
|
66553
|
-
let topY = this.getFlagTopY(h.beats[0], h.direction);
|
|
66554
|
-
if (h.hasTuplet) {
|
|
66555
|
-
topY -= this.tupletSize + this.tupletOffset;
|
|
66556
|
-
}
|
|
66557
|
-
if (topY < maxNoteY) {
|
|
66558
|
-
maxNoteY = topY;
|
|
66559
|
-
}
|
|
66560
|
-
}
|
|
66561
|
-
else {
|
|
66562
|
-
let bottomY = this.getFlagBottomY(h.beats[0], h.direction);
|
|
66563
|
-
if (h.hasTuplet) {
|
|
66564
|
-
bottomY += this.tupletSize + this.tupletOffset;
|
|
66565
|
-
}
|
|
66566
|
-
if (bottomY > minNoteY) {
|
|
66567
|
-
minNoteY = bottomY;
|
|
66568
|
-
}
|
|
66569
|
-
}
|
|
66570
|
-
}
|
|
66571
|
-
else {
|
|
66572
|
-
this.ensureBeamDrawingInfo(h, h.direction);
|
|
66573
|
-
const drawingInfo = h.drawingInfos.get(h.direction);
|
|
66574
|
-
if (h.direction === BeamDirection.Up) {
|
|
66575
|
-
let topY = Math.min(drawingInfo.startY, drawingInfo.endY);
|
|
66576
|
-
if (h.hasTuplet) {
|
|
66577
|
-
topY -= this.tupletSize + this.tupletOffset;
|
|
66578
|
-
}
|
|
66579
|
-
if (topY < maxNoteY) {
|
|
66580
|
-
maxNoteY = topY;
|
|
66581
|
-
}
|
|
66582
|
-
const bottomY = this.getBarLineStart(h.beatOfLowestNote, h.direction) + noteOverflowPadding;
|
|
66583
|
-
if (bottomY > minNoteY) {
|
|
66584
|
-
minNoteY = bottomY;
|
|
66585
|
-
}
|
|
66586
|
-
}
|
|
66587
|
-
else {
|
|
66588
|
-
let bottomY = Math.max(drawingInfo.startY, drawingInfo.endY);
|
|
66589
|
-
if (h.hasTuplet) {
|
|
66590
|
-
bottomY += this.tupletSize + this.tupletOffset;
|
|
66591
|
-
}
|
|
66592
|
-
if (bottomY > minNoteY) {
|
|
66593
|
-
minNoteY = bottomY;
|
|
66594
|
-
}
|
|
66595
|
-
const topY = this.getBarLineStart(h.beatOfHighestNote, h.direction) - noteOverflowPadding;
|
|
66596
|
-
if (topY < maxNoteY) {
|
|
66597
|
-
maxNoteY = topY;
|
|
66598
|
-
}
|
|
66599
|
-
}
|
|
66600
|
-
}
|
|
66601
|
-
}
|
|
66776
|
+
addDash(dash) {
|
|
66777
|
+
let dashes = this._dashes;
|
|
66778
|
+
if (!dashes) {
|
|
66779
|
+
dashes = [];
|
|
66780
|
+
this._dashes = dashes;
|
|
66602
66781
|
}
|
|
66603
|
-
|
|
66604
|
-
|
|
66782
|
+
dashes.push(dash);
|
|
66783
|
+
}
|
|
66784
|
+
addNotes(dash) {
|
|
66785
|
+
let dashes = this._dashes;
|
|
66786
|
+
if (!dashes) {
|
|
66787
|
+
dashes = [];
|
|
66788
|
+
this._dashes = dashes;
|
|
66605
66789
|
}
|
|
66606
|
-
|
|
66607
|
-
|
|
66790
|
+
dashes.push(dash);
|
|
66791
|
+
this.hasAdditionalNumbers = true;
|
|
66792
|
+
}
|
|
66793
|
+
doLayout() {
|
|
66794
|
+
this._slurs.clear();
|
|
66795
|
+
this._effectSlurs = [];
|
|
66796
|
+
super.doLayout();
|
|
66797
|
+
}
|
|
66798
|
+
buildBoundingsLookup(barBounds, cx, cy) {
|
|
66799
|
+
super.buildBoundingsLookup(barBounds, cx, cy);
|
|
66800
|
+
// extend bounds to include dashes
|
|
66801
|
+
const dashes = this._dashes;
|
|
66802
|
+
if (dashes) {
|
|
66803
|
+
const beatBounds = barBounds.beats[barBounds.beats.length - 1];
|
|
66804
|
+
const lastDash = dashes[dashes.length - 1];
|
|
66805
|
+
const visualEndX = lastDash.x + lastDash.contentWidth;
|
|
66806
|
+
beatBounds.visualBounds.w = visualEndX - beatBounds.visualBounds.x;
|
|
66807
|
+
const realEnd = lastDash.x + lastDash.width;
|
|
66808
|
+
beatBounds.realBounds.w = realEnd - beatBounds.realBounds.x;
|
|
66608
66809
|
}
|
|
66609
66810
|
}
|
|
66610
|
-
|
|
66611
|
-
if
|
|
66811
|
+
createTies(n) {
|
|
66812
|
+
// create a tie if any effect requires it
|
|
66813
|
+
if (!n.isVisible) {
|
|
66612
66814
|
return;
|
|
66613
66815
|
}
|
|
66614
|
-
|
|
66615
|
-
|
|
66616
|
-
|
|
66617
|
-
|
|
66618
|
-
// the beaming logic works like this:
|
|
66619
|
-
// 1. we take the first and last note, add the stem, and put a diagnal line between them.
|
|
66620
|
-
// 2. the height of the diagonal line must not exceed a max height,
|
|
66621
|
-
// - if this is the case, the line on the more distant note just gets longer
|
|
66622
|
-
// 3. any middle elements (notes or rests) shift this diagonal line up/down to avoid overlaps
|
|
66623
|
-
const firstBeat = h.beats[0];
|
|
66624
|
-
const lastBeat = h.beats[h.beats.length - 1];
|
|
66625
|
-
const isRest = h.isRestBeamHelper;
|
|
66626
|
-
// 1. put direct diagonal line.
|
|
66627
|
-
drawingInfo.startBeat = firstBeat;
|
|
66628
|
-
drawingInfo.startX = this.getBeatX(firstBeat, BeatXPosition.Stem);
|
|
66629
|
-
drawingInfo.startY =
|
|
66630
|
-
direction === BeamDirection.Up
|
|
66631
|
-
? this.getFlagTopY(firstBeat, direction)
|
|
66632
|
-
: this.getFlagBottomY(firstBeat, direction);
|
|
66633
|
-
drawingInfo.endBeat = lastBeat;
|
|
66634
|
-
drawingInfo.endX = this.getBeatX(lastBeat, BeatXPosition.Stem);
|
|
66635
|
-
drawingInfo.endY =
|
|
66636
|
-
direction === BeamDirection.Up
|
|
66637
|
-
? this.getFlagTopY(lastBeat, direction)
|
|
66638
|
-
: this.getFlagBottomY(lastBeat, direction);
|
|
66639
|
-
// 2. ensure max slope
|
|
66640
|
-
// we use the min/max notes to place the beam along their real position
|
|
66641
|
-
// we only want a maximum of 10 offset for their gradient
|
|
66642
|
-
const maxSlope = this.smuflMetrics.oneStaffSpace;
|
|
66643
|
-
if (direction === BeamDirection.Down &&
|
|
66644
|
-
drawingInfo.startY > drawingInfo.endY &&
|
|
66645
|
-
drawingInfo.startY - drawingInfo.endY > maxSlope) {
|
|
66646
|
-
drawingInfo.endY = drawingInfo.startY - maxSlope;
|
|
66647
|
-
}
|
|
66648
|
-
if (direction === BeamDirection.Down &&
|
|
66649
|
-
drawingInfo.endY > drawingInfo.startY &&
|
|
66650
|
-
drawingInfo.endY - drawingInfo.startY > maxSlope) {
|
|
66651
|
-
drawingInfo.startY = drawingInfo.endY - maxSlope;
|
|
66816
|
+
if (n.isTieOrigin && n.tieDestination.isVisible && !this._slurs.has('numbered.tie')) {
|
|
66817
|
+
const tie = new NumberedTieGlyph(`numbered.tie.${n.beat.id}`, n, n.tieDestination, false);
|
|
66818
|
+
this.addTie(tie);
|
|
66819
|
+
this._slurs.set(tie.slurEffectId, tie);
|
|
66652
66820
|
}
|
|
66653
|
-
if (
|
|
66654
|
-
|
|
66655
|
-
|
|
66656
|
-
drawingInfo.endY = drawingInfo.startY + maxSlope;
|
|
66821
|
+
if (n.isTieDestination) {
|
|
66822
|
+
const tie = new NumberedTieGlyph(`numbered.tie.${n.tieOrigin.beat.id}`, n.tieOrigin, n, true);
|
|
66823
|
+
this.addTie(tie);
|
|
66657
66824
|
}
|
|
66658
|
-
if (
|
|
66659
|
-
|
|
66660
|
-
|
|
66661
|
-
|
|
66825
|
+
if (n.isLeftHandTapped &&
|
|
66826
|
+
!n.isHammerPullDestination &&
|
|
66827
|
+
!this._slurs.has(`numbered.tie.leftHandTap.${n.beat.id}`)) {
|
|
66828
|
+
const tapSlur = new NumberedTieGlyph(`numbered.tie.leftHandTap.${n.beat.id}`, n, n, false);
|
|
66829
|
+
this.addTie(tapSlur);
|
|
66830
|
+
this._slurs.set(tapSlur.slurEffectId, tapSlur);
|
|
66662
66831
|
}
|
|
66663
|
-
//
|
|
66664
|
-
|
|
66665
|
-
|
|
66666
|
-
|
|
66667
|
-
|
|
66668
|
-
|
|
66669
|
-
|
|
66670
|
-
const totalBarsHeight = barCount * beamThickness + (barCount - 1) * beamSpacing;
|
|
66671
|
-
if (direction === BeamDirection.Up) {
|
|
66672
|
-
const bottomBarY = drawingInfo.startY + 2 * beamThickness + beamSpacing;
|
|
66673
|
-
const barTopY = bottomBarY - totalBarsHeight;
|
|
66674
|
-
const diff = drawingInfo.startY - barTopY;
|
|
66675
|
-
if (diff > 0) {
|
|
66676
|
-
barDrawingShift = diff * -1;
|
|
66677
|
-
drawingInfo.startY -= diff;
|
|
66678
|
-
drawingInfo.endY -= diff;
|
|
66832
|
+
// start effect slur on first beat
|
|
66833
|
+
if (n.isEffectSlurOrigin && n.effectSlurDestination) {
|
|
66834
|
+
let expanded = false;
|
|
66835
|
+
for (const slur of this._effectSlurs) {
|
|
66836
|
+
if (slur.tryExpand(n, n.effectSlurDestination, false, false)) {
|
|
66837
|
+
expanded = true;
|
|
66838
|
+
break;
|
|
66679
66839
|
}
|
|
66680
66840
|
}
|
|
66681
|
-
|
|
66682
|
-
const
|
|
66683
|
-
|
|
66684
|
-
|
|
66685
|
-
|
|
66686
|
-
|
|
66687
|
-
drawingInfo.startY += diff;
|
|
66688
|
-
drawingInfo.endY += diff;
|
|
66689
|
-
}
|
|
66841
|
+
if (!expanded) {
|
|
66842
|
+
const effectSlur = new NumberedSlurGlyph(`numbered.slur.effect`, n, n.effectSlurDestination, false, false);
|
|
66843
|
+
this._effectSlurs.push(effectSlur);
|
|
66844
|
+
this.addTie(effectSlur);
|
|
66845
|
+
this._slurs.set(effectSlur.slurEffectId, effectSlur);
|
|
66846
|
+
this._slurs.set('numbered.slur.effect', effectSlur);
|
|
66690
66847
|
}
|
|
66691
66848
|
}
|
|
66692
|
-
//
|
|
66693
|
-
if (
|
|
66694
|
-
|
|
66695
|
-
|
|
66696
|
-
|
|
66697
|
-
|
|
66698
|
-
|
|
66699
|
-
if (diff > 0) {
|
|
66700
|
-
drawingInfo.startY -= diff;
|
|
66701
|
-
drawingInfo.endY -= diff;
|
|
66702
|
-
}
|
|
66703
|
-
}
|
|
66704
|
-
else {
|
|
66705
|
-
const yNeededForLowestNote = barDrawingShift + this.getFlagBottomY(h.beatOfLowestNote, direction);
|
|
66706
|
-
const yGivenByCurrentValues = drawingInfo.calcY(this.getBeatX(h.beatOfLowestNote, BeatXPosition.Stem));
|
|
66707
|
-
const diff = yNeededForLowestNote - yGivenByCurrentValues;
|
|
66708
|
-
if (diff > 0) {
|
|
66709
|
-
drawingInfo.startY += diff;
|
|
66710
|
-
drawingInfo.endY += diff;
|
|
66849
|
+
// end effect slur on last beat
|
|
66850
|
+
if (n.isEffectSlurDestination && n.effectSlurOrigin) {
|
|
66851
|
+
let expanded = false;
|
|
66852
|
+
for (const slur of this._effectSlurs) {
|
|
66853
|
+
if (slur.tryExpand(n.effectSlurOrigin, n, false, true)) {
|
|
66854
|
+
expanded = true;
|
|
66855
|
+
break;
|
|
66711
66856
|
}
|
|
66712
66857
|
}
|
|
66713
|
-
|
|
66714
|
-
|
|
66715
|
-
|
|
66716
|
-
|
|
66717
|
-
|
|
66718
|
-
|
|
66719
|
-
}
|
|
66720
|
-
for (const b of h.restBeats) {
|
|
66721
|
-
// rest beats which are "under" the beam
|
|
66722
|
-
if (b.isRest && b.index < h.beats[h.beats.length - 1].index) {
|
|
66723
|
-
if (direction === BeamDirection.Up) {
|
|
66724
|
-
const yNeededForRest = this.getBeatContainer(b).getBoundingBoxTop() - barSpacing;
|
|
66725
|
-
const yGivenByCurrentValues = drawingInfo.calcY(this.getBeatX(b, BeatXPosition.Stem));
|
|
66726
|
-
const diff = yGivenByCurrentValues - yNeededForRest;
|
|
66727
|
-
if (diff > 0) {
|
|
66728
|
-
drawingInfo.startY -= diff;
|
|
66729
|
-
drawingInfo.endY -= diff;
|
|
66730
|
-
}
|
|
66731
|
-
}
|
|
66732
|
-
else if (direction === BeamDirection.Down) {
|
|
66733
|
-
const yNeededForRest = this.getBeatContainer(b).getBoundingBoxBottom() + barSpacing;
|
|
66734
|
-
const yGivenByCurrentValues = drawingInfo.calcY(this.getBeatX(b, BeatXPosition.Stem));
|
|
66735
|
-
const diff = yNeededForRest - yGivenByCurrentValues;
|
|
66736
|
-
if (diff > 0) {
|
|
66737
|
-
drawingInfo.startY += diff;
|
|
66738
|
-
drawingInfo.endY += diff;
|
|
66739
|
-
}
|
|
66740
|
-
}
|
|
66741
|
-
}
|
|
66742
|
-
}
|
|
66743
|
-
// check if slash shifts bar up or down
|
|
66744
|
-
if (h.slashBeats.length > 0) {
|
|
66745
|
-
for (const b of h.slashBeats) {
|
|
66746
|
-
const yGivenByCurrentValues = drawingInfo.calcY(this.getBeatX(b, BeatXPosition.Stem));
|
|
66747
|
-
const yNeededForSlash = h.direction === BeamDirection.Up
|
|
66748
|
-
? this.getFlagTopY(b, h.direction)
|
|
66749
|
-
: this.getFlagBottomY(b, h.direction);
|
|
66750
|
-
const diff = yNeededForSlash - yGivenByCurrentValues;
|
|
66751
|
-
if (diff > 0) {
|
|
66752
|
-
drawingInfo.startY += diff;
|
|
66753
|
-
drawingInfo.endY += diff;
|
|
66754
|
-
}
|
|
66755
|
-
}
|
|
66858
|
+
if (!expanded) {
|
|
66859
|
+
const effectSlur = new NumberedSlurGlyph(`numbered.slur.effect`, n.effectSlurOrigin, n, false, true);
|
|
66860
|
+
this._effectSlurs.push(effectSlur);
|
|
66861
|
+
this.addTie(effectSlur);
|
|
66862
|
+
this._slurs.set(effectSlur.slurEffectId, effectSlur);
|
|
66863
|
+
this._slurs.set('numbered.slur.effect', effectSlur);
|
|
66756
66864
|
}
|
|
66757
66865
|
}
|
|
66758
66866
|
}
|
|
66759
|
-
getMinLineOfBeat(_beat) {
|
|
66760
|
-
return 0;
|
|
66761
|
-
}
|
|
66762
|
-
getMaxLineOfBeat(_beat) {
|
|
66763
|
-
return 0;
|
|
66764
|
-
}
|
|
66765
|
-
}
|
|
66766
|
-
|
|
66767
|
-
/**
|
|
66768
|
-
* @internal
|
|
66769
|
-
*/
|
|
66770
|
-
class NumberedTieGlyph extends NoteTieGlyph {
|
|
66771
|
-
shouldDrawBendSlur() {
|
|
66772
|
-
return (this.renderer.settings.notation.extendBendArrowsOnTiedNotes &&
|
|
66773
|
-
!!this.startNote.bendOrigin &&
|
|
66774
|
-
this.startNote.isTieOrigin);
|
|
66775
|
-
}
|
|
66776
|
-
calculateTieDirection() {
|
|
66777
|
-
return BeamDirection.Up;
|
|
66778
|
-
}
|
|
66779
66867
|
}
|
|
66780
66868
|
|
|
66781
66869
|
/**
|
|
66782
66870
|
* @internal
|
|
66783
66871
|
*/
|
|
66784
|
-
class
|
|
66785
|
-
|
|
66786
|
-
|
|
66872
|
+
class NumberedNoteBeatContainerGlyphBase extends NumberedBeatContainerGlyph {
|
|
66873
|
+
_absoluteDisplayStart;
|
|
66874
|
+
_displayDuration;
|
|
66875
|
+
constructor(beat, absoluteDisplayStart, displayDuration) {
|
|
66876
|
+
super(beat);
|
|
66877
|
+
this._absoluteDisplayStart = absoluteDisplayStart;
|
|
66878
|
+
this._displayDuration = displayDuration;
|
|
66879
|
+
this.preNotes.skipLayout = true;
|
|
66880
|
+
this.barCount = NumberedNoteBeatContainerGlyphBase._ticksToBarCount(displayDuration);
|
|
66787
66881
|
}
|
|
66788
|
-
static
|
|
66789
|
-
|
|
66790
|
-
|
|
66791
|
-
|
|
66792
|
-
case AccidentalType.Sharp:
|
|
66793
|
-
return MusicFontSymbol.AccidentalSharp;
|
|
66794
|
-
case AccidentalType.Flat:
|
|
66795
|
-
return MusicFontSymbol.AccidentalFlat;
|
|
66796
|
-
case AccidentalType.NaturalQuarterNoteUp:
|
|
66797
|
-
return MusicFontSymbol.AccidentalQuarterToneSharpNaturalArrowUp;
|
|
66798
|
-
case AccidentalType.SharpQuarterNoteUp:
|
|
66799
|
-
return MusicFontSymbol.AccidentalThreeQuarterTonesSharpArrowUp;
|
|
66800
|
-
case AccidentalType.FlatQuarterNoteUp:
|
|
66801
|
-
return MusicFontSymbol.AccidentalQuarterToneFlatArrowUp;
|
|
66802
|
-
case AccidentalType.DoubleSharp:
|
|
66803
|
-
return MusicFontSymbol.AccidentalDoubleSharp;
|
|
66804
|
-
case AccidentalType.DoubleFlat:
|
|
66805
|
-
return MusicFontSymbol.AccidentalDoubleFlat;
|
|
66882
|
+
static _ticksToBarCount(displayDuration) {
|
|
66883
|
+
// we know that displayDuration < MidiUtils.QuarterTime, otherwise this glyph is not created
|
|
66884
|
+
if (displayDuration >= MidiUtils.toTicks(Duration.Eighth)) {
|
|
66885
|
+
return 1;
|
|
66806
66886
|
}
|
|
66807
|
-
|
|
66808
|
-
|
|
66809
|
-
}
|
|
66810
|
-
|
|
66811
|
-
/**
|
|
66812
|
-
* @internal
|
|
66813
|
-
*/
|
|
66814
|
-
class AccidentalColumnInfo {
|
|
66815
|
-
x = 0;
|
|
66816
|
-
y = -3e3;
|
|
66817
|
-
width = 0;
|
|
66818
|
-
}
|
|
66819
|
-
/**
|
|
66820
|
-
* @internal
|
|
66821
|
-
*/
|
|
66822
|
-
class AccidentalGroupGlyph extends GlyphGroup {
|
|
66823
|
-
constructor() {
|
|
66824
|
-
super(0, 0);
|
|
66825
|
-
}
|
|
66826
|
-
doLayout() {
|
|
66827
|
-
if (!this.glyphs || this.glyphs.length === 0) {
|
|
66828
|
-
this.width = 0;
|
|
66829
|
-
return;
|
|
66887
|
+
else if (displayDuration >= MidiUtils.toTicks(Duration.Sixteenth)) {
|
|
66888
|
+
return 2;
|
|
66830
66889
|
}
|
|
66831
|
-
|
|
66832
|
-
|
|
66833
|
-
//
|
|
66834
|
-
this.glyphs.sort((a, b) => {
|
|
66835
|
-
if (a.y < b.y) {
|
|
66836
|
-
return -1;
|
|
66837
|
-
}
|
|
66838
|
-
if (a.y > b.y) {
|
|
66839
|
-
return 1;
|
|
66840
|
-
}
|
|
66841
|
-
return 0;
|
|
66842
|
-
});
|
|
66843
|
-
// defines the reserved y position of the columns
|
|
66844
|
-
const columns = [];
|
|
66845
|
-
columns.push(new AccidentalColumnInfo());
|
|
66846
|
-
for (let i = 0, j = this.glyphs.length; i < j; i++) {
|
|
66847
|
-
const g = this.glyphs[i];
|
|
66848
|
-
g.renderer = this.renderer;
|
|
66849
|
-
g.doLayout();
|
|
66850
|
-
// find column where glyph fits into
|
|
66851
|
-
// as long the glyph does not fit into the current column
|
|
66852
|
-
let gColumn = 0;
|
|
66853
|
-
while (columns[gColumn].y > g.y) {
|
|
66854
|
-
// move to next column
|
|
66855
|
-
gColumn++;
|
|
66856
|
-
// and create the new column if needed
|
|
66857
|
-
if (gColumn === columns.length) {
|
|
66858
|
-
columns.push(new AccidentalColumnInfo());
|
|
66859
|
-
}
|
|
66860
|
-
}
|
|
66861
|
-
// temporary save column as X
|
|
66862
|
-
g.x = gColumn;
|
|
66863
|
-
columns[gColumn].y = g.y + g.height;
|
|
66864
|
-
if (columns[gColumn].width < g.width) {
|
|
66865
|
-
columns[gColumn].width = g.width;
|
|
66866
|
-
}
|
|
66890
|
+
else if (displayDuration >= MidiUtils.toTicks(Duration.ThirtySecond)) {
|
|
66891
|
+
return 3;
|
|
66867
66892
|
}
|
|
66868
|
-
|
|
66869
|
-
|
|
66870
|
-
//
|
|
66871
|
-
this.width = 0;
|
|
66872
|
-
const padding = this.renderer.smuflMetrics.accidentalPadding;
|
|
66873
|
-
for (const column of columns) {
|
|
66874
|
-
this.width += column.width + padding;
|
|
66875
|
-
column.x = this.width;
|
|
66893
|
+
else if (displayDuration >= MidiUtils.toTicks(Duration.SixtyFourth)) {
|
|
66894
|
+
return 4;
|
|
66876
66895
|
}
|
|
66877
|
-
|
|
66878
|
-
|
|
66879
|
-
const column = columns[g.x];
|
|
66880
|
-
g.x = this.width - column.x;
|
|
66896
|
+
else if (displayDuration >= MidiUtils.toTicks(Duration.OneHundredTwentyEighth)) {
|
|
66897
|
+
return 5;
|
|
66881
66898
|
}
|
|
66899
|
+
else if (displayDuration >= MidiUtils.toTicks(Duration.TwoHundredFiftySixth)) {
|
|
66900
|
+
return 6;
|
|
66901
|
+
}
|
|
66902
|
+
return 0;
|
|
66882
66903
|
}
|
|
66883
|
-
|
|
66884
|
-
|
|
66885
|
-
|
|
66886
|
-
* @internal
|
|
66887
|
-
*/
|
|
66888
|
-
class AugmentationDotGlyph extends MusicFontGlyph {
|
|
66889
|
-
constructor(x, y) {
|
|
66890
|
-
super(x, y, 1, MusicFontSymbol.AugmentationDot);
|
|
66904
|
+
barCount;
|
|
66905
|
+
get beatId() {
|
|
66906
|
+
return -1;
|
|
66891
66907
|
}
|
|
66892
|
-
|
|
66893
|
-
|
|
66894
|
-
this.offsetX = this.width / 2;
|
|
66895
|
-
this.width *= 1.5;
|
|
66908
|
+
get contentWidth() {
|
|
66909
|
+
return this.onNotes.width;
|
|
66896
66910
|
}
|
|
66897
|
-
|
|
66898
|
-
|
|
66899
|
-
/**
|
|
66900
|
-
* @internal
|
|
66901
|
-
*/
|
|
66902
|
-
class BeatGlyphBase extends GlyphGroup {
|
|
66903
|
-
_effectGlyphs = [];
|
|
66904
|
-
_normalGlyphs = [];
|
|
66905
|
-
container;
|
|
66906
|
-
computedWidth = 0;
|
|
66907
|
-
constructor() {
|
|
66908
|
-
super(0, 0);
|
|
66911
|
+
get absoluteDisplayStart() {
|
|
66912
|
+
return this._absoluteDisplayStart;
|
|
66909
66913
|
}
|
|
66910
|
-
|
|
66911
|
-
|
|
66912
|
-
let w = 0;
|
|
66913
|
-
if (this.glyphs) {
|
|
66914
|
-
for (let i = 0, j = this.glyphs.length; i < j; i++) {
|
|
66915
|
-
const g = this.glyphs[i];
|
|
66916
|
-
g.x = w;
|
|
66917
|
-
g.renderer = this.renderer;
|
|
66918
|
-
g.doLayout();
|
|
66919
|
-
w += g.width;
|
|
66920
|
-
}
|
|
66921
|
-
}
|
|
66922
|
-
this.width = w;
|
|
66923
|
-
this.computedWidth = w;
|
|
66914
|
+
get displayDuration() {
|
|
66915
|
+
return this._displayDuration;
|
|
66924
66916
|
}
|
|
66925
|
-
|
|
66926
|
-
|
|
66927
|
-
action(this.container.beat.notes[i]);
|
|
66928
|
-
}
|
|
66917
|
+
get graceType() {
|
|
66918
|
+
return GraceType.None;
|
|
66929
66919
|
}
|
|
66930
|
-
|
|
66931
|
-
|
|
66932
|
-
this._effectGlyphs.push(g);
|
|
66920
|
+
get graceIndex() {
|
|
66921
|
+
return 0;
|
|
66933
66922
|
}
|
|
66934
|
-
|
|
66935
|
-
|
|
66936
|
-
this._normalGlyphs.push(g);
|
|
66923
|
+
get graceGroup() {
|
|
66924
|
+
return null;
|
|
66937
66925
|
}
|
|
66938
|
-
get
|
|
66939
|
-
return
|
|
66926
|
+
get isFirstOfTupletGroup() {
|
|
66927
|
+
return false;
|
|
66940
66928
|
}
|
|
66941
|
-
|
|
66942
|
-
|
|
66943
|
-
this._paintNormal(cx, cy, canvas);
|
|
66929
|
+
get tupletGroup() {
|
|
66930
|
+
return null;
|
|
66944
66931
|
}
|
|
66945
|
-
|
|
66946
|
-
|
|
66947
|
-
g.paint(cx + this.x, cy + this.y, canvas);
|
|
66948
|
-
}
|
|
66932
|
+
get isLastOfVoice() {
|
|
66933
|
+
return false;
|
|
66949
66934
|
}
|
|
66950
|
-
|
|
66951
|
-
const _ = this.effectElement
|
|
66952
|
-
? ElementStyleHelper.beat(canvas, this.effectElement, this.container.beat)
|
|
66953
|
-
: undefined;
|
|
66954
|
-
try {
|
|
66955
|
-
for (const g of this._effectGlyphs) {
|
|
66956
|
-
g.paint(cx + this.x, cy + this.y, canvas);
|
|
66957
|
-
}
|
|
66958
|
-
}
|
|
66959
|
-
finally {
|
|
66960
|
-
_?.[Symbol.dispose]?.();
|
|
66961
|
-
}
|
|
66935
|
+
buildBoundingsLookup(_barBounds, _cx, _cy) {
|
|
66962
66936
|
}
|
|
66963
66937
|
}
|
|
66964
|
-
|
|
66965
|
-
/**
|
|
66966
|
-
* @internal
|
|
66967
|
-
*/
|
|
66968
|
-
class BeatOnNoteGlyphBase extends BeatGlyphBase {
|
|
66969
|
-
onTimeX = 0;
|
|
66970
|
-
middleX = 0;
|
|
66971
|
-
stemX = 0;
|
|
66972
|
-
}
|
|
66973
|
-
|
|
66974
66938
|
/**
|
|
66975
66939
|
* @internal
|
|
66976
66940
|
*/
|
|
66977
|
-
class
|
|
66978
|
-
|
|
66941
|
+
class NumberedDashBeatContainerGlyph extends BeatContainerGlyphBase {
|
|
66942
|
+
_absoluteDisplayStart;
|
|
66943
|
+
_voiceIndex;
|
|
66944
|
+
constructor(voiceIndex, absoluteDisplayStart) {
|
|
66979
66945
|
super(0, 0);
|
|
66946
|
+
this._absoluteDisplayStart = absoluteDisplayStart;
|
|
66947
|
+
this._voiceIndex = voiceIndex;
|
|
66980
66948
|
}
|
|
66981
|
-
|
|
66982
|
-
|
|
66949
|
+
get beatId() {
|
|
66950
|
+
return -1;
|
|
66951
|
+
}
|
|
66952
|
+
get contentWidth() {
|
|
66953
|
+
return this.renderer.smuflMetrics.numberedDashGlyphWidth;
|
|
66954
|
+
}
|
|
66955
|
+
get absoluteDisplayStart() {
|
|
66956
|
+
return this._absoluteDisplayStart;
|
|
66957
|
+
}
|
|
66958
|
+
get displayDuration() {
|
|
66959
|
+
return MidiUtils.QuarterTime;
|
|
66960
|
+
}
|
|
66961
|
+
get onTimeX() {
|
|
66962
|
+
return this.renderer.smuflMetrics.numberedDashGlyphWidth / 2;
|
|
66963
|
+
}
|
|
66964
|
+
get graceType() {
|
|
66965
|
+
return GraceType.None;
|
|
66966
|
+
}
|
|
66967
|
+
get graceIndex() {
|
|
66968
|
+
return 0;
|
|
66969
|
+
}
|
|
66970
|
+
get graceGroup() {
|
|
66971
|
+
return null;
|
|
66972
|
+
}
|
|
66973
|
+
get voiceIndex() {
|
|
66974
|
+
return this._voiceIndex;
|
|
66975
|
+
}
|
|
66976
|
+
get isFirstOfTupletGroup() {
|
|
66977
|
+
return false;
|
|
66978
|
+
}
|
|
66979
|
+
get tupletGroup() {
|
|
66980
|
+
return null;
|
|
66981
|
+
}
|
|
66982
|
+
get isLastOfVoice() {
|
|
66983
|
+
return false;
|
|
66984
|
+
}
|
|
66985
|
+
getNoteY(_note, _requestedPosition) {
|
|
66986
|
+
return 0;
|
|
66987
|
+
}
|
|
66988
|
+
doMultiVoiceLayout() {
|
|
66989
|
+
}
|
|
66990
|
+
getRestY(_requestedPosition) {
|
|
66991
|
+
return 0;
|
|
66992
|
+
}
|
|
66993
|
+
getNoteX(_note, _requestedPosition) {
|
|
66994
|
+
return 0;
|
|
66995
|
+
}
|
|
66996
|
+
getBeatX(_requestedPosition, _useSharedSizes) {
|
|
66997
|
+
return 0;
|
|
66998
|
+
}
|
|
66999
|
+
registerLayoutingInfo(layoutings) {
|
|
67000
|
+
const width = this.renderer.smuflMetrics.numberedDashGlyphWidth;
|
|
67001
|
+
layoutings.addBeatSpring(this, width / 2, width / 2);
|
|
67002
|
+
}
|
|
67003
|
+
applyLayoutingInfo(_info) {
|
|
67004
|
+
}
|
|
67005
|
+
buildBoundingsLookup(_barBounds, _cx, _cy) {
|
|
66983
67006
|
}
|
|
66984
67007
|
paint(cx, cy, canvas) {
|
|
66985
67008
|
const renderer = this.renderer;
|
|
66986
|
-
const
|
|
66987
|
-
const
|
|
66988
|
-
const
|
|
66989
|
-
|
|
66990
|
-
const centerY = staffTop + staffHeight / 2 - crossHeight / 2;
|
|
66991
|
-
const lw = canvas.lineWidth;
|
|
66992
|
-
canvas.lineWidth = this.renderer.smuflMetrics.deadSlappedLineWidth;
|
|
66993
|
-
canvas.moveTo(cx + this.x, cy + centerY);
|
|
66994
|
-
canvas.lineTo(cx + this.x + this.width, cy + centerY + crossHeight);
|
|
66995
|
-
canvas.moveTo(cx + this.x, cy + centerY + crossHeight);
|
|
66996
|
-
canvas.lineTo(cx + this.x + this.width, cy + centerY);
|
|
66997
|
-
canvas.stroke();
|
|
66998
|
-
canvas.lineWidth = lw;
|
|
67009
|
+
const dashWidth = renderer.smuflMetrics.numberedDashGlyphWidth;
|
|
67010
|
+
const dashHeight = renderer.smuflMetrics.numberedBarRendererBarSize;
|
|
67011
|
+
const dashY = Math.ceil(cy + renderer.getLineY(0) - dashHeight);
|
|
67012
|
+
canvas.fillRect(cx + this.x, dashY, dashWidth, dashHeight);
|
|
66999
67013
|
}
|
|
67000
67014
|
}
|
|
67001
67015
|
|
|
67002
67016
|
/**
|
|
67003
67017
|
* @internal
|
|
67004
67018
|
*/
|
|
67005
|
-
class
|
|
67006
|
-
|
|
67007
|
-
|
|
67008
|
-
|
|
67009
|
-
|
|
67019
|
+
class GhostParenthesisGlyph extends Glyph {
|
|
67020
|
+
_isOpen;
|
|
67021
|
+
colorOverride;
|
|
67022
|
+
constructor(isOpen) {
|
|
67023
|
+
super(0, 0);
|
|
67024
|
+
this._isOpen = isOpen;
|
|
67010
67025
|
}
|
|
67011
67026
|
doLayout() {
|
|
67027
|
+
super.doLayout();
|
|
67012
67028
|
this.width =
|
|
67013
|
-
this.renderer.smuflMetrics.
|
|
67014
|
-
this.height = this.renderer.smuflMetrics.numberedBarRendererBarSize;
|
|
67029
|
+
this.renderer.smuflMetrics.ghostParenthesisWidth + this.renderer.smuflMetrics.ghostParenthesisPadding;
|
|
67015
67030
|
}
|
|
67016
67031
|
paint(cx, cy, canvas) {
|
|
67017
|
-
const
|
|
67018
|
-
|
|
67019
|
-
|
|
67020
|
-
canvas.fillRect(cx + this.x, Math.ceil(cy + this.y - this.height), this.width - padding, this.height);
|
|
67032
|
+
const c = canvas.color;
|
|
67033
|
+
if (this.colorOverride) {
|
|
67034
|
+
canvas.color = this.colorOverride;
|
|
67021
67035
|
}
|
|
67022
|
-
|
|
67023
|
-
|
|
67036
|
+
if (this._isOpen) {
|
|
67037
|
+
TieGlyph.paintTie(canvas, 1, cx + this.x + this.renderer.smuflMetrics.ghostParenthesisWidth, cy + this.y + this.height, cx + this.x + this.renderer.smuflMetrics.ghostParenthesisWidth, cy + this.y, false, this.renderer.smuflMetrics.ghostParenthesisWidth / 2, this.renderer.smuflMetrics.tieMidpointThickness);
|
|
67024
67038
|
}
|
|
67039
|
+
else {
|
|
67040
|
+
TieGlyph.paintTie(canvas, 1, cx + this.x + this.renderer.smuflMetrics.ghostParenthesisPadding, cy + this.y, cx + this.x + this.renderer.smuflMetrics.ghostParenthesisPadding, cy + this.y + this.height, false, this.renderer.smuflMetrics.ghostParenthesisWidth / 2, this.renderer.smuflMetrics.tieMidpointThickness);
|
|
67041
|
+
}
|
|
67042
|
+
canvas.color = c;
|
|
67025
67043
|
}
|
|
67026
67044
|
}
|
|
67027
67045
|
|
|
67028
67046
|
/**
|
|
67029
67047
|
* @internal
|
|
67030
67048
|
*/
|
|
67031
|
-
class
|
|
67032
|
-
|
|
67033
|
-
|
|
67034
|
-
|
|
67035
|
-
|
|
67049
|
+
class TimeSignatureGlyph extends GlyphGroup {
|
|
67050
|
+
_numerator = 0;
|
|
67051
|
+
_denominator = 0;
|
|
67052
|
+
_isCommon;
|
|
67053
|
+
_isFreeTime;
|
|
67054
|
+
barSubElement = BarSubElement.StandardNotationTimeSignature;
|
|
67055
|
+
constructor(x, y, numerator, denominator, isCommon, isFreeTime) {
|
|
67036
67056
|
super(x, y);
|
|
67037
|
-
this.
|
|
67038
|
-
this.
|
|
67039
|
-
this.
|
|
67057
|
+
this._numerator = numerator;
|
|
67058
|
+
this._denominator = denominator;
|
|
67059
|
+
this._isCommon = isCommon;
|
|
67060
|
+
this._isFreeTime = isFreeTime;
|
|
67040
67061
|
}
|
|
67041
67062
|
paint(cx, cy, canvas) {
|
|
67042
|
-
const _ = this.
|
|
67043
|
-
? ElementStyleHelper.beat(canvas, BeatSubElement.NumberedRests, this._beat)
|
|
67044
|
-
: this._beat.notes.length > 0
|
|
67045
|
-
? ElementStyleHelper.note(canvas, NoteSubElement.NumberedNumber, this._beat.notes[0])
|
|
67046
|
-
: undefined;
|
|
67063
|
+
const _ = ElementStyleHelper.bar(canvas, this.barSubElement, this.renderer.bar);
|
|
67047
67064
|
try {
|
|
67048
|
-
|
|
67049
|
-
canvas.font = this._isGrace ? res.numberedNotationGraceFont : res.numberedNotationFont;
|
|
67050
|
-
canvas.textBaseline = TextBaseline.Middle;
|
|
67051
|
-
canvas.textAlign = TextAlign.Left;
|
|
67052
|
-
canvas.fillText(this._number.toString(), cx + this.x, cy + this.y);
|
|
67065
|
+
super.paint(cx, cy, canvas);
|
|
67053
67066
|
}
|
|
67054
67067
|
finally {
|
|
67055
67068
|
_?.[Symbol.dispose]?.();
|
|
67056
67069
|
}
|
|
67057
67070
|
}
|
|
67058
67071
|
doLayout() {
|
|
67059
|
-
|
|
67060
|
-
|
|
67061
|
-
|
|
67062
|
-
|
|
67063
|
-
|
|
67064
|
-
this.
|
|
67065
|
-
|
|
67072
|
+
if (this._isCommon && this._numerator === 2 && this._denominator === 2) {
|
|
67073
|
+
const common = new MusicFontGlyph(0, 0, this.commonScale, MusicFontSymbol.TimeSigCutCommon);
|
|
67074
|
+
this.addGlyph(common);
|
|
67075
|
+
super.doLayout();
|
|
67076
|
+
}
|
|
67077
|
+
else if (this._isCommon && this._numerator === 4 && this._denominator === 4) {
|
|
67078
|
+
const common = new MusicFontGlyph(0, 0, this.commonScale, MusicFontSymbol.TimeSigCommon);
|
|
67079
|
+
this.addGlyph(common);
|
|
67080
|
+
super.doLayout();
|
|
67081
|
+
}
|
|
67082
|
+
else {
|
|
67083
|
+
const numerator = new NumberGlyph(0, 0, this._numerator, TextBaseline.Top, this.numberScale);
|
|
67084
|
+
const denominator = new NumberGlyph(0, 0, this._denominator, TextBaseline.Bottom, this.numberScale);
|
|
67085
|
+
this.addGlyph(numerator);
|
|
67086
|
+
this.addGlyph(denominator);
|
|
67087
|
+
super.doLayout();
|
|
67088
|
+
const glyphSpace = this.width;
|
|
67089
|
+
numerator.x = (glyphSpace - numerator.width) / 2;
|
|
67090
|
+
denominator.x = (glyphSpace - denominator.width) / 2;
|
|
67091
|
+
this.width = Math.max(numerator.x + numerator.width, denominator.x + denominator.width);
|
|
67092
|
+
}
|
|
67093
|
+
if (this._isFreeTime) {
|
|
67094
|
+
const numberHeight = this.renderer.smuflMetrics.oneStaffSpace * 2;
|
|
67095
|
+
const openParenthesis = new GhostParenthesisGlyph(true);
|
|
67096
|
+
openParenthesis.renderer = this.renderer;
|
|
67097
|
+
openParenthesis.y = -numberHeight;
|
|
67098
|
+
openParenthesis.height = numberHeight * 2;
|
|
67099
|
+
openParenthesis.doLayout();
|
|
67100
|
+
for (const g of this.glyphs) {
|
|
67101
|
+
g.x += openParenthesis.width;
|
|
67102
|
+
}
|
|
67103
|
+
this.width += openParenthesis.width;
|
|
67104
|
+
this.addGlyph(openParenthesis);
|
|
67105
|
+
const closeParenthesis = new GhostParenthesisGlyph(false);
|
|
67106
|
+
closeParenthesis.renderer = this.renderer;
|
|
67107
|
+
closeParenthesis.x = this.width;
|
|
67108
|
+
closeParenthesis.y = -numberHeight;
|
|
67109
|
+
closeParenthesis.height = numberHeight * 2;
|
|
67110
|
+
closeParenthesis.doLayout();
|
|
67111
|
+
this.addGlyph(closeParenthesis);
|
|
67112
|
+
this.width += closeParenthesis.width;
|
|
67113
|
+
}
|
|
67066
67114
|
}
|
|
67067
67115
|
}
|
|
67068
67116
|
|
|
67069
67117
|
/**
|
|
67070
67118
|
* @internal
|
|
67071
67119
|
*/
|
|
67072
|
-
class
|
|
67073
|
-
|
|
67074
|
-
|
|
67075
|
-
get effectElement() {
|
|
67076
|
-
return BeatSubElement.NumberedEffects;
|
|
67120
|
+
class ScoreTimeSignatureGlyph extends TimeSignatureGlyph {
|
|
67121
|
+
get commonScale() {
|
|
67122
|
+
return 1;
|
|
67077
67123
|
}
|
|
67078
|
-
|
|
67079
|
-
|
|
67080
|
-
const accidentals = new AccidentalGroupGlyph();
|
|
67081
|
-
accidentals.renderer = this.renderer;
|
|
67082
|
-
if (this.container.beat.notes.length > 0) {
|
|
67083
|
-
const note = this.container.beat.notes[0];
|
|
67084
|
-
// Notes
|
|
67085
|
-
// - Compared to standard notation accidentals:
|
|
67086
|
-
// - Flat keysigs: When there is a naturalize symbol (against key signature, not naturalizing same line) we have a # in Numbered notation
|
|
67087
|
-
// - Flat keysigs: When there is a flat symbol standard notation we also have a flat in Numbered notation
|
|
67088
|
-
// - C keysig: A sharp on standard notation is a sharp on numbered notation
|
|
67089
|
-
// - # keysigs: When there is a # symbol on standard notation we also a sharp in numbered notation
|
|
67090
|
-
// - # keysigs: When there is a naturalize symbol (against key signature, not naturalizing same line) we have a flat in Numbered notation
|
|
67091
|
-
// Or generally:
|
|
67092
|
-
// - numbered notation has the same accidentals as standard notation if applied
|
|
67093
|
-
// - when the standard notation naturalizes the accidental from the key signature, the numbered notation has the reversed accidental
|
|
67094
|
-
const accidentalMode = note ? note.accidentalMode : NoteAccidentalMode.Default;
|
|
67095
|
-
const noteValue = AccidentalHelper.getNoteValue(note);
|
|
67096
|
-
let accidentalToSet = ModelUtils.computeAccidental(this.renderer.bar.keySignature, accidentalMode, noteValue, note.hasQuarterToneOffset);
|
|
67097
|
-
if (accidentalToSet === AccidentalType.Natural) {
|
|
67098
|
-
const ks = this.renderer.bar.keySignature;
|
|
67099
|
-
const ksi = ks + 7;
|
|
67100
|
-
const naturalizeAccidentalForKeySignature = ksi < 7 ? AccidentalType.Sharp : AccidentalType.Flat;
|
|
67101
|
-
accidentalToSet = naturalizeAccidentalForKeySignature;
|
|
67102
|
-
this.isNaturalizeAccidental = true;
|
|
67103
|
-
}
|
|
67104
|
-
// do we need an accidental on the note?
|
|
67105
|
-
if (accidentalToSet !== AccidentalType.None) {
|
|
67106
|
-
this.accidental = accidentalToSet;
|
|
67107
|
-
const sr = this.renderer;
|
|
67108
|
-
const color = ElementStyleHelper.noteColor(sr.resources, NoteSubElement.NumberedAccidentals, note);
|
|
67109
|
-
const g = new AccidentalGlyph(0, sr.getLineY(0), accidentalToSet, note.beat.graceType !== GraceType.None
|
|
67110
|
-
? EngravingSettings.GraceScale * EngravingSettings.GraceScale
|
|
67111
|
-
: EngravingSettings.GraceScale);
|
|
67112
|
-
g.colorOverride = color;
|
|
67113
|
-
g.renderer = this.renderer;
|
|
67114
|
-
accidentals.addGlyph(g);
|
|
67115
|
-
this.addNormal(accidentals);
|
|
67116
|
-
this.addNormal(new SpacingGlyph(0, 0, this.renderer.smuflMetrics.preNoteEffectPadding));
|
|
67117
|
-
}
|
|
67118
|
-
}
|
|
67119
|
-
}
|
|
67120
|
-
super.doLayout();
|
|
67124
|
+
get numberScale() {
|
|
67125
|
+
return 1;
|
|
67121
67126
|
}
|
|
67122
67127
|
}
|
|
67128
|
+
|
|
67123
67129
|
/**
|
|
67124
67130
|
* @internal
|
|
67125
67131
|
*/
|
|
67126
|
-
class
|
|
67127
|
-
|
|
67128
|
-
|
|
67129
|
-
octaveDots = 0;
|
|
67130
|
-
get effectElement() {
|
|
67131
|
-
return BeatSubElement.NumberedEffects;
|
|
67132
|
+
class FlagGlyph extends MusicFontGlyph {
|
|
67133
|
+
constructor(x, y, duration, direction, isGrace) {
|
|
67134
|
+
super(x, y, isGrace ? EngravingSettings.GraceScale : 1, FlagGlyph.getSymbol(duration, direction, isGrace));
|
|
67132
67135
|
}
|
|
67133
|
-
|
|
67134
|
-
|
|
67135
|
-
|
|
67136
|
-
g = this.noteHeads;
|
|
67137
|
-
}
|
|
67138
|
-
else if (this.deadSlapped) {
|
|
67139
|
-
g = this.deadSlapped;
|
|
67136
|
+
static getSymbol(duration, direction, isGrace) {
|
|
67137
|
+
if (isGrace) {
|
|
67138
|
+
duration = Duration.Eighth;
|
|
67140
67139
|
}
|
|
67141
|
-
if (
|
|
67142
|
-
|
|
67143
|
-
|
|
67144
|
-
|
|
67145
|
-
|
|
67146
|
-
|
|
67147
|
-
|
|
67148
|
-
|
|
67149
|
-
case
|
|
67150
|
-
|
|
67151
|
-
|
|
67140
|
+
if (direction === BeamDirection.Up) {
|
|
67141
|
+
switch (duration) {
|
|
67142
|
+
case Duration.Eighth:
|
|
67143
|
+
return MusicFontSymbol.Flag8thUp;
|
|
67144
|
+
case Duration.Sixteenth:
|
|
67145
|
+
return MusicFontSymbol.Flag16thUp;
|
|
67146
|
+
case Duration.ThirtySecond:
|
|
67147
|
+
return MusicFontSymbol.Flag32ndUp;
|
|
67148
|
+
case Duration.SixtyFourth:
|
|
67149
|
+
return MusicFontSymbol.Flag64thUp;
|
|
67150
|
+
case Duration.OneHundredTwentyEighth:
|
|
67151
|
+
return MusicFontSymbol.Flag128thUp;
|
|
67152
|
+
case Duration.TwoHundredFiftySixth:
|
|
67153
|
+
return MusicFontSymbol.Flag256thUp;
|
|
67154
|
+
default:
|
|
67155
|
+
return MusicFontSymbol.Flag8thUp;
|
|
67152
67156
|
}
|
|
67153
|
-
|
|
67154
|
-
|
|
67155
|
-
|
|
67156
|
-
|
|
67157
|
-
|
|
67158
|
-
|
|
67159
|
-
|
|
67160
|
-
|
|
67161
|
-
|
|
67162
|
-
|
|
67163
|
-
|
|
67164
|
-
|
|
67165
|
-
|
|
67166
|
-
|
|
67157
|
+
}
|
|
67158
|
+
switch (duration) {
|
|
67159
|
+
case Duration.Eighth:
|
|
67160
|
+
return MusicFontSymbol.Flag8thDown;
|
|
67161
|
+
case Duration.Sixteenth:
|
|
67162
|
+
return MusicFontSymbol.Flag16thDown;
|
|
67163
|
+
case Duration.ThirtySecond:
|
|
67164
|
+
return MusicFontSymbol.Flag32ndDown;
|
|
67165
|
+
case Duration.SixtyFourth:
|
|
67166
|
+
return MusicFontSymbol.Flag64thDown;
|
|
67167
|
+
case Duration.OneHundredTwentyEighth:
|
|
67168
|
+
return MusicFontSymbol.Flag128thDown;
|
|
67169
|
+
case Duration.TwoHundredFiftySixth:
|
|
67170
|
+
return MusicFontSymbol.Flag128thDown;
|
|
67171
|
+
default:
|
|
67172
|
+
return MusicFontSymbol.Flag8thDown;
|
|
67167
67173
|
}
|
|
67168
67174
|
}
|
|
67169
|
-
|
|
67170
|
-
|
|
67171
|
-
|
|
67172
|
-
|
|
67173
|
-
|
|
67174
|
-
|
|
67175
|
-
|
|
67176
|
-
|
|
67175
|
+
}
|
|
67176
|
+
|
|
67177
|
+
/**
|
|
67178
|
+
* @internal
|
|
67179
|
+
*/
|
|
67180
|
+
class RepeatCountGlyph extends Glyph {
|
|
67181
|
+
_count = 0;
|
|
67182
|
+
constructor(x, y, count) {
|
|
67183
|
+
super(x, y);
|
|
67184
|
+
this._count = 0;
|
|
67185
|
+
this._count = count;
|
|
67177
67186
|
}
|
|
67178
|
-
|
|
67179
|
-
|
|
67187
|
+
doLayout() {
|
|
67188
|
+
this.renderer.scoreRenderer.canvas.font = this.renderer.resources.barNumberFont;
|
|
67189
|
+
const size = this.renderer.scoreRenderer.canvas.measureText(`x${this._count}`);
|
|
67190
|
+
this.width = 0; // do not account width
|
|
67191
|
+
this.height = size.height;
|
|
67192
|
+
this.y -= size.height;
|
|
67180
67193
|
}
|
|
67181
|
-
|
|
67182
|
-
|
|
67183
|
-
|
|
67184
|
-
|
|
67185
|
-
|
|
67186
|
-
|
|
67187
|
-
|
|
67194
|
+
paint(cx, cy, canvas) {
|
|
67195
|
+
const _ = ElementStyleHelper.bar(canvas, this.renderer.repeatsBarSubElement, this.renderer.bar);
|
|
67196
|
+
try {
|
|
67197
|
+
const res = this.renderer.resources;
|
|
67198
|
+
const oldAlign = canvas.textAlign;
|
|
67199
|
+
canvas.font = res.barNumberFont;
|
|
67200
|
+
canvas.textAlign = TextAlign.Right;
|
|
67201
|
+
const s = `x${this._count}`;
|
|
67202
|
+
const w = canvas.measureText(s).width / 1.5;
|
|
67203
|
+
canvas.fillText(s, cx + this.x - w, cy + this.y);
|
|
67204
|
+
canvas.textAlign = oldAlign;
|
|
67188
67205
|
}
|
|
67189
|
-
|
|
67190
|
-
|
|
67191
|
-
switch (requestedPosition) {
|
|
67192
|
-
case NoteYPosition.Top:
|
|
67193
|
-
case NoteYPosition.TopWithStem:
|
|
67194
|
-
pos -= g.height / 2;
|
|
67195
|
-
break;
|
|
67196
|
-
case NoteYPosition.Center:
|
|
67197
|
-
break;
|
|
67198
|
-
case NoteYPosition.Bottom:
|
|
67199
|
-
case NoteYPosition.BottomWithStem:
|
|
67200
|
-
pos += g.height / 2;
|
|
67201
|
-
break;
|
|
67202
|
-
case NoteYPosition.StemUp:
|
|
67203
|
-
case NoteYPosition.StemDown:
|
|
67204
|
-
break;
|
|
67205
|
-
}
|
|
67206
|
-
return pos;
|
|
67206
|
+
finally {
|
|
67207
|
+
_?.[Symbol.dispose]?.();
|
|
67207
67208
|
}
|
|
67209
|
+
}
|
|
67210
|
+
}
|
|
67211
|
+
|
|
67212
|
+
/**
|
|
67213
|
+
* This is a base class for any bar renderer which renders music notation on a staff
|
|
67214
|
+
* with lines like Standard Notation, Guitar Tablatures and Slash Notation.
|
|
67215
|
+
*
|
|
67216
|
+
* This base class takes care of the typical bits like drawing lines,
|
|
67217
|
+
* allowing note positioning and creating glyphs like repeats, bar numbers etc..
|
|
67218
|
+
* @internal
|
|
67219
|
+
*/
|
|
67220
|
+
class LineBarRenderer extends BarRendererBase {
|
|
67221
|
+
firstLineY = 0;
|
|
67222
|
+
_startSpacing = false;
|
|
67223
|
+
tupletSize = 0;
|
|
67224
|
+
get lineOffset() {
|
|
67225
|
+
return this.lineSpacing;
|
|
67226
|
+
}
|
|
67227
|
+
get tupletOffset() {
|
|
67228
|
+
return this.smuflMetrics.oneStaffSpace * 0.5;
|
|
67229
|
+
}
|
|
67230
|
+
get topGlyphOverflow() {
|
|
67208
67231
|
return 0;
|
|
67209
67232
|
}
|
|
67210
|
-
|
|
67211
|
-
|
|
67212
|
-
|
|
67213
|
-
|
|
67214
|
-
|
|
67215
|
-
|
|
67216
|
-
|
|
67217
|
-
|
|
67218
|
-
|
|
67219
|
-
|
|
67220
|
-
|
|
67221
|
-
|
|
67222
|
-
|
|
67223
|
-
|
|
67224
|
-
|
|
67225
|
-
|
|
67233
|
+
get bottomGlyphOverflow() {
|
|
67234
|
+
return 0;
|
|
67235
|
+
}
|
|
67236
|
+
initLineBasedSizes() {
|
|
67237
|
+
this.height = this.lineOffset * (this.heightLineCount - 1);
|
|
67238
|
+
}
|
|
67239
|
+
updateSizes() {
|
|
67240
|
+
this.initLineBasedSizes();
|
|
67241
|
+
this.adjustSizes();
|
|
67242
|
+
this.updateFirstLineY();
|
|
67243
|
+
super.updateSizes();
|
|
67244
|
+
}
|
|
67245
|
+
adjustSizes() {
|
|
67246
|
+
}
|
|
67247
|
+
updateFirstLineY() {
|
|
67248
|
+
const fullLineHeight = this.lineOffset * (this.heightLineCount - 1);
|
|
67249
|
+
const actualLineHeight = this.drawnLineCount === 0 ? 0 : (this.drawnLineCount - 1) * this.lineOffset;
|
|
67250
|
+
const lineYOffset = this.smuflMetrics.staffLineThickness / 2;
|
|
67251
|
+
this.firstLineY = (((fullLineHeight - actualLineHeight) / 2) | 0) - lineYOffset;
|
|
67252
|
+
}
|
|
67226
67253
|
doLayout() {
|
|
67227
|
-
|
|
67228
|
-
|
|
67229
|
-
|
|
67230
|
-
|
|
67231
|
-
|
|
67232
|
-
|
|
67233
|
-
|
|
67234
|
-
|
|
67235
|
-
|
|
67236
|
-
|
|
67237
|
-
|
|
67238
|
-
|
|
67239
|
-
|
|
67240
|
-
|
|
67241
|
-
|
|
67242
|
-
|
|
67243
|
-
|
|
67244
|
-
|
|
67245
|
-
|
|
67254
|
+
this.initLineBasedSizes();
|
|
67255
|
+
this.updateFirstLineY();
|
|
67256
|
+
this.tupletSize = this.smuflMetrics.glyphHeights.get(MusicFontSymbol.Tuplet0);
|
|
67257
|
+
super.doLayout();
|
|
67258
|
+
}
|
|
67259
|
+
getLineY(line) {
|
|
67260
|
+
return this.firstLineY + this.getLineHeight(line);
|
|
67261
|
+
}
|
|
67262
|
+
getLineHeight(line) {
|
|
67263
|
+
return this.lineOffset * line;
|
|
67264
|
+
}
|
|
67265
|
+
paintContent(cx, cy, canvas) {
|
|
67266
|
+
super.paintContent(cx, cy, canvas);
|
|
67267
|
+
this.paintBeams(cx, cy, canvas, this.flagsSubElement, this.beamsSubElement);
|
|
67268
|
+
this.paintTuplets(cx, cy, canvas, this.tupletSubElement);
|
|
67269
|
+
}
|
|
67270
|
+
paintBackground(cx, cy, canvas) {
|
|
67271
|
+
super.paintBackground(cx, cy, canvas);
|
|
67272
|
+
// canvas.color = Color.random(100);
|
|
67273
|
+
// canvas.fillRect(cx + this.x, cy + this.y, this.width, this.height);
|
|
67274
|
+
//
|
|
67275
|
+
// draw string lines
|
|
67276
|
+
//
|
|
67277
|
+
this.paintStaffLines(cx, cy, canvas);
|
|
67278
|
+
this.paintSimileMark(cx, cy, canvas);
|
|
67279
|
+
}
|
|
67280
|
+
paintStaffLines(cx, cy, canvas) {
|
|
67281
|
+
const _ = ElementStyleHelper.bar(canvas, this.staffLineBarSubElement, this.bar, true);
|
|
67282
|
+
try {
|
|
67283
|
+
// collect tab note position for spaces
|
|
67284
|
+
const spaces = [];
|
|
67285
|
+
for (let i = 0, j = this.drawnLineCount; i < j; i++) {
|
|
67286
|
+
spaces.push([]);
|
|
67287
|
+
}
|
|
67288
|
+
// on multibar rest glyphs we don't have spaces as they are empty
|
|
67289
|
+
if (!this.additionalMultiRestBars) {
|
|
67290
|
+
this.collectSpaces(spaces);
|
|
67291
|
+
}
|
|
67292
|
+
// if we have multiple voices we need to sort by X-position, otherwise have a wild mix in the list
|
|
67293
|
+
// but painting relies on ascending X-position
|
|
67294
|
+
for (const line of spaces) {
|
|
67295
|
+
line.sort((a, b) => {
|
|
67296
|
+
return a[0] > b[0] ? 1 : a[0] < b[0] ? -1 : 0;
|
|
67297
|
+
});
|
|
67298
|
+
}
|
|
67299
|
+
// during system fitting it can happen that we have fraction widths
|
|
67300
|
+
// but to have lines until the full end-pixel we round up.
|
|
67301
|
+
// this way we avoid holes,
|
|
67302
|
+
const lineWidth = this.width;
|
|
67303
|
+
// we want the lines to be exactly virtually aligned with the respective Y-position
|
|
67304
|
+
// for note heads to align correctly
|
|
67305
|
+
const lineYOffset = this.smuflMetrics.staffLineThickness / 2;
|
|
67306
|
+
for (let i = 0; i < this.drawnLineCount; i++) {
|
|
67307
|
+
const lineY = this.getLineY(i) - lineYOffset;
|
|
67308
|
+
let lineX = 0;
|
|
67309
|
+
for (const line of spaces[i]) {
|
|
67310
|
+
canvas.fillRect(cx + this.x + lineX, cy + this.y + lineY, line[0] - lineX, this.smuflMetrics.staffLineThickness);
|
|
67311
|
+
lineX = line[0] + line[1];
|
|
67246
67312
|
}
|
|
67247
|
-
|
|
67248
|
-
|
|
67249
|
-
|
|
67250
|
-
|
|
67251
|
-
|
|
67252
|
-
|
|
67253
|
-
|
|
67254
|
-
|
|
67255
|
-
|
|
67256
|
-
|
|
67257
|
-
|
|
67258
|
-
|
|
67259
|
-
|
|
67260
|
-
|
|
67261
|
-
|
|
67262
|
-
|
|
67263
|
-
|
|
67264
|
-
|
|
67265
|
-
|
|
67266
|
-
|
|
67267
|
-
|
|
67268
|
-
|
|
67269
|
-
|
|
67270
|
-
numberWithinOctave = steps.toString();
|
|
67313
|
+
canvas.fillRect(cx + this.x + lineX, cy + this.y + lineY, lineWidth - lineX, this.smuflMetrics.staffLineThickness);
|
|
67314
|
+
}
|
|
67315
|
+
}
|
|
67316
|
+
finally {
|
|
67317
|
+
_?.[Symbol.dispose]?.();
|
|
67318
|
+
}
|
|
67319
|
+
}
|
|
67320
|
+
collectSpaces(_spaces) {
|
|
67321
|
+
}
|
|
67322
|
+
createStartSpacing() {
|
|
67323
|
+
if (this._startSpacing) {
|
|
67324
|
+
return;
|
|
67325
|
+
}
|
|
67326
|
+
const padding = this.index === 0 ? this.settings.display.firstStaffPaddingLeft : this.settings.display.staffPaddingLeft;
|
|
67327
|
+
this.addPreBeatGlyph(new SpacingGlyph(0, 0, padding));
|
|
67328
|
+
this._startSpacing = true;
|
|
67329
|
+
}
|
|
67330
|
+
paintTuplets(cx, cy, canvas, beatElement, bracketsAsArcs = false) {
|
|
67331
|
+
for (const v of this.voiceContainer.voiceDrawOrder) {
|
|
67332
|
+
if (this.voiceContainer.tupletGroups.has(v)) {
|
|
67333
|
+
const voice = this.voiceContainer.tupletGroups.get(v);
|
|
67334
|
+
for (const tupletGroup of voice) {
|
|
67335
|
+
this._paintTupletHelper(cx, cy, canvas, tupletGroup, beatElement, bracketsAsArcs);
|
|
67271
67336
|
}
|
|
67272
67337
|
}
|
|
67273
|
-
|
|
67274
|
-
|
|
67275
|
-
|
|
67276
|
-
|
|
67277
|
-
|
|
67278
|
-
|
|
67338
|
+
}
|
|
67339
|
+
}
|
|
67340
|
+
getTupletBeamDirection(helper) {
|
|
67341
|
+
return this.getBeamDirection(helper);
|
|
67342
|
+
}
|
|
67343
|
+
_paintTupletHelper(cx, cy, canvas, h, beatElement, bracketsAsArcs) {
|
|
67344
|
+
const res = this.resources;
|
|
67345
|
+
const oldAlign = canvas.textAlign;
|
|
67346
|
+
const oldBaseLine = canvas.textBaseline;
|
|
67347
|
+
canvas.color = h.voice.index === 0 ? this.resources.mainGlyphColor : this.resources.secondaryGlyphColor;
|
|
67348
|
+
canvas.textAlign = TextAlign.Center;
|
|
67349
|
+
canvas.textBaseline = TextBaseline.Middle;
|
|
67350
|
+
let s;
|
|
67351
|
+
const num = h.beats[0].tupletNumerator;
|
|
67352
|
+
const den = h.beats[0].tupletDenominator;
|
|
67353
|
+
// list as in Guitar Pro 7. for certain tuplets only the numerator is shown
|
|
67354
|
+
if (num === 2 && den === 3) {
|
|
67355
|
+
s = [MusicFontSymbol.Tuplet2];
|
|
67356
|
+
}
|
|
67357
|
+
else if (num === 3 && den === 2) {
|
|
67358
|
+
s = [MusicFontSymbol.Tuplet3];
|
|
67359
|
+
}
|
|
67360
|
+
else if (num === 4 && den === 6) {
|
|
67361
|
+
s = [MusicFontSymbol.Tuplet4];
|
|
67362
|
+
}
|
|
67363
|
+
else if (num === 5 && den === 4) {
|
|
67364
|
+
s = [MusicFontSymbol.Tuplet5];
|
|
67365
|
+
}
|
|
67366
|
+
else if (num === 6 && den === 4) {
|
|
67367
|
+
s = [MusicFontSymbol.Tuplet6];
|
|
67368
|
+
}
|
|
67369
|
+
else if (num === 7 && den === 4) {
|
|
67370
|
+
s = [MusicFontSymbol.Tuplet7];
|
|
67371
|
+
}
|
|
67372
|
+
else if (num === 9 && den === 8) {
|
|
67373
|
+
s = [MusicFontSymbol.Tuplet9];
|
|
67374
|
+
}
|
|
67375
|
+
else if (num === 10 && den === 8) {
|
|
67376
|
+
s = [MusicFontSymbol.Tuplet1, MusicFontSymbol.Tuplet0];
|
|
67377
|
+
}
|
|
67378
|
+
else if (num === 11 && den === 8) {
|
|
67379
|
+
s = [MusicFontSymbol.Tuplet1, MusicFontSymbol.Tuplet1];
|
|
67380
|
+
}
|
|
67381
|
+
else if (num === 12 && den === 8) {
|
|
67382
|
+
s = [MusicFontSymbol.Tuplet1, MusicFontSymbol.Tuplet2];
|
|
67383
|
+
}
|
|
67384
|
+
else if (num === 13 && den === 8) {
|
|
67385
|
+
s = [MusicFontSymbol.Tuplet1, MusicFontSymbol.Tuplet3];
|
|
67386
|
+
}
|
|
67387
|
+
else {
|
|
67388
|
+
s = [];
|
|
67389
|
+
const zero = MusicFontSymbol.Tuplet0;
|
|
67390
|
+
if (num > 10) {
|
|
67391
|
+
s.push((zero + Math.floor(num / 10)));
|
|
67392
|
+
s.push((zero + (num - 10)));
|
|
67279
67393
|
}
|
|
67280
67394
|
else {
|
|
67281
|
-
|
|
67282
|
-
const noteHeadGlyph = new NumberedNoteHeadGlyph(0, glyphY, numberWithinOctave, isGrace, this.container.beat);
|
|
67283
|
-
this.noteHeads = noteHeadGlyph;
|
|
67284
|
-
this.addNormal(noteHeadGlyph);
|
|
67395
|
+
s.push((zero + num));
|
|
67285
67396
|
}
|
|
67286
|
-
|
|
67287
|
-
|
|
67288
|
-
|
|
67289
|
-
|
|
67290
|
-
const dot = new AugmentationDotGlyph(0, glyphY);
|
|
67291
|
-
dot.renderer = this.renderer;
|
|
67292
|
-
this.addEffect(dot);
|
|
67293
|
-
}
|
|
67397
|
+
s.push(MusicFontSymbol.TupletColon);
|
|
67398
|
+
if (den > 10) {
|
|
67399
|
+
s.push((zero + Math.floor(den / 10)));
|
|
67400
|
+
s.push((zero + (den - 10)));
|
|
67294
67401
|
}
|
|
67295
|
-
|
|
67296
|
-
|
|
67297
|
-
let numberOfQuarterNotes = 0;
|
|
67298
|
-
switch (this.container.beat.duration) {
|
|
67299
|
-
case Duration.QuadrupleWhole:
|
|
67300
|
-
numberOfQuarterNotes = 16;
|
|
67301
|
-
break;
|
|
67302
|
-
case Duration.DoubleWhole:
|
|
67303
|
-
numberOfQuarterNotes = 8;
|
|
67304
|
-
break;
|
|
67305
|
-
case Duration.Whole:
|
|
67306
|
-
numberOfQuarterNotes = 4;
|
|
67307
|
-
break;
|
|
67308
|
-
case Duration.Half:
|
|
67309
|
-
numberOfQuarterNotes = 2;
|
|
67310
|
-
break;
|
|
67402
|
+
else {
|
|
67403
|
+
s.push((zero + den));
|
|
67311
67404
|
}
|
|
67312
|
-
|
|
67313
|
-
|
|
67314
|
-
|
|
67315
|
-
|
|
67405
|
+
}
|
|
67406
|
+
// check if we need to paint simple footer
|
|
67407
|
+
const offset = this.tupletOffset;
|
|
67408
|
+
const size = this.tupletSize;
|
|
67409
|
+
const shift = offset + size * 0.5;
|
|
67410
|
+
const _ = ElementStyleHelper.beat(canvas, beatElement, h.beats[0]);
|
|
67411
|
+
try {
|
|
67412
|
+
const l = canvas.lineWidth;
|
|
67413
|
+
canvas.lineWidth = this.smuflMetrics.tupletBracketThickness;
|
|
67414
|
+
if (h.beats.length === 1 || !h.isFull) {
|
|
67415
|
+
for (const beat of h.beats) {
|
|
67416
|
+
const beamingHelper = this.helpers.getBeamingHelperForBeat(beat);
|
|
67417
|
+
if (!beamingHelper) {
|
|
67418
|
+
continue;
|
|
67419
|
+
}
|
|
67420
|
+
const direction = this.getTupletBeamDirection(beamingHelper);
|
|
67421
|
+
const tupletX = this.getBeatX(beat, BeatXPosition.Stem);
|
|
67422
|
+
let tupletY = this.calculateBeamYWithDirection(beamingHelper, tupletX, direction);
|
|
67423
|
+
if (direction === BeamDirection.Down) {
|
|
67424
|
+
tupletY += shift;
|
|
67425
|
+
}
|
|
67426
|
+
else {
|
|
67427
|
+
tupletY -= shift;
|
|
67428
|
+
}
|
|
67429
|
+
canvas.fillMusicFontSymbols(cx + this.x + tupletX, cy + this.y + tupletY + size * 0.5, 1, s, true);
|
|
67430
|
+
}
|
|
67316
67431
|
}
|
|
67317
|
-
|
|
67318
|
-
const
|
|
67319
|
-
|
|
67320
|
-
|
|
67432
|
+
else {
|
|
67433
|
+
const firstBeat = h.beats[0];
|
|
67434
|
+
const lastBeat = h.beats[h.beats.length - 1];
|
|
67435
|
+
let firstNonRestBeat = null;
|
|
67436
|
+
let lastNonRestBeat = null;
|
|
67437
|
+
for (let i = 0; i < h.beats.length; i++) {
|
|
67438
|
+
if (!h.beats[i].isRest) {
|
|
67439
|
+
firstNonRestBeat = h.beats[i];
|
|
67440
|
+
break;
|
|
67441
|
+
}
|
|
67442
|
+
}
|
|
67443
|
+
for (let i = h.beats.length - 1; i >= 0; i--) {
|
|
67444
|
+
if (!h.beats[i].isRest) {
|
|
67445
|
+
lastNonRestBeat = h.beats[i];
|
|
67446
|
+
break;
|
|
67447
|
+
}
|
|
67448
|
+
}
|
|
67449
|
+
let isRestOnly = false;
|
|
67450
|
+
if (!firstNonRestBeat) {
|
|
67451
|
+
firstNonRestBeat = firstBeat;
|
|
67452
|
+
isRestOnly = true;
|
|
67453
|
+
}
|
|
67454
|
+
if (!lastNonRestBeat) {
|
|
67455
|
+
lastNonRestBeat = lastBeat;
|
|
67456
|
+
}
|
|
67457
|
+
//
|
|
67458
|
+
// Calculate the overall area of the tuplet bracket
|
|
67459
|
+
const startX = this.getBeatX(firstBeat, BeatXPosition.OnNotes);
|
|
67460
|
+
const endX = this.getBeatX(lastBeat, BeatXPosition.PostNotes);
|
|
67461
|
+
//
|
|
67462
|
+
// calculate the y positions for our bracket
|
|
67463
|
+
const firstNonRestBeamingHelper = this.helpers.getBeamingHelperForBeat(firstNonRestBeat);
|
|
67464
|
+
const lastNonRestBeamingHelper = this.helpers.getBeamingHelperForBeat(lastNonRestBeat);
|
|
67465
|
+
const direction = this.getTupletBeamDirection(firstNonRestBeamingHelper);
|
|
67466
|
+
let startY = this.calculateBeamYWithDirection(firstNonRestBeamingHelper, startX, direction);
|
|
67467
|
+
let endY = this.calculateBeamYWithDirection(lastNonRestBeamingHelper, endX, direction);
|
|
67468
|
+
if (isRestOnly) {
|
|
67469
|
+
startY = Math.max(startY, endY);
|
|
67470
|
+
endY = startY;
|
|
67471
|
+
}
|
|
67472
|
+
// align line centered in available space
|
|
67473
|
+
if (direction === BeamDirection.Down) {
|
|
67474
|
+
startY += shift;
|
|
67475
|
+
endY += shift;
|
|
67476
|
+
}
|
|
67477
|
+
else {
|
|
67478
|
+
startY -= shift;
|
|
67479
|
+
endY -= shift;
|
|
67480
|
+
}
|
|
67481
|
+
//
|
|
67482
|
+
// Calculate how many space the text will need
|
|
67483
|
+
const sw = s.reduce((acc, sym) => acc + res.engravingSettings.glyphWidths.get(sym), 0);
|
|
67484
|
+
const sp = res.engravingSettings.oneStaffSpace * 0.5;
|
|
67485
|
+
//
|
|
67486
|
+
// Calculate the offsets where to break the bracket
|
|
67487
|
+
const middleX = (startX + endX) / 2;
|
|
67488
|
+
const offset1X = middleX - sw / 2 - sp;
|
|
67489
|
+
const offset2X = middleX + sw / 2 + sp;
|
|
67490
|
+
const k = (endY - startY) / (endX - startX);
|
|
67491
|
+
const d = startY - k * startX;
|
|
67492
|
+
const offset1Y = k * offset1X + d;
|
|
67493
|
+
const middleY = k * middleX + d;
|
|
67494
|
+
const offset2Y = k * offset2X + d;
|
|
67495
|
+
const angleStartY = direction === BeamDirection.Down ? startY - size * 0.5 : startY + size * 0.5;
|
|
67496
|
+
const angleEndY = direction === BeamDirection.Down ? endY - size * 0.5 : endY + size * 0.5;
|
|
67497
|
+
//
|
|
67498
|
+
// draw the bracket
|
|
67499
|
+
const pixelAlignment = canvas.lineWidth % 2 === 0 ? 0 : 0.5;
|
|
67500
|
+
cx += pixelAlignment;
|
|
67501
|
+
cy += pixelAlignment;
|
|
67502
|
+
if (offset1X > startX) {
|
|
67503
|
+
canvas.beginPath();
|
|
67504
|
+
canvas.moveTo(cx + this.x + startX, cy + this.y + angleStartY);
|
|
67505
|
+
if (bracketsAsArcs) {
|
|
67506
|
+
canvas.quadraticCurveTo(cx + this.x + (offset1X + startX) / 2, cy + this.y + offset1Y, cx + this.x + offset1X, cy + this.y + offset1Y);
|
|
67507
|
+
}
|
|
67508
|
+
else {
|
|
67509
|
+
canvas.lineTo(cx + this.x + startX, cy + this.y + startY);
|
|
67510
|
+
canvas.lineTo(cx + this.x + offset1X, cy + this.y + offset1Y);
|
|
67511
|
+
}
|
|
67512
|
+
canvas.moveTo(cx + this.x + offset2X, cy + this.y + offset2Y);
|
|
67513
|
+
if (bracketsAsArcs) {
|
|
67514
|
+
canvas.quadraticCurveTo(cx + this.x + (endX + offset2X) / 2, cy + this.y + offset2Y, cx + this.x + endX, cy + this.y + angleEndY);
|
|
67515
|
+
}
|
|
67516
|
+
else {
|
|
67517
|
+
canvas.lineTo(cx + this.x + endX, cy + this.y + endY);
|
|
67518
|
+
canvas.lineTo(cx + this.x + endX, cy + this.y + angleEndY);
|
|
67519
|
+
}
|
|
67520
|
+
canvas.stroke();
|
|
67521
|
+
}
|
|
67522
|
+
//
|
|
67523
|
+
// Draw the string
|
|
67524
|
+
canvas.fillMusicFontSymbols(cx + this.x + middleX, cy + this.y + middleY + size * 0.5, 1, s, true);
|
|
67321
67525
|
}
|
|
67526
|
+
canvas.textAlign = oldAlign;
|
|
67527
|
+
canvas.textBaseline = oldBaseLine;
|
|
67528
|
+
canvas.lineWidth = l;
|
|
67322
67529
|
}
|
|
67323
|
-
|
|
67324
|
-
|
|
67325
|
-
this.onTimeX = this.width / 2;
|
|
67326
|
-
}
|
|
67327
|
-
else if (this.noteHeads) {
|
|
67328
|
-
this.onTimeX = this.noteHeads.x + this.noteHeads.width / 2;
|
|
67329
|
-
}
|
|
67330
|
-
else if (this.deadSlapped) {
|
|
67331
|
-
this.onTimeX = this.deadSlapped.x + this.deadSlapped.width / 2;
|
|
67530
|
+
finally {
|
|
67531
|
+
_?.[Symbol.dispose]?.();
|
|
67332
67532
|
}
|
|
67333
|
-
this.middleX = this.onTimeX;
|
|
67334
|
-
this.stemX = this.middleX;
|
|
67335
67533
|
}
|
|
67336
|
-
|
|
67337
|
-
|
|
67338
|
-
|
|
67339
|
-
|
|
67340
|
-
|
|
67341
|
-
class TabTieGlyph extends NoteTieGlyph {
|
|
67342
|
-
calculateTieDirection() {
|
|
67343
|
-
if (this.isLeftHandTap) {
|
|
67344
|
-
return BeamDirection.Up;
|
|
67534
|
+
paintBeams(cx, cy, canvas, flagsElement, beamsElement) {
|
|
67535
|
+
for (const v of this.voiceContainer.voiceDrawOrder) {
|
|
67536
|
+
for (const h of this.helpers.beamHelpers[v]) {
|
|
67537
|
+
this.paintBeamHelper(cx, cy, canvas, h, flagsElement, beamsElement);
|
|
67538
|
+
}
|
|
67345
67539
|
}
|
|
67346
|
-
return TabTieGlyph.getBeamDirectionForNote(this.startNote);
|
|
67347
|
-
}
|
|
67348
|
-
static getBeamDirectionForNote(note) {
|
|
67349
|
-
return note.string > 3 ? BeamDirection.Up : BeamDirection.Down;
|
|
67350
67540
|
}
|
|
67351
|
-
|
|
67352
|
-
|
|
67353
|
-
/**
|
|
67354
|
-
* @internal
|
|
67355
|
-
*/
|
|
67356
|
-
class TabSlurGlyph extends TabTieGlyph {
|
|
67357
|
-
_forSlide;
|
|
67358
|
-
constructor(slurEffectId, startNote, endNote, forSlide, forEnd) {
|
|
67359
|
-
super(slurEffectId, startNote, endNote, forEnd);
|
|
67360
|
-
this._forSlide = forSlide;
|
|
67541
|
+
drawBeamHelperAsFlags(h) {
|
|
67542
|
+
return h.beats.length === 1;
|
|
67361
67543
|
}
|
|
67362
|
-
|
|
67363
|
-
|
|
67544
|
+
hasFlag(beat) {
|
|
67545
|
+
if (beat.isRest) {
|
|
67546
|
+
return false;
|
|
67547
|
+
}
|
|
67548
|
+
const helper = this.helpers.getBeamingHelperForBeat(beat);
|
|
67549
|
+
if (helper) {
|
|
67550
|
+
return helper.hasFlag(this.drawBeamHelperAsFlags(helper), beat);
|
|
67551
|
+
}
|
|
67552
|
+
return BeamingHelper.beatHasFlag(beat);
|
|
67364
67553
|
}
|
|
67365
|
-
|
|
67366
|
-
|
|
67367
|
-
if (this._forSlide !== forSlide) {
|
|
67554
|
+
hasStem(beat) {
|
|
67555
|
+
if (beat.isRest) {
|
|
67368
67556
|
return false;
|
|
67369
67557
|
}
|
|
67370
|
-
|
|
67371
|
-
if (
|
|
67558
|
+
const helper = this.helpers.getBeamingHelperForBeat(beat);
|
|
67559
|
+
if (helper) {
|
|
67560
|
+
return helper.hasStem(this.drawBeamHelperAsFlags(helper), beat);
|
|
67561
|
+
}
|
|
67562
|
+
return BeamingHelper.beatHasStem(beat);
|
|
67563
|
+
}
|
|
67564
|
+
paintBeamHelper(cx, cy, canvas, h, flagsElement, beamsElement) {
|
|
67565
|
+
canvas.color = h.voice.index === 0 ? this.resources.mainGlyphColor : this.resources.secondaryGlyphColor;
|
|
67566
|
+
if (this.shouldPaintBeamingHelper(h)) {
|
|
67567
|
+
if (this.drawBeamHelperAsFlags(h)) {
|
|
67568
|
+
this.paintFlag(cx, cy, canvas, h, flagsElement);
|
|
67569
|
+
}
|
|
67570
|
+
else {
|
|
67571
|
+
this.paintBar(cx, cy, canvas, h, beamsElement);
|
|
67572
|
+
}
|
|
67573
|
+
}
|
|
67574
|
+
}
|
|
67575
|
+
shouldPaintBeamingHelper(h) {
|
|
67576
|
+
return !h.isRestBeamHelper;
|
|
67577
|
+
}
|
|
67578
|
+
shouldPaintFlag(beat) {
|
|
67579
|
+
// no flags for bend grace beats
|
|
67580
|
+
if (beat.graceType === GraceType.BendGrace) {
|
|
67372
67581
|
return false;
|
|
67373
67582
|
}
|
|
67374
|
-
if (
|
|
67583
|
+
if (beat.deadSlapped) {
|
|
67375
67584
|
return false;
|
|
67376
67585
|
}
|
|
67377
|
-
|
|
67378
|
-
if (
|
|
67586
|
+
// no flags for any grace notes on songbook mode
|
|
67587
|
+
if (beat.graceType !== GraceType.None && this.settings.notation.notationMode === NotationMode.SongBook) {
|
|
67379
67588
|
return false;
|
|
67380
67589
|
}
|
|
67381
|
-
//
|
|
67382
|
-
if (
|
|
67590
|
+
// only flags for durations with stems
|
|
67591
|
+
if (beat.duration === Duration.Whole ||
|
|
67592
|
+
beat.duration === Duration.DoubleWhole ||
|
|
67593
|
+
beat.duration === Duration.QuadrupleWhole) {
|
|
67383
67594
|
return false;
|
|
67384
67595
|
}
|
|
67385
|
-
|
|
67386
|
-
|
|
67387
|
-
|
|
67388
|
-
|
|
67389
|
-
|
|
67596
|
+
return true;
|
|
67597
|
+
}
|
|
67598
|
+
paintFlag(cx, cy, canvas, h, flagsElement) {
|
|
67599
|
+
for (const beat of h.beats) {
|
|
67600
|
+
if (!this.shouldPaintFlag(beat)) {
|
|
67601
|
+
continue;
|
|
67602
|
+
}
|
|
67603
|
+
const isGrace = beat.graceType !== GraceType.None;
|
|
67604
|
+
//
|
|
67605
|
+
// draw line
|
|
67606
|
+
//
|
|
67607
|
+
const beatLineX = this.getBeatX(beat, BeatXPosition.Stem);
|
|
67608
|
+
const direction = this.getBeamDirection(h);
|
|
67609
|
+
const topY = cy + this.y + this.getFlagTopY(beat, direction);
|
|
67610
|
+
const bottomY = cy + this.y + this.getFlagBottomY(beat, direction);
|
|
67611
|
+
let flagY = 0;
|
|
67612
|
+
if (direction === BeamDirection.Down) {
|
|
67613
|
+
flagY = bottomY;
|
|
67614
|
+
}
|
|
67615
|
+
else {
|
|
67616
|
+
flagY = topY;
|
|
67617
|
+
}
|
|
67618
|
+
if (!h.hasStem(true, beat)) {
|
|
67619
|
+
continue;
|
|
67620
|
+
}
|
|
67621
|
+
this.paintBeamingStem(beat, cy + this.y, cx + this.x + beatLineX, topY, bottomY, canvas);
|
|
67622
|
+
const _ = ElementStyleHelper.beat(canvas, flagsElement, beat);
|
|
67623
|
+
try {
|
|
67624
|
+
let flagWidth = 0;
|
|
67625
|
+
//
|
|
67626
|
+
// Draw flag
|
|
67627
|
+
//
|
|
67628
|
+
if (h.hasFlag(true, beat)) {
|
|
67629
|
+
const glyph = new FlagGlyph(cx + this.x + beatLineX, flagY, beat.duration, direction, isGrace);
|
|
67630
|
+
glyph.renderer = this;
|
|
67631
|
+
glyph.doLayout();
|
|
67632
|
+
glyph.paint(0, 0, canvas);
|
|
67633
|
+
flagWidth = glyph.width / 2;
|
|
67390
67634
|
}
|
|
67391
|
-
if (
|
|
67392
|
-
|
|
67635
|
+
if (beat.graceType === GraceType.BeforeBeat) {
|
|
67636
|
+
if (direction === BeamDirection.Down) {
|
|
67637
|
+
CanvasHelper.fillMusicFontSymbolSafe(canvas, cx + this.x + beatLineX + flagWidth / 2, (topY + bottomY - this.smuflMetrics.glyphHeights.get(MusicFontSymbol.GraceNoteSlashStemDown)) /
|
|
67638
|
+
2, EngravingSettings.GraceScale, MusicFontSymbol.GraceNoteSlashStemDown, true);
|
|
67639
|
+
}
|
|
67640
|
+
else {
|
|
67641
|
+
CanvasHelper.fillMusicFontSymbolSafe(canvas, cx + this.x + beatLineX + flagWidth / 2, (topY + bottomY + this.smuflMetrics.glyphHeights.get(MusicFontSymbol.GraceNoteSlashStemUp)) /
|
|
67642
|
+
2, EngravingSettings.GraceScale, MusicFontSymbol.GraceNoteSlashStemUp, true);
|
|
67643
|
+
}
|
|
67393
67644
|
}
|
|
67645
|
+
}
|
|
67646
|
+
finally {
|
|
67647
|
+
_?.[Symbol.dispose]?.();
|
|
67648
|
+
}
|
|
67649
|
+
}
|
|
67650
|
+
}
|
|
67651
|
+
getFlagStemSize(duration, forceMinStem = false) {
|
|
67652
|
+
let size = 0;
|
|
67653
|
+
switch (duration) {
|
|
67654
|
+
case Duration.QuadrupleWhole:
|
|
67655
|
+
case Duration.Half:
|
|
67656
|
+
case Duration.Quarter:
|
|
67657
|
+
case Duration.Eighth:
|
|
67658
|
+
case Duration.Sixteenth:
|
|
67659
|
+
case Duration.ThirtySecond:
|
|
67660
|
+
case Duration.SixtyFourth:
|
|
67661
|
+
case Duration.OneHundredTwentyEighth:
|
|
67662
|
+
case Duration.TwoHundredFiftySixth:
|
|
67663
|
+
size = this.smuflMetrics.standardStemLength + this.smuflMetrics.stemFlagOffsets.get(duration);
|
|
67394
67664
|
break;
|
|
67395
|
-
|
|
67396
|
-
|
|
67397
|
-
this.startNote = startNote;
|
|
67398
|
-
}
|
|
67399
|
-
if (endNote.realValue < this.endNote.realValue) {
|
|
67400
|
-
this.endNote = endNote;
|
|
67401
|
-
}
|
|
67665
|
+
default:
|
|
67666
|
+
size = forceMinStem ? this.smuflMetrics.standardStemLength : 0;
|
|
67402
67667
|
break;
|
|
67403
67668
|
}
|
|
67404
|
-
return
|
|
67669
|
+
return size;
|
|
67405
67670
|
}
|
|
67406
|
-
|
|
67407
|
-
|
|
67408
|
-
|
|
67409
|
-
* @internal
|
|
67410
|
-
*/
|
|
67411
|
-
class NumberedSlurGlyph extends TabSlurGlyph {
|
|
67412
|
-
calculateTieDirection() {
|
|
67413
|
-
return BeamDirection.Up;
|
|
67671
|
+
recreatePreBeatGlyphs() {
|
|
67672
|
+
this._startSpacing = false;
|
|
67673
|
+
super.recreatePreBeatGlyphs();
|
|
67414
67674
|
}
|
|
67415
|
-
|
|
67416
|
-
|
|
67417
|
-
/**
|
|
67418
|
-
* @internal
|
|
67419
|
-
*/
|
|
67420
|
-
class NumberedBeatContainerGlyph extends BeatContainerGlyph {
|
|
67421
|
-
_slurs = new Map();
|
|
67422
|
-
_effectSlurs = [];
|
|
67423
|
-
constructor(beat) {
|
|
67424
|
-
super(beat);
|
|
67425
|
-
this.preNotes = new NumberedBeatPreNotesGlyph();
|
|
67426
|
-
this.onNotes = new NumberedBeatGlyph();
|
|
67675
|
+
calculateBeamY(h, x) {
|
|
67676
|
+
return this.calculateBeamYWithDirection(h, x, this.getBeamDirection(h));
|
|
67427
67677
|
}
|
|
67428
|
-
|
|
67429
|
-
|
|
67430
|
-
this.
|
|
67431
|
-
|
|
67678
|
+
createPreBeatGlyphs() {
|
|
67679
|
+
super.createPreBeatGlyphs();
|
|
67680
|
+
this.addPreBeatGlyph(new BarLineGlyph(false, this.bar.staff.track.score.stylesheet.extendBarLines));
|
|
67681
|
+
this.createLinePreBeatGlyphs();
|
|
67682
|
+
this.addPreBeatGlyph(new BarNumberGlyph(0, this.getLineHeight(-0.5), this.bar.index + 1));
|
|
67432
67683
|
}
|
|
67433
|
-
|
|
67434
|
-
|
|
67435
|
-
|
|
67436
|
-
|
|
67437
|
-
|
|
67438
|
-
|
|
67439
|
-
const tie = new NumberedTieGlyph(`numbered.tie.${n.beat.id}`, n, n.tieDestination, false);
|
|
67440
|
-
this.addTie(tie);
|
|
67441
|
-
this._slurs.set(tie.slurEffectId, tie);
|
|
67442
|
-
}
|
|
67443
|
-
if (n.isTieDestination) {
|
|
67444
|
-
const tie = new NumberedTieGlyph(`numbered.tie.${n.tieOrigin.beat.id}`, n.tieOrigin, n, true);
|
|
67445
|
-
this.addTie(tie);
|
|
67446
|
-
}
|
|
67447
|
-
if (n.isLeftHandTapped &&
|
|
67448
|
-
!n.isHammerPullDestination &&
|
|
67449
|
-
!this._slurs.has(`numbered.tie.leftHandTap.${n.beat.id}`)) {
|
|
67450
|
-
const tapSlur = new NumberedTieGlyph(`numbered.tie.leftHandTap.${n.beat.id}`, n, n, false);
|
|
67451
|
-
this.addTie(tapSlur);
|
|
67452
|
-
this._slurs.set(tapSlur.slurEffectId, tapSlur);
|
|
67684
|
+
createPostBeatGlyphs() {
|
|
67685
|
+
super.createPostBeatGlyphs();
|
|
67686
|
+
const lastBar = this.lastBar;
|
|
67687
|
+
this.addPostBeatGlyph(new BarLineGlyph(true, this.bar.staff.track.score.stylesheet.extendBarLines));
|
|
67688
|
+
if (lastBar.masterBar.isRepeatEnd && lastBar.masterBar.repeatCount > 2) {
|
|
67689
|
+
this.addPostBeatGlyph(new RepeatCountGlyph(0, this.getLineHeight(-0.5), this.bar.masterBar.repeatCount));
|
|
67453
67690
|
}
|
|
67454
|
-
|
|
67455
|
-
|
|
67456
|
-
|
|
67457
|
-
|
|
67458
|
-
|
|
67459
|
-
|
|
67460
|
-
|
|
67461
|
-
|
|
67462
|
-
|
|
67463
|
-
|
|
67464
|
-
const effectSlur = new NumberedSlurGlyph(`numbered.slur.effect`, n, n.effectSlurDestination, false, false);
|
|
67465
|
-
this._effectSlurs.push(effectSlur);
|
|
67466
|
-
this.addTie(effectSlur);
|
|
67467
|
-
this._slurs.set(effectSlur.slurEffectId, effectSlur);
|
|
67468
|
-
this._slurs.set('numbered.slur.effect', effectSlur);
|
|
67469
|
-
}
|
|
67691
|
+
}
|
|
67692
|
+
paintBar(cx, cy, canvas, h, beamsElement) {
|
|
67693
|
+
const direction = this.getBeamDirection(h);
|
|
67694
|
+
const isGrace = h.graceType !== GraceType.None;
|
|
67695
|
+
const scaleMod = isGrace ? EngravingSettings.GraceScale : 1;
|
|
67696
|
+
let barSpacing = (this.beamSpacing + this.beamThickness) * scaleMod;
|
|
67697
|
+
let barSize = this.beamThickness * scaleMod;
|
|
67698
|
+
if (direction === BeamDirection.Down) {
|
|
67699
|
+
barSpacing = -barSpacing;
|
|
67700
|
+
barSize = -barSize;
|
|
67470
67701
|
}
|
|
67471
|
-
|
|
67472
|
-
|
|
67473
|
-
|
|
67474
|
-
|
|
67475
|
-
if (slur.tryExpand(n.effectSlurOrigin, n, false, true)) {
|
|
67476
|
-
expanded = true;
|
|
67477
|
-
break;
|
|
67478
|
-
}
|
|
67479
|
-
}
|
|
67480
|
-
if (!expanded) {
|
|
67481
|
-
const effectSlur = new NumberedSlurGlyph(`numbered.slur.effect`, n.effectSlurOrigin, n, false, true);
|
|
67482
|
-
this._effectSlurs.push(effectSlur);
|
|
67483
|
-
this.addTie(effectSlur);
|
|
67484
|
-
this._slurs.set(effectSlur.slurEffectId, effectSlur);
|
|
67485
|
-
this._slurs.set('numbered.slur.effect', effectSlur);
|
|
67702
|
+
for (let i = 0, j = h.beats.length; i < j; i++) {
|
|
67703
|
+
const beat = h.beats[i];
|
|
67704
|
+
if (beat.deadSlapped) {
|
|
67705
|
+
continue;
|
|
67486
67706
|
}
|
|
67487
|
-
|
|
67488
|
-
|
|
67489
|
-
|
|
67490
|
-
|
|
67491
|
-
|
|
67492
|
-
|
|
67493
|
-
|
|
67494
|
-
|
|
67495
|
-
|
|
67496
|
-
|
|
67497
|
-
|
|
67498
|
-
|
|
67499
|
-
|
|
67500
|
-
|
|
67501
|
-
|
|
67502
|
-
|
|
67503
|
-
|
|
67504
|
-
|
|
67505
|
-
|
|
67506
|
-
|
|
67507
|
-
|
|
67508
|
-
|
|
67509
|
-
|
|
67510
|
-
|
|
67511
|
-
|
|
67512
|
-
|
|
67513
|
-
|
|
67514
|
-
|
|
67515
|
-
|
|
67516
|
-
|
|
67517
|
-
|
|
67518
|
-
|
|
67519
|
-
|
|
67520
|
-
|
|
67521
|
-
|
|
67522
|
-
|
|
67523
|
-
|
|
67524
|
-
|
|
67525
|
-
|
|
67526
|
-
|
|
67527
|
-
|
|
67528
|
-
|
|
67529
|
-
|
|
67530
|
-
|
|
67531
|
-
|
|
67532
|
-
|
|
67533
|
-
|
|
67534
|
-
|
|
67535
|
-
|
|
67536
|
-
|
|
67537
|
-
|
|
67538
|
-
|
|
67539
|
-
|
|
67540
|
-
|
|
67541
|
-
|
|
67542
|
-
|
|
67543
|
-
|
|
67544
|
-
|
|
67545
|
-
|
|
67546
|
-
|
|
67547
|
-
|
|
67548
|
-
|
|
67549
|
-
|
|
67550
|
-
|
|
67551
|
-
|
|
67552
|
-
|
|
67553
|
-
|
|
67554
|
-
|
|
67555
|
-
|
|
67556
|
-
|
|
67557
|
-
|
|
67558
|
-
|
|
67559
|
-
|
|
67560
|
-
|
|
67561
|
-
|
|
67562
|
-
|
|
67563
|
-
break;
|
|
67564
|
-
case KeySignature.FSharp:
|
|
67565
|
-
text2 = ' F';
|
|
67566
|
-
accidental = AccidentalType.Sharp;
|
|
67567
|
-
break;
|
|
67568
|
-
case KeySignature.CSharp:
|
|
67569
|
-
text2 = ' C';
|
|
67570
|
-
accidental = AccidentalType.Sharp;
|
|
67571
|
-
break;
|
|
67572
|
-
}
|
|
67573
|
-
break;
|
|
67574
|
-
case KeySignatureType.Minor:
|
|
67575
|
-
switch (this._keySignature) {
|
|
67576
|
-
case KeySignature.Cb:
|
|
67577
|
-
text2 = ' a';
|
|
67578
|
-
accidental = AccidentalType.Flat;
|
|
67579
|
-
break;
|
|
67580
|
-
case KeySignature.Gb:
|
|
67581
|
-
text2 = ' e';
|
|
67582
|
-
accidental = AccidentalType.Flat;
|
|
67583
|
-
break;
|
|
67584
|
-
case KeySignature.Db:
|
|
67585
|
-
text2 = ' b';
|
|
67586
|
-
accidental = AccidentalType.Flat;
|
|
67587
|
-
break;
|
|
67588
|
-
case KeySignature.Ab:
|
|
67589
|
-
text2 = 'f';
|
|
67590
|
-
accidental = AccidentalType.None;
|
|
67591
|
-
break;
|
|
67592
|
-
case KeySignature.Eb:
|
|
67593
|
-
text2 = 'c';
|
|
67594
|
-
accidental = AccidentalType.None;
|
|
67595
|
-
break;
|
|
67596
|
-
case KeySignature.Bb:
|
|
67597
|
-
text2 = 'g';
|
|
67598
|
-
accidental = AccidentalType.None;
|
|
67599
|
-
break;
|
|
67600
|
-
case KeySignature.F:
|
|
67601
|
-
text2 = 'd';
|
|
67602
|
-
break;
|
|
67603
|
-
case KeySignature.C:
|
|
67604
|
-
text2 = 'a';
|
|
67605
|
-
accidental = AccidentalType.None;
|
|
67606
|
-
break;
|
|
67607
|
-
case KeySignature.G:
|
|
67608
|
-
text2 = 'e';
|
|
67609
|
-
accidental = AccidentalType.None;
|
|
67610
|
-
break;
|
|
67611
|
-
case KeySignature.D:
|
|
67612
|
-
text2 = 'b';
|
|
67613
|
-
accidental = AccidentalType.None;
|
|
67614
|
-
break;
|
|
67615
|
-
case KeySignature.A:
|
|
67616
|
-
text2 = ' f';
|
|
67617
|
-
accidental = AccidentalType.Sharp;
|
|
67618
|
-
break;
|
|
67619
|
-
case KeySignature.E:
|
|
67620
|
-
text2 = ' c';
|
|
67621
|
-
accidental = AccidentalType.Sharp;
|
|
67622
|
-
break;
|
|
67623
|
-
case KeySignature.B:
|
|
67624
|
-
text2 = ' g';
|
|
67625
|
-
accidental = AccidentalType.Sharp;
|
|
67626
|
-
break;
|
|
67627
|
-
case KeySignature.FSharp:
|
|
67628
|
-
text2 = ' d';
|
|
67629
|
-
accidental = AccidentalType.Sharp;
|
|
67630
|
-
break;
|
|
67631
|
-
case KeySignature.CSharp:
|
|
67632
|
-
text2 = ' a';
|
|
67633
|
-
accidental = AccidentalType.Sharp;
|
|
67634
|
-
break;
|
|
67707
|
+
const beatLineX = this.getBeatX(beat, BeatXPosition.Stem);
|
|
67708
|
+
const y1 = cy + this.y + this.getBarLineStart(beat, direction);
|
|
67709
|
+
// ensure we are pixel aligned on the end of the stem to avoid anti-aliasing artifacts
|
|
67710
|
+
// when combining stems and beams on sub-pixel level
|
|
67711
|
+
const y2 = (cy + this.y + this.calculateBeamY(h, beatLineX)) | 0;
|
|
67712
|
+
if (y1 < y2) {
|
|
67713
|
+
this.paintBeamingStem(beat, cy + this.y, cx + this.x + beatLineX, y1, y2, canvas);
|
|
67714
|
+
}
|
|
67715
|
+
else {
|
|
67716
|
+
this.paintBeamingStem(beat, cy + this.y, cx + this.x + beatLineX, y2, y1, canvas);
|
|
67717
|
+
}
|
|
67718
|
+
const _ = ElementStyleHelper.beat(canvas, beamsElement, beat);
|
|
67719
|
+
try {
|
|
67720
|
+
const brokenBarOffset = this.smuflMetrics.brokenBeamWidth * scaleMod;
|
|
67721
|
+
const barCount = ModelUtils.getIndex(beat.duration) - 2;
|
|
67722
|
+
const barStart = cy + this.y;
|
|
67723
|
+
for (let barIndex = 0; barIndex < barCount; barIndex++) {
|
|
67724
|
+
let barStartX = 0;
|
|
67725
|
+
let barEndX = 0;
|
|
67726
|
+
let barStartY = 0;
|
|
67727
|
+
let barEndY = 0;
|
|
67728
|
+
const barY = barStart + barIndex * barSpacing;
|
|
67729
|
+
//
|
|
67730
|
+
// Bar to Next?
|
|
67731
|
+
//
|
|
67732
|
+
if (i < h.beats.length - 1) {
|
|
67733
|
+
const isFullBarJoin = BeamingHelper.isFullBarJoin(beat, h.beats[i + 1], barIndex);
|
|
67734
|
+
// force two broken bars on secondary (last) beam?
|
|
67735
|
+
if (barIndex === barCount - 1 &&
|
|
67736
|
+
isFullBarJoin &&
|
|
67737
|
+
beat.beamingMode === BeatBeamingMode.ForceSplitOnSecondaryToNext) {
|
|
67738
|
+
// start part
|
|
67739
|
+
barStartX = beatLineX;
|
|
67740
|
+
barEndX = barStartX + brokenBarOffset;
|
|
67741
|
+
barStartY = barY + this.calculateBeamY(h, barStartX);
|
|
67742
|
+
barEndY = barY + this.calculateBeamY(h, barEndX);
|
|
67743
|
+
LineBarRenderer.paintSingleBar(canvas, cx + this.x + barStartX, barStartY, cx + this.x + barEndX, barEndY, barSize);
|
|
67744
|
+
// end part
|
|
67745
|
+
barEndX = this.getBeatX(h.beats[i + 1], BeatXPosition.Stem);
|
|
67746
|
+
barStartX = barEndX - brokenBarOffset;
|
|
67747
|
+
barStartY = barY + this.calculateBeamY(h, barStartX);
|
|
67748
|
+
barEndY = barY + this.calculateBeamY(h, barEndX);
|
|
67749
|
+
LineBarRenderer.paintSingleBar(canvas, cx + this.x + barStartX, barStartY, cx + this.x + barEndX, barEndY, barSize);
|
|
67750
|
+
}
|
|
67751
|
+
else {
|
|
67752
|
+
if (isFullBarJoin) {
|
|
67753
|
+
// full bar?
|
|
67754
|
+
barStartX = beatLineX;
|
|
67755
|
+
barEndX = this.getBeatX(h.beats[i + 1], BeatXPosition.Stem);
|
|
67756
|
+
}
|
|
67757
|
+
else if (i === 0 || !BeamingHelper.isFullBarJoin(h.beats[i - 1], beat, barIndex)) {
|
|
67758
|
+
barStartX = beatLineX;
|
|
67759
|
+
barEndX = barStartX + brokenBarOffset;
|
|
67760
|
+
}
|
|
67761
|
+
else {
|
|
67762
|
+
continue;
|
|
67763
|
+
}
|
|
67764
|
+
barStartY = barY + this.calculateBeamY(h, barStartX);
|
|
67765
|
+
barEndY = barY + this.calculateBeamY(h, barEndX);
|
|
67766
|
+
// ensure we are pixel aligned on the end of the stem to avoid anti-aliasing artifacts
|
|
67767
|
+
// when combining stems and beams on sub-pixel level
|
|
67768
|
+
if (barIndex === 0) {
|
|
67769
|
+
barStartY = barStartY | 0;
|
|
67770
|
+
barEndY = barEndY | 0;
|
|
67771
|
+
}
|
|
67772
|
+
LineBarRenderer.paintSingleBar(canvas, cx + this.x + barStartX, barStartY, cx + this.x + barEndX, barEndY, barSize);
|
|
67773
|
+
}
|
|
67774
|
+
}
|
|
67775
|
+
else if (i > 0 && !BeamingHelper.isFullBarJoin(beat, h.beats[i - 1], barIndex)) {
|
|
67776
|
+
barStartX = beatLineX - brokenBarOffset;
|
|
67777
|
+
barEndX = beatLineX;
|
|
67778
|
+
barEndX = beatLineX;
|
|
67779
|
+
barStartY = barY + this.calculateBeamY(h, barStartX);
|
|
67780
|
+
barEndY = barY + this.calculateBeamY(h, barEndX);
|
|
67781
|
+
LineBarRenderer.paintSingleBar(canvas, cx + this.x + barStartX, barStartY, cx + this.x + barEndX, barEndY, barSize);
|
|
67782
|
+
}
|
|
67635
67783
|
}
|
|
67636
|
-
|
|
67637
|
-
|
|
67638
|
-
|
|
67639
|
-
this._accidental = accidental;
|
|
67640
|
-
const c = this.renderer.scoreRenderer.canvas;
|
|
67641
|
-
const res = this.renderer.resources;
|
|
67642
|
-
c.font = res.numberedNotationFont;
|
|
67643
|
-
this._accidentalOffset = c.measureText(text).width;
|
|
67644
|
-
this.width = c.measureText(text + text2).width;
|
|
67645
|
-
}
|
|
67646
|
-
paint(cx, cy, canvas) {
|
|
67647
|
-
const _ = ElementStyleHelper.bar(canvas, BarSubElement.NumberedKeySignature, this.renderer.bar);
|
|
67648
|
-
try {
|
|
67649
|
-
const res = this.renderer.resources;
|
|
67650
|
-
canvas.font = res.numberedNotationFont;
|
|
67651
|
-
canvas.textBaseline = TextBaseline.Middle;
|
|
67652
|
-
canvas.fillText(this._text, cx + this.x, cy + this.y);
|
|
67653
|
-
if (this._accidental !== AccidentalType.None) {
|
|
67654
|
-
CanvasHelper.fillMusicFontSymbolSafe(canvas, cx + this.x + this._accidentalOffset, cy + this.y, 1, AccidentalGlyph.getMusicSymbol(this._accidental), false);
|
|
67784
|
+
}
|
|
67785
|
+
finally {
|
|
67786
|
+
_?.[Symbol.dispose]?.();
|
|
67655
67787
|
}
|
|
67656
67788
|
}
|
|
67657
|
-
|
|
67658
|
-
|
|
67789
|
+
if (h.graceType === GraceType.BeforeBeat) {
|
|
67790
|
+
const beatLineX = this.getBeatX(h.beats[0], BeatXPosition.Stem);
|
|
67791
|
+
const flagWidth = this.smuflMetrics.glyphWidths.get(MusicFontSymbol.Flag8thUp) * EngravingSettings.GraceScale;
|
|
67792
|
+
let slashY = (cy + this.y + this.calculateBeamY(h, beatLineX)) | 0;
|
|
67793
|
+
slashY += barSize + barSpacing;
|
|
67794
|
+
if (direction === BeamDirection.Down) {
|
|
67795
|
+
CanvasHelper.fillMusicFontSymbolSafe(canvas, cx + this.x + beatLineX + flagWidth / 2, slashY, EngravingSettings.GraceScale, MusicFontSymbol.GraceNoteSlashStemDown, true);
|
|
67796
|
+
}
|
|
67797
|
+
else {
|
|
67798
|
+
CanvasHelper.fillMusicFontSymbolSafe(canvas, cx + this.x + beatLineX + flagWidth / 2, slashY, EngravingSettings.GraceScale, MusicFontSymbol.GraceNoteSlashStemUp, true);
|
|
67799
|
+
}
|
|
67659
67800
|
}
|
|
67660
67801
|
}
|
|
67661
|
-
|
|
67662
|
-
|
|
67663
|
-
|
|
67664
|
-
|
|
67665
|
-
|
|
67666
|
-
|
|
67667
|
-
|
|
67668
|
-
|
|
67669
|
-
constructor(isOpen) {
|
|
67670
|
-
super(0, 0);
|
|
67671
|
-
this._isOpen = isOpen;
|
|
67672
|
-
}
|
|
67673
|
-
doLayout() {
|
|
67674
|
-
super.doLayout();
|
|
67675
|
-
this.width =
|
|
67676
|
-
this.renderer.smuflMetrics.ghostParenthesisWidth + this.renderer.smuflMetrics.ghostParenthesisPadding;
|
|
67802
|
+
static paintSingleBar(canvas, x1, y1, x2, y2, size) {
|
|
67803
|
+
canvas.beginPath();
|
|
67804
|
+
canvas.moveTo(x1, y1);
|
|
67805
|
+
canvas.lineTo(x2, y2);
|
|
67806
|
+
canvas.lineTo(x2, y2 + size);
|
|
67807
|
+
canvas.lineTo(x1, y1 + size);
|
|
67808
|
+
canvas.closePath();
|
|
67809
|
+
canvas.fill();
|
|
67677
67810
|
}
|
|
67678
|
-
|
|
67679
|
-
|
|
67680
|
-
|
|
67681
|
-
|
|
67811
|
+
calculateBeamingOverflows(rendererTop, rendererBottom) {
|
|
67812
|
+
let maxNoteY = 0;
|
|
67813
|
+
let minNoteY = 0;
|
|
67814
|
+
const noteOverflowPadding = this.getLineHeight(0.5);
|
|
67815
|
+
for (const v of this.helpers.beamHelpers) {
|
|
67816
|
+
for (const h of v) {
|
|
67817
|
+
if (!this.shouldPaintBeamingHelper(h)) ;
|
|
67818
|
+
else if (h.beats.length === 1 && h.beats[0].duration >= Duration.Half) {
|
|
67819
|
+
const tupletDirection = this.getTupletBeamDirection(h);
|
|
67820
|
+
if (h.direction === BeamDirection.Up) {
|
|
67821
|
+
let topY = this.getFlagTopY(h.beats[0], h.direction);
|
|
67822
|
+
if (h.hasTuplet && tupletDirection === h.direction) {
|
|
67823
|
+
topY -= this.tupletSize + this.tupletOffset;
|
|
67824
|
+
}
|
|
67825
|
+
if (topY < maxNoteY) {
|
|
67826
|
+
maxNoteY = topY;
|
|
67827
|
+
}
|
|
67828
|
+
if (h.hasTuplet && tupletDirection !== h.direction) {
|
|
67829
|
+
let bottomY = this.getFlagBottomY(h.beats[0], tupletDirection);
|
|
67830
|
+
bottomY += this.tupletSize + this.tupletOffset;
|
|
67831
|
+
if (bottomY > minNoteY) {
|
|
67832
|
+
minNoteY = bottomY;
|
|
67833
|
+
}
|
|
67834
|
+
}
|
|
67835
|
+
}
|
|
67836
|
+
else {
|
|
67837
|
+
let bottomY = this.getFlagBottomY(h.beats[0], h.direction);
|
|
67838
|
+
if (h.hasTuplet && tupletDirection === h.direction) {
|
|
67839
|
+
bottomY += this.tupletSize + this.tupletOffset;
|
|
67840
|
+
}
|
|
67841
|
+
if (bottomY > minNoteY) {
|
|
67842
|
+
minNoteY = bottomY;
|
|
67843
|
+
}
|
|
67844
|
+
if (h.hasTuplet && tupletDirection !== h.direction) {
|
|
67845
|
+
let topY = this.getFlagTopY(h.beats[0], tupletDirection);
|
|
67846
|
+
topY -= this.tupletSize + this.tupletOffset;
|
|
67847
|
+
if (topY < maxNoteY) {
|
|
67848
|
+
maxNoteY = topY;
|
|
67849
|
+
}
|
|
67850
|
+
}
|
|
67851
|
+
}
|
|
67852
|
+
}
|
|
67853
|
+
else {
|
|
67854
|
+
this.ensureBeamDrawingInfo(h, h.direction);
|
|
67855
|
+
const drawingInfo = h.drawingInfos.get(h.direction);
|
|
67856
|
+
const tupletDirection = this.getTupletBeamDirection(h);
|
|
67857
|
+
if (h.direction === BeamDirection.Up) {
|
|
67858
|
+
let topY = Math.min(drawingInfo.startY, drawingInfo.endY);
|
|
67859
|
+
if (h.hasTuplet && tupletDirection === h.direction) {
|
|
67860
|
+
topY -= this.tupletSize + this.tupletOffset;
|
|
67861
|
+
}
|
|
67862
|
+
if (topY < maxNoteY) {
|
|
67863
|
+
maxNoteY = topY;
|
|
67864
|
+
}
|
|
67865
|
+
let bottomY = this.getBarLineStart(h.beatOfLowestNote, h.direction) + noteOverflowPadding;
|
|
67866
|
+
if (h.hasTuplet && tupletDirection !== h.direction) {
|
|
67867
|
+
bottomY += this.tupletSize + this.tupletOffset;
|
|
67868
|
+
}
|
|
67869
|
+
if (bottomY > minNoteY) {
|
|
67870
|
+
minNoteY = bottomY;
|
|
67871
|
+
}
|
|
67872
|
+
}
|
|
67873
|
+
else {
|
|
67874
|
+
let bottomY = Math.max(drawingInfo.startY, drawingInfo.endY);
|
|
67875
|
+
if (h.hasTuplet && tupletDirection === h.direction) {
|
|
67876
|
+
bottomY += this.tupletSize + this.tupletOffset;
|
|
67877
|
+
}
|
|
67878
|
+
if (bottomY > minNoteY) {
|
|
67879
|
+
minNoteY = bottomY;
|
|
67880
|
+
}
|
|
67881
|
+
let topY = this.getBarLineStart(h.beatOfHighestNote, h.direction) - noteOverflowPadding;
|
|
67882
|
+
if (h.hasTuplet && tupletDirection !== h.direction) {
|
|
67883
|
+
topY -= this.tupletSize + this.tupletOffset;
|
|
67884
|
+
}
|
|
67885
|
+
if (topY < maxNoteY) {
|
|
67886
|
+
maxNoteY = topY;
|
|
67887
|
+
}
|
|
67888
|
+
}
|
|
67889
|
+
}
|
|
67890
|
+
}
|
|
67682
67891
|
}
|
|
67683
|
-
if (
|
|
67684
|
-
|
|
67892
|
+
if (maxNoteY < rendererTop) {
|
|
67893
|
+
this.registerOverflowTop(Math.abs(maxNoteY));
|
|
67685
67894
|
}
|
|
67686
|
-
|
|
67687
|
-
|
|
67895
|
+
if (minNoteY > rendererBottom) {
|
|
67896
|
+
this.registerOverflowBottom(Math.abs(minNoteY) - rendererBottom);
|
|
67688
67897
|
}
|
|
67689
|
-
canvas.color = c;
|
|
67690
|
-
}
|
|
67691
|
-
}
|
|
67692
|
-
|
|
67693
|
-
/**
|
|
67694
|
-
* @internal
|
|
67695
|
-
*/
|
|
67696
|
-
class TimeSignatureGlyph extends GlyphGroup {
|
|
67697
|
-
_numerator = 0;
|
|
67698
|
-
_denominator = 0;
|
|
67699
|
-
_isCommon;
|
|
67700
|
-
_isFreeTime;
|
|
67701
|
-
barSubElement = BarSubElement.StandardNotationTimeSignature;
|
|
67702
|
-
constructor(x, y, numerator, denominator, isCommon, isFreeTime) {
|
|
67703
|
-
super(x, y);
|
|
67704
|
-
this._numerator = numerator;
|
|
67705
|
-
this._denominator = denominator;
|
|
67706
|
-
this._isCommon = isCommon;
|
|
67707
|
-
this._isFreeTime = isFreeTime;
|
|
67708
67898
|
}
|
|
67709
|
-
|
|
67710
|
-
const
|
|
67711
|
-
|
|
67712
|
-
|
|
67899
|
+
initializeBeamDrawingInfo(h, direction) {
|
|
67900
|
+
const drawingInfo = new BeamingHelperDrawInfo();
|
|
67901
|
+
const firstBeat = h.beats[0];
|
|
67902
|
+
const lastBeat = h.beats[h.beats.length - 1];
|
|
67903
|
+
// 1. put direct diagonal line.
|
|
67904
|
+
drawingInfo.startBeat = firstBeat;
|
|
67905
|
+
drawingInfo.startX = this.getBeatX(firstBeat, BeatXPosition.Stem);
|
|
67906
|
+
drawingInfo.startY =
|
|
67907
|
+
direction === BeamDirection.Up
|
|
67908
|
+
? this.getFlagTopY(firstBeat, direction)
|
|
67909
|
+
: this.getFlagBottomY(firstBeat, direction);
|
|
67910
|
+
drawingInfo.endBeat = lastBeat;
|
|
67911
|
+
drawingInfo.endX = this.getBeatX(lastBeat, BeatXPosition.Stem);
|
|
67912
|
+
drawingInfo.endY =
|
|
67913
|
+
direction === BeamDirection.Up
|
|
67914
|
+
? this.getFlagTopY(lastBeat, direction)
|
|
67915
|
+
: this.getFlagBottomY(lastBeat, direction);
|
|
67916
|
+
// 2. ensure max slope
|
|
67917
|
+
// we use the min/max notes to place the beam along their real position
|
|
67918
|
+
// we only want a maximum of 10 offset for their gradient
|
|
67919
|
+
const maxSlope = this.smuflMetrics.oneStaffSpace;
|
|
67920
|
+
if (direction === BeamDirection.Down &&
|
|
67921
|
+
drawingInfo.startY > drawingInfo.endY &&
|
|
67922
|
+
drawingInfo.startY - drawingInfo.endY > maxSlope) {
|
|
67923
|
+
drawingInfo.endY = drawingInfo.startY - maxSlope;
|
|
67713
67924
|
}
|
|
67714
|
-
|
|
67715
|
-
|
|
67925
|
+
if (direction === BeamDirection.Down &&
|
|
67926
|
+
drawingInfo.endY > drawingInfo.startY &&
|
|
67927
|
+
drawingInfo.endY - drawingInfo.startY > maxSlope) {
|
|
67928
|
+
drawingInfo.startY = drawingInfo.endY - maxSlope;
|
|
67716
67929
|
}
|
|
67717
|
-
|
|
67718
|
-
|
|
67719
|
-
|
|
67720
|
-
|
|
67721
|
-
this.addGlyph(common);
|
|
67722
|
-
super.doLayout();
|
|
67930
|
+
if (direction === BeamDirection.Up &&
|
|
67931
|
+
drawingInfo.startY < drawingInfo.endY &&
|
|
67932
|
+
drawingInfo.endY - drawingInfo.startY > maxSlope) {
|
|
67933
|
+
drawingInfo.endY = drawingInfo.startY + maxSlope;
|
|
67723
67934
|
}
|
|
67724
|
-
|
|
67725
|
-
|
|
67726
|
-
|
|
67727
|
-
|
|
67935
|
+
if (direction === BeamDirection.Up &&
|
|
67936
|
+
drawingInfo.endY < drawingInfo.startY &&
|
|
67937
|
+
drawingInfo.startY - drawingInfo.endY > maxSlope) {
|
|
67938
|
+
drawingInfo.startY = drawingInfo.endY + maxSlope;
|
|
67728
67939
|
}
|
|
67729
|
-
|
|
67730
|
-
|
|
67731
|
-
|
|
67732
|
-
|
|
67733
|
-
|
|
67734
|
-
|
|
67735
|
-
|
|
67736
|
-
|
|
67737
|
-
|
|
67738
|
-
|
|
67940
|
+
return drawingInfo;
|
|
67941
|
+
}
|
|
67942
|
+
get beamSpacing() {
|
|
67943
|
+
return this.smuflMetrics.beamSpacing;
|
|
67944
|
+
}
|
|
67945
|
+
get beamThickness() {
|
|
67946
|
+
return this.smuflMetrics.beamThickness;
|
|
67947
|
+
}
|
|
67948
|
+
ensureBeamDrawingInfo(h, direction) {
|
|
67949
|
+
if (h.drawingInfos.has(direction)) {
|
|
67950
|
+
return;
|
|
67739
67951
|
}
|
|
67740
|
-
|
|
67741
|
-
|
|
67742
|
-
|
|
67743
|
-
|
|
67744
|
-
|
|
67745
|
-
|
|
67746
|
-
|
|
67747
|
-
|
|
67748
|
-
|
|
67952
|
+
// the beaming logic works like this:
|
|
67953
|
+
// 1. we take the first and last note, add the stem, and put a diagnal line between them.
|
|
67954
|
+
// 2. the height of the diagonal line must not exceed a max height,
|
|
67955
|
+
// - if this is the case, the line on the more distant note just gets longer
|
|
67956
|
+
// 3. any middle elements (notes or rests) shift this diagonal line up/down to avoid overlaps
|
|
67957
|
+
const drawingInfo = this.initializeBeamDrawingInfo(h, direction);
|
|
67958
|
+
h.drawingInfos.set(direction, drawingInfo);
|
|
67959
|
+
const isRest = h.isRestBeamHelper;
|
|
67960
|
+
const scale = h.graceType !== GraceType.None ? EngravingSettings.GraceScale : 1;
|
|
67961
|
+
const barCount = ModelUtils.getIndex(h.shortestDuration) - 2;
|
|
67962
|
+
// 3. adjust beam drawing order
|
|
67963
|
+
// we can only draw up to 2 beams towards the noteheads, then we have to grow to the other side
|
|
67964
|
+
// here we shift accordingly
|
|
67965
|
+
let barDrawingShift = 0;
|
|
67966
|
+
if (barCount > 2 && !isRest) {
|
|
67967
|
+
const beamSpacing = this.beamSpacing * scale;
|
|
67968
|
+
const beamThickness = this.beamThickness * scale;
|
|
67969
|
+
const totalBarsHeight = barCount * beamThickness + (barCount - 1) * beamSpacing;
|
|
67970
|
+
if (direction === BeamDirection.Up) {
|
|
67971
|
+
const bottomBarY = drawingInfo.startY + 2 * beamThickness + beamSpacing;
|
|
67972
|
+
const barTopY = bottomBarY - totalBarsHeight;
|
|
67973
|
+
const diff = drawingInfo.startY - barTopY;
|
|
67974
|
+
if (diff > 0) {
|
|
67975
|
+
barDrawingShift = diff * -1;
|
|
67976
|
+
drawingInfo.startY -= diff;
|
|
67977
|
+
drawingInfo.endY -= diff;
|
|
67978
|
+
}
|
|
67979
|
+
}
|
|
67980
|
+
else {
|
|
67981
|
+
const topBarY = drawingInfo.startY - 2 * beamThickness + beamSpacing;
|
|
67982
|
+
const barBottomY = topBarY + totalBarsHeight;
|
|
67983
|
+
const diff = barBottomY - drawingInfo.startY;
|
|
67984
|
+
if (diff > 0) {
|
|
67985
|
+
barDrawingShift = diff;
|
|
67986
|
+
drawingInfo.startY += diff;
|
|
67987
|
+
drawingInfo.endY += diff;
|
|
67988
|
+
}
|
|
67989
|
+
}
|
|
67990
|
+
}
|
|
67991
|
+
// 4. let middle elements shift up/down
|
|
67992
|
+
if (h.beats.length > 1) {
|
|
67993
|
+
// check if highest note shifts bar up or down
|
|
67994
|
+
if (direction === BeamDirection.Up) {
|
|
67995
|
+
const yNeededForHighestNote = barDrawingShift + this.getFlagTopY(h.beatOfHighestNote, direction);
|
|
67996
|
+
const yGivenByCurrentValues = drawingInfo.calcY(this.getBeatX(h.beatOfHighestNote, BeatXPosition.Stem));
|
|
67997
|
+
const diff = yGivenByCurrentValues - yNeededForHighestNote;
|
|
67998
|
+
if (diff > 0) {
|
|
67999
|
+
drawingInfo.startY -= diff;
|
|
68000
|
+
drawingInfo.endY -= diff;
|
|
68001
|
+
}
|
|
68002
|
+
}
|
|
68003
|
+
else {
|
|
68004
|
+
const yNeededForLowestNote = barDrawingShift + this.getFlagBottomY(h.beatOfLowestNote, direction);
|
|
68005
|
+
const yGivenByCurrentValues = drawingInfo.calcY(this.getBeatX(h.beatOfLowestNote, BeatXPosition.Stem));
|
|
68006
|
+
const diff = yNeededForLowestNote - yGivenByCurrentValues;
|
|
68007
|
+
if (diff > 0) {
|
|
68008
|
+
drawingInfo.startY += diff;
|
|
68009
|
+
drawingInfo.endY += diff;
|
|
68010
|
+
}
|
|
68011
|
+
}
|
|
68012
|
+
// check if rest shifts bar up or down
|
|
68013
|
+
let barSpacing = 0;
|
|
68014
|
+
if (h.restBeats.length > 0) {
|
|
68015
|
+
// space needed for the bars, rests need to be below them
|
|
68016
|
+
const scaleMod = h.graceType !== GraceType.None ? EngravingSettings.GraceScale : 1;
|
|
68017
|
+
barSpacing = barCount * (this.beamSpacing + this.beamThickness) * scaleMod;
|
|
68018
|
+
}
|
|
68019
|
+
for (const b of h.restBeats) {
|
|
68020
|
+
// rest beats which are "under" the beam
|
|
68021
|
+
if (b.isRest && b.index < h.beats[h.beats.length - 1].index) {
|
|
68022
|
+
if (direction === BeamDirection.Up) {
|
|
68023
|
+
const yNeededForRest = this.getBeatContainer(b).getBoundingBoxTop() - barSpacing;
|
|
68024
|
+
const yGivenByCurrentValues = drawingInfo.calcY(this.getBeatX(b, BeatXPosition.Stem));
|
|
68025
|
+
const diff = yGivenByCurrentValues - yNeededForRest;
|
|
68026
|
+
if (diff > 0) {
|
|
68027
|
+
drawingInfo.startY -= diff;
|
|
68028
|
+
drawingInfo.endY -= diff;
|
|
68029
|
+
}
|
|
68030
|
+
}
|
|
68031
|
+
else if (direction === BeamDirection.Down) {
|
|
68032
|
+
const yNeededForRest = this.getBeatContainer(b).getBoundingBoxBottom() + barSpacing;
|
|
68033
|
+
const yGivenByCurrentValues = drawingInfo.calcY(this.getBeatX(b, BeatXPosition.Stem));
|
|
68034
|
+
const diff = yNeededForRest - yGivenByCurrentValues;
|
|
68035
|
+
if (diff > 0) {
|
|
68036
|
+
drawingInfo.startY += diff;
|
|
68037
|
+
drawingInfo.endY += diff;
|
|
68038
|
+
}
|
|
68039
|
+
}
|
|
68040
|
+
}
|
|
68041
|
+
}
|
|
68042
|
+
// check if slash shifts bar up or down
|
|
68043
|
+
if (h.slashBeats.length > 0) {
|
|
68044
|
+
for (const b of h.slashBeats) {
|
|
68045
|
+
const yGivenByCurrentValues = drawingInfo.calcY(this.getBeatX(b, BeatXPosition.Stem));
|
|
68046
|
+
const yNeededForSlash = h.direction === BeamDirection.Up
|
|
68047
|
+
? this.getFlagTopY(b, h.direction)
|
|
68048
|
+
: this.getFlagBottomY(b, h.direction);
|
|
68049
|
+
const diff = yNeededForSlash - yGivenByCurrentValues;
|
|
68050
|
+
if (diff > 0) {
|
|
68051
|
+
drawingInfo.startY += diff;
|
|
68052
|
+
drawingInfo.endY += diff;
|
|
68053
|
+
}
|
|
68054
|
+
}
|
|
67749
68055
|
}
|
|
67750
|
-
this.width += openParenthesis.width;
|
|
67751
|
-
this.addGlyph(openParenthesis);
|
|
67752
|
-
const closeParenthesis = new GhostParenthesisGlyph(false);
|
|
67753
|
-
closeParenthesis.renderer = this.renderer;
|
|
67754
|
-
closeParenthesis.x = this.width;
|
|
67755
|
-
closeParenthesis.y = -numberHeight;
|
|
67756
|
-
closeParenthesis.height = numberHeight * 2;
|
|
67757
|
-
closeParenthesis.doLayout();
|
|
67758
|
-
this.addGlyph(closeParenthesis);
|
|
67759
|
-
this.width += closeParenthesis.width;
|
|
67760
68056
|
}
|
|
67761
68057
|
}
|
|
67762
|
-
|
|
67763
|
-
|
|
67764
|
-
/**
|
|
67765
|
-
* @internal
|
|
67766
|
-
*/
|
|
67767
|
-
class ScoreTimeSignatureGlyph extends TimeSignatureGlyph {
|
|
67768
|
-
get commonScale() {
|
|
67769
|
-
return 1;
|
|
68058
|
+
getMinLineOfBeat(_beat) {
|
|
68059
|
+
return 0;
|
|
67770
68060
|
}
|
|
67771
|
-
|
|
67772
|
-
return
|
|
68061
|
+
getMaxLineOfBeat(_beat) {
|
|
68062
|
+
return 0;
|
|
67773
68063
|
}
|
|
67774
68064
|
}
|
|
67775
68065
|
|
|
@@ -67782,27 +68072,9 @@ class NumberedBarRenderer extends LineBarRenderer {
|
|
|
67782
68072
|
simpleWhammyOverflow = 0;
|
|
67783
68073
|
_isOnlyNumbered;
|
|
67784
68074
|
shortestDuration = Duration.QuadrupleWhole;
|
|
67785
|
-
lowestOctave = null;
|
|
67786
|
-
highestOctave = null;
|
|
67787
|
-
octaves = new Map();
|
|
67788
68075
|
get dotSpacing() {
|
|
67789
68076
|
return this.smuflMetrics.glyphHeights.get(MusicFontSymbol.AugmentationDot) * 2;
|
|
67790
68077
|
}
|
|
67791
|
-
registerOctave(beat, octave) {
|
|
67792
|
-
this.octaves.set(beat, octave);
|
|
67793
|
-
if (this.lowestOctave === null) {
|
|
67794
|
-
this.lowestOctave = octave;
|
|
67795
|
-
this.highestOctave = octave;
|
|
67796
|
-
}
|
|
67797
|
-
else {
|
|
67798
|
-
if (octave < this.lowestOctave) {
|
|
67799
|
-
this.lowestOctave = octave;
|
|
67800
|
-
}
|
|
67801
|
-
if (octave > this.highestOctave) {
|
|
67802
|
-
this.highestOctave = octave;
|
|
67803
|
-
}
|
|
67804
|
-
}
|
|
67805
|
-
}
|
|
67806
68078
|
get repeatsBarSubElement() {
|
|
67807
68079
|
return BarSubElement.NumberedRepeats;
|
|
67808
68080
|
}
|
|
@@ -67840,89 +68112,61 @@ class NumberedBarRenderer extends LineBarRenderer {
|
|
|
67840
68112
|
get tupletSubElement() {
|
|
67841
68113
|
return BeatSubElement.NumberedTuplet;
|
|
67842
68114
|
}
|
|
67843
|
-
|
|
67844
|
-
|
|
67845
|
-
if (this.voiceContainer.tupletGroups.size > 0) {
|
|
67846
|
-
this.registerOverflowTop(this.tupletSize);
|
|
67847
|
-
}
|
|
67848
|
-
if (!this.bar.isEmpty) {
|
|
67849
|
-
const barCount = ModelUtils.getIndex(this.shortestDuration) - 2;
|
|
67850
|
-
const dotSpacing = this.dotSpacing;
|
|
67851
|
-
if (barCount > 0) {
|
|
67852
|
-
const barSpacing = this.smuflMetrics.numberedBarRendererBarSpacing;
|
|
67853
|
-
const barSize = this.smuflMetrics.numberedBarRendererBarSize;
|
|
67854
|
-
const barOverflow = (barCount - 1) * barSpacing + barSize;
|
|
67855
|
-
let dotOverflow = 0;
|
|
67856
|
-
const lowestOctave = this.lowestOctave;
|
|
67857
|
-
if (lowestOctave !== null) {
|
|
67858
|
-
dotOverflow =
|
|
67859
|
-
Math.abs(lowestOctave) * dotSpacing +
|
|
67860
|
-
this.smuflMetrics.glyphHeights.get(MusicFontSymbol.AugmentationDot);
|
|
67861
|
-
}
|
|
67862
|
-
this.registerOverflowBottom(barOverflow + dotOverflow);
|
|
67863
|
-
}
|
|
67864
|
-
const highestOctave = this.highestOctave;
|
|
67865
|
-
if (highestOctave !== null) {
|
|
67866
|
-
const dotOverflow = Math.abs(highestOctave) * dotSpacing +
|
|
67867
|
-
this.smuflMetrics.glyphHeights.get(MusicFontSymbol.AugmentationDot);
|
|
67868
|
-
this.registerOverflowTop(dotOverflow);
|
|
67869
|
-
}
|
|
67870
|
-
}
|
|
68115
|
+
shouldPaintBeamingHelper(_h) {
|
|
68116
|
+
return true;
|
|
67871
68117
|
}
|
|
67872
68118
|
paintFlag(cx, cy, canvas, h, flagsElement) {
|
|
67873
68119
|
this.paintBar(cx, cy, canvas, h, flagsElement);
|
|
67874
68120
|
}
|
|
67875
68121
|
paintBar(cx, cy, canvas, h, flagsElement) {
|
|
67876
|
-
if (h.beats.length === 0) {
|
|
68122
|
+
if (h.beats.length === 0 || h.graceType !== GraceType.None) {
|
|
67877
68123
|
return;
|
|
67878
68124
|
}
|
|
67879
|
-
const res = this.resources;
|
|
67880
68125
|
for (let i = 0, j = h.beats.length; i < j; i++) {
|
|
67881
68126
|
const beat = h.beats[i];
|
|
67882
68127
|
const _ = ElementStyleHelper.beat(canvas, flagsElement, beat);
|
|
67883
68128
|
try {
|
|
67884
|
-
|
|
67885
|
-
|
|
67886
|
-
|
|
67887
|
-
|
|
67888
|
-
|
|
67889
|
-
|
|
67890
|
-
|
|
67891
|
-
|
|
67892
|
-
const beamY = this.calculateBeamY(h, beatLineX);
|
|
67893
|
-
for (let barIndex = 0; barIndex < barCount; barIndex++) {
|
|
67894
|
-
let barStartX = 0;
|
|
67895
|
-
let barEndX = 0;
|
|
67896
|
-
let barStartY = 0;
|
|
67897
|
-
const barY = barStart + barIndex * barSpacing;
|
|
67898
|
-
if (i === h.beats.length - 1) {
|
|
67899
|
-
barStartX = beatLineX;
|
|
67900
|
-
barEndX = this.getBeatX(beat, BeatXPosition.PostNotes);
|
|
67901
|
-
}
|
|
67902
|
-
else {
|
|
67903
|
-
barStartX = beatLineX;
|
|
67904
|
-
barEndX = this.getBeatX(h.beats[i + 1], BeatXPosition.PreNotes);
|
|
67905
|
-
}
|
|
67906
|
-
barStartY = barY + beamY;
|
|
67907
|
-
canvas.fillRect(cx + this.x + barStartX, barStartY, barEndX - barStartX, barSize);
|
|
68129
|
+
const direction = this.getBeamDirection(h);
|
|
68130
|
+
const isGrace = h.graceType !== GraceType.None;
|
|
68131
|
+
const scaleMod = isGrace ? EngravingSettings.GraceScale : 1;
|
|
68132
|
+
let barSpacing = (this.beamSpacing + this.beamThickness) * scaleMod;
|
|
68133
|
+
let barSize = this.beamThickness * scaleMod;
|
|
68134
|
+
if (direction === BeamDirection.Down) {
|
|
68135
|
+
barSpacing = -barSpacing;
|
|
68136
|
+
barSize = -barSize;
|
|
67908
68137
|
}
|
|
67909
|
-
let
|
|
67910
|
-
|
|
67911
|
-
let
|
|
67912
|
-
let
|
|
67913
|
-
if (
|
|
67914
|
-
|
|
67915
|
-
|
|
68138
|
+
let barCount = ModelUtils.getIndex(beat.duration) - 2;
|
|
68139
|
+
let beatLineX = this.getBeatX(beat, BeatXPosition.PreNotes);
|
|
68140
|
+
let barStartX = 0;
|
|
68141
|
+
let barEndX = 0;
|
|
68142
|
+
if (i === h.beats.length - 1) {
|
|
68143
|
+
barStartX = beatLineX;
|
|
68144
|
+
barEndX = this.getBeatX(beat, BeatXPosition.PostNotes);
|
|
67916
68145
|
}
|
|
67917
|
-
else
|
|
67918
|
-
|
|
67919
|
-
|
|
68146
|
+
else {
|
|
68147
|
+
barStartX = beatLineX;
|
|
68148
|
+
barEndX = this.getBeatX(h.beats[i + 1], BeatXPosition.PreNotes);
|
|
67920
68149
|
}
|
|
67921
|
-
const
|
|
67922
|
-
|
|
67923
|
-
|
|
67924
|
-
|
|
67925
|
-
|
|
68150
|
+
const barStart = cy + this.y + this.calculateBeamY(h, beatLineX);
|
|
68151
|
+
for (let barIndex = 0; barIndex < barCount; barIndex++) {
|
|
68152
|
+
const barY = barStart + barIndex * barSpacing;
|
|
68153
|
+
LineBarRenderer.paintSingleBar(canvas, cx + this.x + barStartX, barY, cx + this.x + barEndX, barY, barSize);
|
|
68154
|
+
}
|
|
68155
|
+
// dashes for additional numbers
|
|
68156
|
+
const container = this.voiceContainer.getBeatContainer(beat);
|
|
68157
|
+
if (container && container.hasAdditionalNumbers) {
|
|
68158
|
+
for (const additionalNumber of container.iterateAdditionalNumbers()) {
|
|
68159
|
+
barCount = additionalNumber.barCount;
|
|
68160
|
+
beatLineX =
|
|
68161
|
+
this.beatGlyphsStart + additionalNumber.x + additionalNumber.getBeatX(BeatXPosition.PreNotes, false);
|
|
68162
|
+
for (let barIndex = 0; barIndex < barCount; barIndex++) {
|
|
68163
|
+
const barY = barStart + barIndex * barSpacing;
|
|
68164
|
+
const additionalBarEndX = this.beatGlyphsStart +
|
|
68165
|
+
additionalNumber.x +
|
|
68166
|
+
additionalNumber.getBeatX(BeatXPosition.PostNotes, false);
|
|
68167
|
+
LineBarRenderer.paintSingleBar(canvas, cx + this.x + beatLineX, barY, cx + this.x + additionalBarEndX, barY, barSize);
|
|
68168
|
+
}
|
|
68169
|
+
}
|
|
67926
68170
|
}
|
|
67927
68171
|
}
|
|
67928
68172
|
finally {
|
|
@@ -67930,20 +68174,58 @@ class NumberedBarRenderer extends LineBarRenderer {
|
|
|
67930
68174
|
}
|
|
67931
68175
|
}
|
|
67932
68176
|
}
|
|
68177
|
+
calculateOverflows(rendererTop, rendererBottom) {
|
|
68178
|
+
super.calculateOverflows(rendererTop, rendererBottom);
|
|
68179
|
+
if (this.bar.isEmpty) {
|
|
68180
|
+
return;
|
|
68181
|
+
}
|
|
68182
|
+
this.calculateBeamingOverflows(rendererTop, rendererBottom);
|
|
68183
|
+
}
|
|
67933
68184
|
getNoteLine(_note) {
|
|
67934
68185
|
return 0;
|
|
67935
68186
|
}
|
|
67936
|
-
|
|
67937
|
-
|
|
67938
|
-
|
|
67939
|
-
|
|
67940
|
-
|
|
68187
|
+
_calculateBarHeight(beat) {
|
|
68188
|
+
const barCount = ModelUtils.getIndex(beat.duration) - 2;
|
|
68189
|
+
let barHeight = 0;
|
|
68190
|
+
if (barCount > 0) {
|
|
68191
|
+
const smufl = this.smuflMetrics;
|
|
68192
|
+
barHeight =
|
|
68193
|
+
smufl.numberedBarRendererBarSpacing +
|
|
68194
|
+
barCount * (smufl.numberedBarRendererBarSpacing + smufl.numberedBarRendererBarSize);
|
|
68195
|
+
}
|
|
68196
|
+
return barHeight;
|
|
67941
68197
|
}
|
|
67942
|
-
getFlagTopY(
|
|
67943
|
-
|
|
68198
|
+
getFlagTopY(beat, direction) {
|
|
68199
|
+
const barHeight = this._calculateBarHeight(beat);
|
|
68200
|
+
const container = this.voiceContainer.getBeatContainer(beat);
|
|
68201
|
+
if (!container) {
|
|
68202
|
+
if (direction === BeamDirection.Up) {
|
|
68203
|
+
return this.voiceContainer.getBoundingBoxTop() - barHeight;
|
|
68204
|
+
}
|
|
68205
|
+
return this.voiceContainer.getBoundingBoxBottom();
|
|
68206
|
+
}
|
|
68207
|
+
if (direction === BeamDirection.Up) {
|
|
68208
|
+
return container.getBoundingBoxTop() - barHeight;
|
|
68209
|
+
}
|
|
68210
|
+
return container.getBoundingBoxBottom();
|
|
67944
68211
|
}
|
|
67945
|
-
getFlagBottomY(
|
|
67946
|
-
|
|
68212
|
+
getFlagBottomY(beat, direction) {
|
|
68213
|
+
const barHeight = this._calculateBarHeight(beat);
|
|
68214
|
+
const container = this.voiceContainer.getBeatContainer(beat);
|
|
68215
|
+
if (!container) {
|
|
68216
|
+
if (direction === BeamDirection.Down) {
|
|
68217
|
+
return this.voiceContainer.getBoundingBoxBottom() + barHeight;
|
|
68218
|
+
}
|
|
68219
|
+
return this.getLineY(0);
|
|
68220
|
+
}
|
|
68221
|
+
if (direction === BeamDirection.Down) {
|
|
68222
|
+
return container.getBoundingBoxBottom() + barHeight;
|
|
68223
|
+
}
|
|
68224
|
+
return this.getLineY(0);
|
|
68225
|
+
}
|
|
68226
|
+
completeBeamingHelper(helper) {
|
|
68227
|
+
super.completeBeamingHelper(helper);
|
|
68228
|
+
helper.direction = BeamDirection.Down;
|
|
67947
68229
|
}
|
|
67948
68230
|
getBeamDirection(_helper) {
|
|
67949
68231
|
return BeamDirection.Down;
|
|
@@ -67958,13 +68240,26 @@ class NumberedBarRenderer extends LineBarRenderer {
|
|
|
67958
68240
|
}
|
|
67959
68241
|
return y;
|
|
67960
68242
|
}
|
|
67961
|
-
calculateBeamYWithDirection(
|
|
67962
|
-
|
|
67963
|
-
|
|
68243
|
+
calculateBeamYWithDirection(h, _x, direction) {
|
|
68244
|
+
if (h.beats.length === 0) {
|
|
68245
|
+
return this.getLineY(0);
|
|
68246
|
+
}
|
|
68247
|
+
this.ensureBeamDrawingInfo(h, direction);
|
|
68248
|
+
const info = h.drawingInfos.get(direction);
|
|
68249
|
+
if (direction === BeamDirection.Up) {
|
|
68250
|
+
return Math.min(info.startY, info.endY);
|
|
68251
|
+
}
|
|
68252
|
+
else {
|
|
68253
|
+
return Math.max(info.startY, info.endY);
|
|
68254
|
+
}
|
|
67964
68255
|
}
|
|
67965
|
-
getBarLineStart(
|
|
67966
|
-
|
|
67967
|
-
|
|
68256
|
+
getBarLineStart(beat, _direction) {
|
|
68257
|
+
// NOTE: this is only for the overflow calculation, this renderer has a custom bar drawing logic
|
|
68258
|
+
const container = this.voiceContainer.getBeatContainer(beat);
|
|
68259
|
+
if (!container) {
|
|
68260
|
+
return this.voiceContainer.getBoundingBoxTop();
|
|
68261
|
+
}
|
|
68262
|
+
return container.getBoundingBoxTop();
|
|
67968
68263
|
}
|
|
67969
68264
|
createPreBeatGlyphs() {
|
|
67970
68265
|
this.wasFirstOfStaff = this.isFirstOfStaff;
|
|
@@ -67972,14 +68267,10 @@ class NumberedBarRenderer extends LineBarRenderer {
|
|
|
67972
68267
|
this.addPreBeatGlyph(new BarLineGlyph(false, this.bar.staff.track.score.stylesheet.extendBarLines));
|
|
67973
68268
|
}
|
|
67974
68269
|
this.createLinePreBeatGlyphs();
|
|
68270
|
+
this.createStartSpacing();
|
|
67975
68271
|
this.addPreBeatGlyph(new BarNumberGlyph(0, this.getLineHeight(-0.5), this.bar.index + 1));
|
|
67976
68272
|
}
|
|
67977
68273
|
createLinePreBeatGlyphs() {
|
|
67978
|
-
// Key signature
|
|
67979
|
-
if (!this.bar.previousBar || this.bar.keySignature !== this.bar.previousBar.keySignature) {
|
|
67980
|
-
this.createStartSpacing();
|
|
67981
|
-
this._createKeySignatureGlyphs();
|
|
67982
|
-
}
|
|
67983
68274
|
if (this._isOnlyNumbered &&
|
|
67984
68275
|
(!this.bar.previousBar ||
|
|
67985
68276
|
(this.bar.previousBar &&
|
|
@@ -67995,11 +68286,7 @@ class NumberedBarRenderer extends LineBarRenderer {
|
|
|
67995
68286
|
this._createTimeSignatureGlyphs();
|
|
67996
68287
|
}
|
|
67997
68288
|
}
|
|
67998
|
-
_createKeySignatureGlyphs() {
|
|
67999
|
-
this.addPreBeatGlyph(new NumberedKeySignatureGlyph(0, this.getLineY(0), this.bar.keySignature, this.bar.keySignatureType));
|
|
68000
|
-
}
|
|
68001
68289
|
_createTimeSignatureGlyphs() {
|
|
68002
|
-
this.addPreBeatGlyph(new SpacingGlyph(0, 0, this.smuflMetrics.oneStaffSpace));
|
|
68003
68290
|
const masterBar = this.bar.masterBar;
|
|
68004
68291
|
const g = new ScoreTimeSignatureGlyph(0, this.getLineY(0), masterBar.timeSignatureNumerator, masterBar.timeSignatureDenominator, masterBar.timeSignatureCommon, masterBar.isFreeTime &&
|
|
68005
68292
|
(masterBar.previousMasterBar == null ||
|
|
@@ -68017,12 +68304,40 @@ class NumberedBarRenderer extends LineBarRenderer {
|
|
|
68017
68304
|
return;
|
|
68018
68305
|
}
|
|
68019
68306
|
super.createVoiceGlyphs(v);
|
|
68307
|
+
const absoluteStart = this.bar.masterBar.start;
|
|
68020
68308
|
for (const b of v.beats) {
|
|
68021
|
-
|
|
68309
|
+
const mainContainer = new NumberedBeatContainerGlyph(b);
|
|
68310
|
+
this.addBeatGlyph(mainContainer);
|
|
68311
|
+
// create dashes and filler glyphs
|
|
68312
|
+
// we want a glyph on every quarter tick
|
|
68313
|
+
if (b.duration < Duration.Quarter) {
|
|
68314
|
+
const endTick = b.displayStart + b.displayDuration;
|
|
68315
|
+
let dashTick = b.displayStart + MidiUtils.QuarterTime;
|
|
68316
|
+
while (dashTick < endTick) {
|
|
68317
|
+
const isFullTick = endTick - dashTick >= MidiUtils.QuarterTime;
|
|
68318
|
+
if (isFullTick) {
|
|
68319
|
+
const dash = new NumberedDashBeatContainerGlyph(v.index, absoluteStart + dashTick);
|
|
68320
|
+
this.addBeatGlyph(dash);
|
|
68321
|
+
mainContainer.addDash(dash);
|
|
68322
|
+
}
|
|
68323
|
+
else if (b.duration === Duration.Half && b.dots > 1) {
|
|
68324
|
+
const remainingTickNumber = new NumberedNoteBeatContainerGlyphBase(b, absoluteStart + dashTick, endTick - dashTick);
|
|
68325
|
+
this.addBeatGlyph(remainingTickNumber);
|
|
68326
|
+
mainContainer.addNotes(remainingTickNumber);
|
|
68327
|
+
}
|
|
68328
|
+
dashTick += MidiUtils.QuarterTime;
|
|
68329
|
+
}
|
|
68330
|
+
}
|
|
68022
68331
|
}
|
|
68023
68332
|
}
|
|
68024
68333
|
paintBeamingStem(_beat, _cy, _x, _topY, _bottomY, _canvas) {
|
|
68025
68334
|
}
|
|
68335
|
+
get beamSpacing() {
|
|
68336
|
+
return this.smuflMetrics.numberedBarRendererBarSpacing;
|
|
68337
|
+
}
|
|
68338
|
+
get beamThickness() {
|
|
68339
|
+
return this.smuflMetrics.numberedBarRendererBarSize;
|
|
68340
|
+
}
|
|
68026
68341
|
paintBeamHelper(cx, cy, canvas, h, flagsElement, beamsElement) {
|
|
68027
68342
|
if (h.voice?.index === 0) {
|
|
68028
68343
|
super.paintBeamHelper(cx, cy, canvas, h, flagsElement, beamsElement);
|
|
@@ -69554,6 +69869,7 @@ class ScoreWhammyBarGlyph extends ScoreHelperNotesBaseGlyph {
|
|
|
69554
69869
|
break;
|
|
69555
69870
|
}
|
|
69556
69871
|
super.doLayout();
|
|
69872
|
+
this.width = this.width / 2;
|
|
69557
69873
|
}
|
|
69558
69874
|
paint(cx, cy, canvas) {
|
|
69559
69875
|
const beat = this._beat;
|
|
@@ -70312,6 +70628,10 @@ class ScoreBendGlyph extends ScoreHelperNotesBaseGlyph {
|
|
|
70312
70628
|
this._beat = container.beat;
|
|
70313
70629
|
this._container = container;
|
|
70314
70630
|
}
|
|
70631
|
+
doLayout() {
|
|
70632
|
+
super.doLayout();
|
|
70633
|
+
this.width = 0;
|
|
70634
|
+
}
|
|
70315
70635
|
getBoundingBoxTop() {
|
|
70316
70636
|
return super.getBoundingBoxTop() - this._calculateMaxSlurHeight(BeamDirection.Up);
|
|
70317
70637
|
}
|
|
@@ -71171,7 +71491,6 @@ class ScoreBeatContainerGlyph extends BeatContainerGlyph {
|
|
|
71171
71491
|
updateWidth() {
|
|
71172
71492
|
super.updateWidth();
|
|
71173
71493
|
this.width += this._flagStretch;
|
|
71174
|
-
this.minWidth += this._flagStretch;
|
|
71175
71494
|
}
|
|
71176
71495
|
}
|
|
71177
71496
|
|
|
@@ -71840,7 +72159,6 @@ class SlashBeatContainerGlyph extends BeatContainerGlyph {
|
|
|
71840
72159
|
updateWidth() {
|
|
71841
72160
|
super.updateWidth();
|
|
71842
72161
|
this.width += this._flagStretch;
|
|
71843
|
-
this.minWidth += this._flagStretch;
|
|
71844
72162
|
}
|
|
71845
72163
|
}
|
|
71846
72164
|
|
|
@@ -73589,7 +73907,9 @@ class Environment {
|
|
|
73589
73907
|
]),
|
|
73590
73908
|
//
|
|
73591
73909
|
// Numbered
|
|
73592
|
-
new NumberedBarRendererFactory([
|
|
73910
|
+
new NumberedBarRendererFactory([
|
|
73911
|
+
{ effect: new NumberedBarKeySignatureEffectInfo(), mode: EffectBandMode.OwnedTop, order: 1000 }
|
|
73912
|
+
]),
|
|
73593
73913
|
//
|
|
73594
73914
|
// Tabs
|
|
73595
73915
|
new TabBarRendererFactory([
|