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