@tspro/web-music-score 3.0.1 → 3.1.0

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.
@@ -1,7 +1,7 @@
1
- /* WebMusicScore v3.0.1 | (c) 2023 PahkaSoft | MIT License | Includes: Tone.js (MIT License) */
1
+ /* WebMusicScore v3.1.0 | (c) 2023 PahkaSoft | MIT License | Includes: Tone.js (MIT License) */
2
2
  import {
3
3
  __publicField
4
- } from "../chunk-4AS76G4O.mjs";
4
+ } from "../chunk-B4J3KED2.mjs";
5
5
 
6
6
  // src/score/pub/div-rect.ts
7
7
  import { Utils } from "@tspro/ts-utils-lib";
@@ -330,6 +330,13 @@ var Connective = /* @__PURE__ */ ((Connective3) => {
330
330
  Connective3[Connective3["Slide"] = 2] = "Slide";
331
331
  return Connective3;
332
332
  })(Connective || {});
333
+ var VerticalPosition = /* @__PURE__ */ ((VerticalPosition4) => {
334
+ VerticalPosition4[VerticalPosition4["Above"] = 0] = "Above";
335
+ VerticalPosition4[VerticalPosition4["Below"] = 1] = "Below";
336
+ VerticalPosition4[VerticalPosition4["Both"] = 2] = "Both";
337
+ VerticalPosition4[VerticalPosition4["Auto"] = 3] = "Auto";
338
+ return VerticalPosition4;
339
+ })(VerticalPosition || {});
333
340
  var PlayState = /* @__PURE__ */ ((PlayState2) => {
334
341
  PlayState2[PlayState2["Playing"] = 0] = "Playing";
335
342
  PlayState2[PlayState2["Paused"] = 1] = "Paused";
@@ -444,7 +451,7 @@ var MusicObject = class {
444
451
  import { Note as Note9 } from "@tspro/web-music-score/theory";
445
452
 
446
453
  // src/score/engine/obj-staff-and-tab.ts
447
- import { getTuningStrings, Note, validateTuningName } from "@tspro/web-music-score/theory";
454
+ import { getTuningStrings, Note as Note8, validateTuningName } from "@tspro/web-music-score/theory";
448
455
 
449
456
  // src/score/engine/renderer.ts
450
457
  import { Utils as Utils2, Vec2, Device } from "@tspro/ts-utils-lib";
@@ -862,260 +869,16 @@ var Renderer = class {
862
869
  };
863
870
 
864
871
  // src/score/engine/obj-staff-and-tab.ts
865
- import { MusicError as MusicError3, MusicErrorType as MusicErrorType3 } from "@tspro/web-music-score/core";
866
- import { Utils as Utils3 } from "@tspro/ts-utils-lib";
867
- var ObjStaff = class extends MusicObject {
868
- constructor(row, staffConfig) {
869
- super(row);
870
- this.row = row;
871
- this.staffConfig = staffConfig;
872
- __publicField(this, "clefImageAsset");
873
- __publicField(this, "clefLineDiatonicId");
874
- __publicField(this, "topLineDiatonicId");
875
- __publicField(this, "middleLineDiatonicId");
876
- __publicField(this, "bottomLineDiatonicId");
877
- __publicField(this, "minDiatonicId");
878
- __publicField(this, "maxDiatonicId");
879
- __publicField(this, "joinedGrandStaff");
880
- __publicField(this, "topLineY", 0);
881
- __publicField(this, "bottomLineY", 0);
882
- __publicField(this, "objects", []);
883
- __publicField(this, "mi");
884
- const getDiatonicId = (noteName, isOctaveDown) => Note.getNote(noteName).diatonicId - (isOctaveDown ? 7 : 0);
885
- if (staffConfig.clef === "G" /* G */) {
886
- this.clefImageAsset = 0 /* TrebleClefPng */;
887
- this.clefLineDiatonicId = getDiatonicId("G4", staffConfig.isOctaveDown === true);
888
- this.middleLineDiatonicId = this.clefLineDiatonicId + 2;
889
- } else {
890
- this.clefImageAsset = 1 /* BassClefPng */;
891
- this.clefLineDiatonicId = getDiatonicId("F3", staffConfig.isOctaveDown === true);
892
- this.middleLineDiatonicId = this.clefLineDiatonicId - 2;
893
- }
894
- this.topLineDiatonicId = this.middleLineDiatonicId + 4;
895
- this.bottomLineDiatonicId = this.middleLineDiatonicId - 4;
896
- this.minDiatonicId = staffConfig.minNote !== void 0 ? Math.min(getDiatonicId(staffConfig.minNote, false), this.bottomLineDiatonicId) : void 0;
897
- this.maxDiatonicId = staffConfig.maxNote !== void 0 ? Math.max(getDiatonicId(staffConfig.maxNote, false), this.topLineDiatonicId) : void 0;
898
- this.mi = new MStaff(this);
899
- }
900
- getMusicInterface() {
901
- return this.mi;
902
- }
903
- get isOctaveDown() {
904
- return this.staffConfig.isOctaveDown === true;
905
- }
906
- getTopLineY() {
907
- return this.topLineY;
908
- }
909
- getMiddleLineY() {
910
- return (this.topLineY + this.bottomLineY) / 2;
911
- }
912
- getBottomLineY() {
913
- return this.bottomLineY;
914
- }
915
- joinGrandStaff(staff) {
916
- if (staff !== this) {
917
- this.joinedGrandStaff = staff;
918
- }
919
- }
920
- getLineSpacing() {
921
- return (this.bottomLineY - this.topLineY) / 4;
922
- }
923
- getDiatonicSpacing() {
924
- return this.getLineSpacing() / 2;
925
- }
926
- containsDiatonicId(diatonicId) {
927
- Note.validateDiatonicId(diatonicId);
928
- return (this.minDiatonicId === void 0 || diatonicId >= this.minDiatonicId) && (this.maxDiatonicId === void 0 || diatonicId <= this.maxDiatonicId);
929
- }
930
- getDiatonicIdY(diatonicId) {
931
- if (this.containsDiatonicId(diatonicId)) {
932
- return this.bottomLineY + (this.bottomLineDiatonicId - diatonicId) * this.getDiatonicSpacing();
933
- } else if (this.joinedGrandStaff && this.joinedGrandStaff.containsDiatonicId(diatonicId)) {
934
- return this.joinedGrandStaff.getDiatonicIdY(diatonicId);
935
- } else {
936
- throw new MusicError3(MusicErrorType3.Score, "Staff does not contain diatonicId " + diatonicId);
937
- }
938
- }
939
- getActualStaff(diatonicId) {
940
- if (this.containsDiatonicId(diatonicId)) {
941
- return this;
942
- } else if (this.joinedGrandStaff && this.joinedGrandStaff.containsDiatonicId(diatonicId)) {
943
- return this.joinedGrandStaff;
944
- } else {
945
- throw new MusicError3(MusicErrorType3.Score, "Staff does not contain diatonicId " + diatonicId);
946
- }
947
- }
948
- getDiatonicIdAt(y) {
949
- let diatonicId = Math.round(this.bottomLineDiatonicId - (y - this.bottomLineY) / this.getDiatonicSpacing());
950
- return this.containsDiatonicId(diatonicId) ? diatonicId : void 0;
951
- }
952
- isLine(diatonicId) {
953
- return diatonicId % 2 === this.middleLineDiatonicId % 2;
954
- }
955
- isSpace(diatonicId) {
956
- return diatonicId % 2 !== this.middleLineDiatonicId % 2;
957
- }
958
- containsVoiceId(voiceId) {
959
- return !this.staffConfig.voiceIds || this.staffConfig.voiceIds.includes(voiceId);
960
- }
961
- isGrand() {
962
- return this.staffConfig.isGrand === true;
963
- }
964
- calcTop() {
965
- let top = this.topLineY;
966
- this.objects.forEach((o) => top = Math.min(top, o.getRect().top));
967
- if (this.maxDiatonicId !== void 0) {
968
- let y = this.getDiatonicIdY(this.maxDiatonicId);
969
- let y2 = this.getDiatonicIdY(this.maxDiatonicId - 1);
970
- top = Math.min(top, y - Math.abs(y2 - y) + 1);
971
- }
972
- return top;
973
- }
974
- calcBottom() {
975
- let bottom = this.bottomLineY;
976
- this.objects.forEach((o) => bottom = Math.max(bottom, o.getRect().bottom));
977
- if (this.minDiatonicId !== void 0) {
978
- let y = this.getDiatonicIdY(this.minDiatonicId);
979
- let y2 = this.getDiatonicIdY(this.minDiatonicId + 1);
980
- bottom = Math.max(bottom, y + Math.abs(y2 - y) - 1);
981
- }
982
- return bottom;
983
- }
984
- addObject(o) {
985
- this.objects.push(o);
986
- }
987
- removeObjects() {
988
- this.objects.length = 0;
989
- }
990
- pick(x, y) {
991
- return [this];
992
- }
993
- layoutHeight(renderer) {
994
- let { unitSize } = renderer;
995
- let h = unitSize * DocumentSettings.StaffHeight;
996
- this.topLineY = -h / 2;
997
- this.bottomLineY = h / 2;
998
- this.rect = new DivRect(0, 0, this.topLineY, this.bottomLineY);
999
- }
1000
- layoutWidth(renderer) {
1001
- this.rect.left = this.row.getRect().left;
1002
- this.rect.right = this.row.getRect().right;
1003
- }
1004
- offset(dx, dy) {
1005
- this.topLineY += dy;
1006
- this.bottomLineY += dy;
1007
- this.objects.forEach((o) => {
1008
- if (o.offsetInPlace) {
1009
- o.offsetInPlace(0, dy);
1010
- } else if (o.offset) {
1011
- o.offset(0, dy);
1012
- }
1013
- });
1014
- this.rect.offsetInPlace(dx, dy);
1015
- }
1016
- draw(renderer) {
1017
- }
1018
- };
1019
- var ObjTab = class extends MusicObject {
1020
- constructor(row, tabConfig) {
1021
- super(row);
1022
- this.row = row;
1023
- this.tabConfig = tabConfig;
1024
- __publicField(this, "top", 0);
1025
- __publicField(this, "bottom", 0);
1026
- __publicField(this, "objects", []);
1027
- __publicField(this, "tuningName");
1028
- __publicField(this, "tuningStrings");
1029
- __publicField(this, "mi");
1030
- if (Utils3.Is.isArray(tabConfig.tuning)) {
1031
- this.tuningName = void 0;
1032
- this.tuningStrings = tabConfig.tuning.map((noteName) => Note.getNote(noteName)).reverse();
1033
- } else if (typeof tabConfig.tuning === "string") {
1034
- this.tuningName = validateTuningName(tabConfig.tuning);
1035
- this.tuningStrings = getTuningStrings(this.tuningName);
1036
- } else {
1037
- this.tuningName = "Standard";
1038
- this.tuningStrings = getTuningStrings(this.tuningName);
1039
- }
1040
- this.mi = new MTab(this);
1041
- }
1042
- getMusicInterface() {
1043
- return this.mi;
1044
- }
1045
- getTuningName() {
1046
- return this.tuningName;
1047
- }
1048
- getTuningStrings() {
1049
- return this.tuningStrings;
1050
- }
1051
- /** Return Y coordinate of string. */
1052
- getStringY(stringId) {
1053
- return this.top + (this.bottom - this.top) / 6 * (stringId + 0.5);
1054
- }
1055
- getTopStringY() {
1056
- return this.getStringY(0);
1057
- }
1058
- getBottomStringY() {
1059
- return this.getStringY(5);
1060
- }
1061
- getTop() {
1062
- return this.top;
1063
- }
1064
- getBottom() {
1065
- return this.bottom;
1066
- }
1067
- containsVoiceId(voiceId) {
1068
- return !this.tabConfig.voiceIds || this.tabConfig.voiceIds.includes(voiceId);
1069
- }
1070
- calcTop() {
1071
- return this.top;
1072
- }
1073
- calcBottom() {
1074
- return this.bottom;
1075
- }
1076
- addObject(o) {
1077
- this.objects.push(o);
1078
- }
1079
- removeObjects() {
1080
- this.objects.length = 0;
1081
- }
1082
- pick(x, y) {
1083
- return [this];
1084
- }
1085
- layoutHeight(renderer) {
1086
- let { unitSize } = renderer;
1087
- let h = unitSize * DocumentSettings.TabHeight;
1088
- this.top = -h / 2;
1089
- this.bottom = h / 2;
1090
- this.rect = new DivRect(0, 0, this.top, this.bottom);
1091
- }
1092
- layoutWidth(renderer) {
1093
- this.rect.left = this.row.getRect().left;
1094
- this.rect.right = this.row.getRect().right;
1095
- }
1096
- offset(dx, dy) {
1097
- this.top += dy;
1098
- this.bottom += dy;
1099
- this.objects.forEach((o) => {
1100
- if (o.offsetInPlace) {
1101
- o.offsetInPlace(0, dy);
1102
- } else if (o.offset) {
1103
- o.offset(0, dy);
1104
- }
1105
- });
1106
- this.rect.offsetInPlace(dx, dy);
1107
- }
1108
- draw(renderer) {
1109
- }
1110
- };
872
+ import { MusicError as MusicError15, MusicErrorType as MusicErrorType15 } from "@tspro/web-music-score/core";
873
+ import { Utils as Utils9 } from "@tspro/ts-utils-lib";
1111
874
 
1112
875
  // src/score/engine/obj-measure.ts
1113
- import { Utils as Utils9 } from "@tspro/ts-utils-lib";
1114
- import { getScale, Scale, validateScaleType, Note as Note8, NoteLength as NoteLength6, RhythmProps as RhythmProps4, KeySignature as KeySignature2, getDefaultKeySignature, PitchNotation, SymbolSet } from "@tspro/web-music-score/theory";
876
+ import { Utils as Utils8 } from "@tspro/ts-utils-lib";
877
+ import { getScale, Scale, validateScaleType, Note as Note7, NoteLength as NoteLength6, RhythmProps as RhythmProps4, KeySignature as KeySignature2, getDefaultKeySignature, PitchNotation, SymbolSet } from "@tspro/web-music-score/theory";
1115
878
  import { getDefaultTempo, TimeSignature, getDefaultTimeSignature } from "@tspro/web-music-score/theory";
1116
879
 
1117
880
  // src/score/engine/acc-state.ts
1118
- import { Note as Note2 } from "@tspro/web-music-score/theory";
881
+ import { Note } from "@tspro/web-music-score/theory";
1119
882
  var AccidentalState = class {
1120
883
  constructor(measure) {
1121
884
  this.measure = measure;
@@ -1123,7 +886,7 @@ var AccidentalState = class {
1123
886
  }
1124
887
  getAccidentalFromKeySignature(diatonicId) {
1125
888
  let ks = this.measure.getKeySignature();
1126
- let accNote = ks.getOrderedAccidentalNotes().find((accNote2) => accNote2.diatonicClass === Note2.getDiatonicClass(diatonicId));
889
+ let accNote = ks.getOrderedAccidentalNotes().find((accNote2) => accNote2.diatonicClass === Note.getDiatonicClass(diatonicId));
1127
890
  return accNote ? accNote.accidental : void 0;
1128
891
  }
1129
892
  setAccidental(note) {
@@ -1137,7 +900,7 @@ var AccidentalState = class {
1137
900
  };
1138
901
 
1139
902
  // src/score/engine/obj-signature.ts
1140
- import { Note as Note3, getTempoString, KeySignature } from "@tspro/web-music-score/theory";
903
+ import { Note as Note2, getTempoString, KeySignature } from "@tspro/web-music-score/theory";
1141
904
 
1142
905
  // src/score/engine/obj-image.ts
1143
906
  var ObjImage = class extends MusicObject {
@@ -1185,7 +948,7 @@ var ObjImage = class extends MusicObject {
1185
948
  };
1186
949
 
1187
950
  // src/score/engine/obj-accidental.ts
1188
- import { MusicError as MusicError4, MusicErrorType as MusicErrorType4 } from "@tspro/web-music-score/core";
951
+ import { MusicError as MusicError3, MusicErrorType as MusicErrorType3 } from "@tspro/web-music-score/core";
1189
952
  var ObjAccidental = class extends MusicObject {
1190
953
  constructor(parent, diatonicId, accidental, color = "black") {
1191
954
  super(parent);
@@ -1220,7 +983,7 @@ var ObjAccidental = class extends MusicObject {
1220
983
  this.rect = DivRect.createSections(unitSize * 1, unitSize * 1, unitSize * 1, unitSize * 1);
1221
984
  break;
1222
985
  default:
1223
- throw new MusicError4(MusicErrorType4.Score, "Invalid accidental value: " + this.accidental);
986
+ throw new MusicError3(MusicErrorType3.Score, "Invalid accidental value: " + this.accidental);
1224
987
  }
1225
988
  }
1226
989
  offset(dx, dy) {
@@ -1433,7 +1196,7 @@ var ObjText = class extends MusicObject {
1433
1196
  };
1434
1197
 
1435
1198
  // src/score/engine/obj-signature.ts
1436
- import { MusicError as MusicError5, MusicErrorType as MusicErrorType5 } from "@tspro/web-music-score/core";
1199
+ import { MusicError as MusicError4, MusicErrorType as MusicErrorType4 } from "@tspro/web-music-score/core";
1437
1200
  var ObjSignature = class extends MusicObject {
1438
1201
  constructor(measure, staff) {
1439
1202
  super(measure);
@@ -1527,9 +1290,9 @@ var ObjSignature = class extends MusicObject {
1527
1290
  }
1528
1291
  }
1529
1292
  if (bottomAccidentalDiatonicId !== void 0) {
1530
- return Note3.findNextDiatonicIdAbove(accNote.diatonicId, bottomAccidentalDiatonicId, false);
1293
+ return Note2.findNextDiatonicIdAbove(accNote.diatonicId, bottomAccidentalDiatonicId, false);
1531
1294
  } else {
1532
- throw new MusicError5(MusicErrorType5.Score, "Cannot get accidental diatonicId because note has no accidental.");
1295
+ throw new MusicError4(MusicErrorType4.Score, "Cannot get accidental diatonicId because note has no accidental.");
1533
1296
  }
1534
1297
  }
1535
1298
  pick(x, y) {
@@ -1699,12 +1462,12 @@ var ObjSignature = class extends MusicObject {
1699
1462
  };
1700
1463
 
1701
1464
  // src/score/engine/player.ts
1702
- import { Utils as Utils6 } from "@tspro/ts-utils-lib";
1465
+ import { Utils as Utils5 } from "@tspro/ts-utils-lib";
1703
1466
  import { NoteLength as NoteLength5, RhythmProps as RhythmProps3, alterTempoSpeed } from "@tspro/web-music-score/theory";
1704
1467
  import * as Audio from "@tspro/web-music-score/audio";
1705
1468
 
1706
1469
  // src/score/engine/obj-rhythm-column.ts
1707
- import { Note as Note6, NoteLength as NoteLength4 } from "@tspro/web-music-score/theory";
1470
+ import { Note as Note5, NoteLength as NoteLength4 } from "@tspro/web-music-score/theory";
1708
1471
 
1709
1472
  // src/score/engine/obj-arpeggio.ts
1710
1473
  var ObjArpeggio = class extends MusicObject {
@@ -1731,8 +1494,8 @@ var ObjArpeggio = class extends MusicObject {
1731
1494
  let { unitSize } = renderer;
1732
1495
  this.topArrowHeight = this.arpeggioDir === 0 /* Up */ ? unitSize : 0;
1733
1496
  this.bottomArrowHeight = this.arpeggioDir === 1 /* Down */ ? unitSize : 0;
1734
- let top = this.line instanceof ObjStaff ? this.line.getTopLineY() : this.line.getTopStringY();
1735
- let bottom = this.line instanceof ObjStaff ? this.line.getBottomLineY() : this.line.getBottomStringY();
1497
+ let top = this.line.getTopLineY();
1498
+ let bottom = this.line.getBottomLineY();
1736
1499
  this.cycleHeight = unitSize * 2;
1737
1500
  this.numCycles = Math.ceil((bottom - top) / this.cycleHeight) + 2;
1738
1501
  let width = unitSize * 2;
@@ -1777,14 +1540,14 @@ var ObjArpeggio = class extends MusicObject {
1777
1540
  };
1778
1541
 
1779
1542
  // src/score/engine/obj-rest.ts
1780
- import { Note as Note4, NoteLength, RhythmProps } from "@tspro/web-music-score/theory";
1781
- import { MusicError as MusicError6, MusicErrorType as MusicErrorType6 } from "@tspro/web-music-score/core";
1543
+ import { Note as Note3, NoteLength, RhythmProps } from "@tspro/web-music-score/theory";
1544
+ import { MusicError as MusicError5, MusicErrorType as MusicErrorType5 } from "@tspro/web-music-score/core";
1782
1545
  function getDiatonicIdFromStaffPos(staffPos) {
1783
1546
  if (typeof staffPos === "number") {
1784
- return Note4.getChromaticNote(staffPos).diatonicId;
1547
+ return Note3.getChromaticNote(staffPos).diatonicId;
1785
1548
  } else if (typeof staffPos === "string") {
1786
- return Note4.getNote(staffPos).diatonicId;
1787
- } else if (staffPos instanceof Note4) {
1549
+ return Note3.getNote(staffPos).diatonicId;
1550
+ } else if (staffPos instanceof Note3) {
1788
1551
  return staffPos.diatonicId;
1789
1552
  } else {
1790
1553
  return void 0;
@@ -1840,7 +1603,7 @@ var ObjRest = class extends MusicObject {
1840
1603
  let hasStaff = this.row.hasStaff;
1841
1604
  let staff2 = this.row.getStaff(diatonicId);
1842
1605
  if (hasStaff && !staff2) {
1843
- throw new MusicError6(MusicErrorType6.Score, "Rest staffPos is out of staff boundaries!");
1606
+ throw new MusicError5(MusicErrorType5.Score, "Rest staffPos is out of staff boundaries!");
1844
1607
  }
1845
1608
  }
1846
1609
  this.ownDiatonicId = this.measure.updateOwnDiatonicId(voiceId, diatonicId);
@@ -1881,6 +1644,15 @@ var ObjRest = class extends MusicObject {
1881
1644
  get triplet() {
1882
1645
  return this.rhythmProps.triplet;
1883
1646
  }
1647
+ getStaticObjects(line) {
1648
+ let staticObjects = [];
1649
+ this.staffObjects.forEach((obj) => {
1650
+ if (obj.staff === line) {
1651
+ staticObjects.push(obj);
1652
+ }
1653
+ });
1654
+ return staticObjects;
1655
+ }
1884
1656
  pick(x, y) {
1885
1657
  if (!this.getRect().contains(x, y)) {
1886
1658
  return [];
@@ -1934,7 +1706,7 @@ var ObjRest = class extends MusicObject {
1934
1706
  case NoteLength.SixtyFourth:
1935
1707
  return -3;
1936
1708
  default:
1937
- throw new MusicError6(MusicErrorType6.Score, "Cannot get rest dot vertical displacement because note length is invalid.");
1709
+ throw new MusicError5(MusicErrorType5.Score, "Cannot get rest dot vertical displacement because note length is invalid.");
1938
1710
  }
1939
1711
  }
1940
1712
  updateAccidentalState(accState) {
@@ -2091,13 +1863,13 @@ var ObjRest = class extends MusicObject {
2091
1863
  };
2092
1864
 
2093
1865
  // src/score/engine/obj-note-group.ts
2094
- import { Utils as Utils5 } from "@tspro/ts-utils-lib";
2095
- import { Note as Note5, NoteLength as NoteLength3, RhythmProps as RhythmProps2 } from "@tspro/web-music-score/theory";
1866
+ import { Utils as Utils4 } from "@tspro/ts-utils-lib";
1867
+ import { Note as Note4, NoteLength as NoteLength3, RhythmProps as RhythmProps2 } from "@tspro/web-music-score/theory";
2096
1868
 
2097
1869
  // src/score/engine/obj-beam-group.ts
2098
- import { Utils as Utils4 } from "@tspro/ts-utils-lib";
1870
+ import { Utils as Utils3 } from "@tspro/ts-utils-lib";
2099
1871
  import { MinNoteLength, NoteLength as NoteLength2 } from "@tspro/web-music-score/theory";
2100
- import { MusicError as MusicError7, MusicErrorType as MusicErrorType7 } from "@tspro/web-music-score/core";
1872
+ import { MusicError as MusicError6, MusicErrorType as MusicErrorType6 } from "@tspro/web-music-score/core";
2101
1873
  var adjustBeamAngle = (dx, dy) => {
2102
1874
  let T = DocumentSettings.BeamAngleFactor;
2103
1875
  if (!Number.isFinite(T) || T === 0) {
@@ -2174,13 +1946,13 @@ var ObjBeamGroup = class _ObjBeamGroup extends MusicObject {
2174
1946
  __publicField(this, "staffObjects", []);
2175
1947
  this.mi = new MBeamGroup(this);
2176
1948
  if (!symbols.every((s) => s.measure === symbols[0].measure)) {
2177
- throw new MusicError7(MusicErrorType7.Score, "All beam group symbols are not in same measure.");
1949
+ throw new MusicError6(MusicErrorType6.Score, "All beam group symbols are not in same measure.");
2178
1950
  } else if (symbols.length < 2) {
2179
- throw new MusicError7(MusicErrorType7.Score, "Beam group need minimum 2 symbols, but " + symbols.length + " given.");
1951
+ throw new MusicError6(MusicErrorType6.Score, "Beam group need minimum 2 symbols, but " + symbols.length + " given.");
2180
1952
  }
2181
1953
  if (triplet) {
2182
1954
  if (!symbols.every((s) => s.triplet)) {
2183
- throw new MusicError7(MusicErrorType7.Score, "Not every symbol's triplet property is true.");
1955
+ throw new MusicError6(MusicErrorType6.Score, "Not every symbol's triplet property is true.");
2184
1956
  }
2185
1957
  let isGroup = symbols.length < 3 || symbols.some((s) => !(s instanceof ObjNoteGroup)) || symbols.some((s) => s.rhythmProps.flagCount !== symbols[0].rhythmProps.flagCount);
2186
1958
  if (symbols.length === 3 && symbols[0] instanceof ObjNoteGroup && symbols[symbols.length - 1] instanceof ObjNoteGroup && symbols[0].rhythmProps.flagCount === symbols[symbols.length - 1].rhythmProps.flagCount) {
@@ -2198,7 +1970,7 @@ var ObjBeamGroup = class _ObjBeamGroup extends MusicObject {
2198
1970
  symbols.forEach((s) => s.setBeamGroup(this));
2199
1971
  symbols[0].measure.addBeamGroup(this);
2200
1972
  } else {
2201
- throw new MusicError7(MusicErrorType7.Score, "Cannot add beam group because some symbol already has one.");
1973
+ throw new MusicError6(MusicErrorType6.Score, "Cannot add beam group because some symbol already has one.");
2202
1974
  }
2203
1975
  }
2204
1976
  static createBeam(noteGroups) {
@@ -2337,7 +2109,7 @@ var ObjBeamGroup = class _ObjBeamGroup extends MusicObject {
2337
2109
  symbolY.forEach((symY, i) => {
2338
2110
  let symX = symbolX[i];
2339
2111
  if (symX !== void 0 && symY !== void 0) {
2340
- let beamY = Utils4.Math.interpolateY(leftX, leftY, rightX, rightY, symX);
2112
+ let beamY = Utils3.Math.interpolateY(leftX, leftY, rightX, rightY, symX);
2341
2113
  let raiseY = symY - beamY;
2342
2114
  if (stemDir === 1 /* Up */ && raiseY < 0) {
2343
2115
  raiseBeamY = Math.min(raiseBeamY, raiseY);
@@ -2352,8 +2124,8 @@ var ObjBeamGroup = class _ObjBeamGroup extends MusicObject {
2352
2124
  let obj = new ObjStaffBeamGroup(mainStaff, this);
2353
2125
  if (this.type === 2 /* TripletGroup */) {
2354
2126
  let ef = unitSize / (rightX - leftX);
2355
- let l = Utils4.Math.interpolateCoord(leftX, leftY + groupLineDy, rightX, rightY + groupLineDy, -ef);
2356
- let r = Utils4.Math.interpolateCoord(leftX, leftY + groupLineDy, rightX, rightY + groupLineDy, 1 + ef);
2127
+ let l = Utils3.Math.interpolateCoord(leftX, leftY + groupLineDy, rightX, rightY + groupLineDy, -ef);
2128
+ let r = Utils3.Math.interpolateCoord(leftX, leftY + groupLineDy, rightX, rightY + groupLineDy, 1 + ef);
2357
2129
  obj.points.push(new BeamPoint(leftStaff, this, leftSymbol, l.x, l.y));
2358
2130
  obj.points.push(new BeamPoint(rightStaff, this, rightSymbol, r.x, r.y));
2359
2131
  obj.tripletNumberOffsetY = 0;
@@ -2411,7 +2183,7 @@ var ObjBeamGroup = class _ObjBeamGroup extends MusicObject {
2411
2183
  obj.points.forEach((pt) => {
2412
2184
  if (pt.symbol instanceof ObjNoteGroup) {
2413
2185
  if (pt !== left && pt !== right) {
2414
- pt.y = Utils4.Math.interpolateY(left.x, left.y, right.x, right.y, pt.x);
2186
+ pt.y = Utils3.Math.interpolateY(left.x, left.y, right.x, right.y, pt.x);
2415
2187
  }
2416
2188
  pt.symbol.setStemTipY(pt.staff, pt.y);
2417
2189
  }
@@ -2436,8 +2208,8 @@ var ObjBeamGroup = class _ObjBeamGroup extends MusicObject {
2436
2208
  let r = obj.points[obj.points.length - 1];
2437
2209
  if (l && r) {
2438
2210
  let tf = obj.tripletNumber ? obj.tripletNumber.getRect().width / (r.x - l.x) * 1.2 : 0;
2439
- let lc = Utils4.Math.interpolateCoord(l.x, l.y, r.x, r.y, 0.5 - tf / 2);
2440
- let rc = Utils4.Math.interpolateCoord(l.x, l.y, r.x, r.y, 0.5 + tf / 2);
2211
+ let lc = Utils3.Math.interpolateCoord(l.x, l.y, r.x, r.y, 0.5 - tf / 2);
2212
+ let rc = Utils3.Math.interpolateCoord(l.x, l.y, r.x, r.y, 0.5 + tf / 2);
2441
2213
  let tipH = this.stemDir === 1 /* Up */ ? unitSize : -unitSize;
2442
2214
  renderer.drawLine(l.x, l.y, lc.x, lc.y, color, lineWidth);
2443
2215
  renderer.drawLine(rc.x, rc.y, r.x, r.y, color, lineWidth);
@@ -2480,13 +2252,13 @@ var ObjBeamGroup = class _ObjBeamGroup extends MusicObject {
2480
2252
  };
2481
2253
 
2482
2254
  // src/score/engine/obj-note-group.ts
2483
- import { MusicError as MusicError8, MusicErrorType as MusicErrorType8 } from "@tspro/web-music-score/core";
2255
+ import { MusicError as MusicError7, MusicErrorType as MusicErrorType7 } from "@tspro/web-music-score/core";
2484
2256
  function sortNoteStringData(notes, strings) {
2485
- let stringArr = Utils5.Arr.isArray(strings) ? strings : strings !== void 0 ? [strings] : [];
2257
+ let stringArr = Utils4.Arr.isArray(strings) ? strings : strings !== void 0 ? [strings] : [];
2486
2258
  let noteStringData = notes.map((note, i) => {
2487
2259
  return { note, string: stringArr[i] };
2488
2260
  });
2489
- noteStringData = Utils5.Arr.removeDuplicatesCmp(noteStringData, (a, b) => Note5.equals(a.note, b.note)).sort((a, b) => Note5.compareFunc(a.note, b.note));
2261
+ noteStringData = Utils4.Arr.removeDuplicatesCmp(noteStringData, (a, b) => Note4.equals(a.note, b.note)).sort((a, b) => Note4.compareFunc(a.note, b.note));
2490
2262
  return {
2491
2263
  notes: noteStringData.map((e) => e.note),
2492
2264
  strings: noteStringData.every((e) => e.string === void 0) ? void 0 : noteStringData.map((e) => e.string)
@@ -2600,8 +2372,8 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2600
2372
  __publicField(this, "staffObjects", []);
2601
2373
  __publicField(this, "tabObjects", []);
2602
2374
  __publicField(this, "mi");
2603
- if (!Utils5.Is.isIntegerGte(notes.length, 1)) {
2604
- throw new MusicError8(MusicErrorType8.Score, "Cannot create note group object because notes array is empty.");
2375
+ if (!Utils4.Is.isIntegerGte(notes.length, 1)) {
2376
+ throw new MusicError7(MusicErrorType7.Score, "Cannot create note group object because notes array is empty.");
2605
2377
  }
2606
2378
  let noteStringData = sortNoteStringData(notes, options == null ? void 0 : options.string);
2607
2379
  this.notes = noteStringData.notes;
@@ -2640,13 +2412,27 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2640
2412
  }
2641
2413
  startConnective(connectiveProps) {
2642
2414
  if (!this.row.hasStaff && connectiveProps.connective === 0 /* Tie */) {
2643
- throw new MusicError8(MusicErrorType8.Score, "Ties not implemented for guitar tabs alone, staff is required!");
2415
+ throw new MusicError7(MusicErrorType7.Score, "Ties not implemented for guitar tabs alone, staff is required!");
2644
2416
  } else if (!this.row.hasStaff && connectiveProps.connective === 1 /* Slur */) {
2645
- throw new MusicError8(MusicErrorType8.Score, "Slurs not implemented for guitar tabs alone, staff is required!");
2417
+ throw new MusicError7(MusicErrorType7.Score, "Slurs not implemented for guitar tabs alone, staff is required!");
2646
2418
  }
2647
2419
  this.startConnnectives.push(connectiveProps);
2648
2420
  this.doc.addConnectiveProps(connectiveProps);
2649
2421
  }
2422
+ getStaticObjects(line) {
2423
+ let staticObjects = [];
2424
+ this.staffObjects.forEach((obj) => {
2425
+ if (obj.staff === line) {
2426
+ staticObjects.push(obj);
2427
+ }
2428
+ });
2429
+ this.tabObjects.forEach((obj) => {
2430
+ if (obj.tab === line) {
2431
+ staticObjects.push(obj);
2432
+ }
2433
+ });
2434
+ return staticObjects;
2435
+ }
2650
2436
  pick(x, y) {
2651
2437
  if (!this.getRect().contains(x, y)) {
2652
2438
  return [];
@@ -2675,7 +2461,7 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2675
2461
  if (line instanceof ObjStaff) {
2676
2462
  let staff = line;
2677
2463
  if (noteIndex < 0 || noteIndex >= this.notes.length) {
2678
- throw new MusicError8(MusicErrorType8.Score, "Invalid noteIndex: " + noteIndex);
2464
+ throw new MusicError7(MusicErrorType7.Score, "Invalid noteIndex: " + noteIndex);
2679
2465
  }
2680
2466
  let obj = this.staffObjects.find((obj2) => obj2.staff === staff);
2681
2467
  if (!obj || noteIndex < 0 || noteIndex >= obj.noteHeadRects.length) {
@@ -2723,7 +2509,7 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2723
2509
  case 4 /* StemTip */:
2724
2510
  return { x: centerX, y: stemTip.centerY + (stemDir === 1 /* Up */ ? -padding : padding) };
2725
2511
  default:
2726
- throw new MusicError8(MusicErrorType8.Score, "Invalid noteAnchor: " + noteAnchor);
2512
+ throw new MusicError7(MusicErrorType7.Score, "Invalid noteAnchor: " + noteAnchor);
2727
2513
  }
2728
2514
  } else {
2729
2515
  let tab = line;
@@ -2855,15 +2641,15 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2855
2641
  return Math.max(this.rhythmProps.ticks, this.measure.getMeasureTicks() - this.col.positionTicks);
2856
2642
  }
2857
2643
  let prev = tieNoteGroups[j - 1];
2858
- if (prev && prev.notes.some((n) => Note5.equals(n, note))) {
2644
+ if (prev && prev.notes.some((n) => Note4.equals(n, note))) {
2859
2645
  return 0;
2860
2646
  }
2861
2647
  tieNoteGroups = tieNoteGroups.slice(j);
2862
- j = tieNoteGroups.findIndex((ng) => ng.notes.every((n) => !Note5.equals(n, note)));
2648
+ j = tieNoteGroups.findIndex((ng) => ng.notes.every((n) => !Note4.equals(n, note)));
2863
2649
  if (j >= 0) {
2864
2650
  tieNoteGroups = tieNoteGroups.slice(0, j);
2865
2651
  }
2866
- return Utils5.Math.sum(tieNoteGroups.map((ng) => ng.rhythmProps.ticks));
2652
+ return Utils4.Math.sum(tieNoteGroups.map((ng) => ng.rhythmProps.ticks));
2867
2653
  });
2868
2654
  return tiedTicks.length === 0 ? this.rhythmProps.ticks : Math.max(...tiedTicks);
2869
2655
  }
@@ -3155,7 +2941,7 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
3155
2941
  }
3156
2942
  });
3157
2943
  } else {
3158
- throw new MusicError8(MusicErrorType8.Score, "Cannot set triplet beam count because triplet beam group type is invalid.");
2944
+ throw new MusicError7(MusicErrorType7.Score, "Cannot set triplet beam count because triplet beam group type is invalid.");
3159
2945
  }
3160
2946
  }
3161
2947
  getDotVerticalDisplacement(staff, diatonicId, stemDir) {
@@ -3181,9 +2967,9 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
3181
2967
  };
3182
2968
 
3183
2969
  // src/score/engine/obj-rhythm-column.ts
3184
- import { MusicError as MusicError9, MusicErrorType as MusicErrorType9 } from "@tspro/web-music-score/core";
2970
+ import { MusicError as MusicError8, MusicErrorType as MusicErrorType8 } from "@tspro/web-music-score/core";
3185
2971
  var noteHeadDataCompareFunc = (a, b) => {
3186
- let cmp = Note6.compareFunc(a.note, b.note);
2972
+ let cmp = Note5.compareFunc(a.note, b.note);
3187
2973
  if (cmp === 0) {
3188
2974
  cmp = a.noteGroup.stemDir === b.noteGroup.stemDir ? 0 : a.noteGroup.stemDir === 1 /* Up */ ? 1 : -1;
3189
2975
  }
@@ -3224,7 +3010,7 @@ var ObjRhythmColumn = class extends MusicObject {
3224
3010
  if (colId >= 0 && colId < this.measure.getColumnCount()) {
3225
3011
  return this.measure.getColumn(colId + 1);
3226
3012
  } else {
3227
- throw new MusicError9(MusicErrorType9.Score, "Cannot get next column in measure because current column's id in mesure is invalid.");
3013
+ throw new MusicError8(MusicErrorType8.Score, "Cannot get next column in measure because current column's id in mesure is invalid.");
3228
3014
  }
3229
3015
  }
3230
3016
  /**
@@ -3251,6 +3037,22 @@ var ObjRhythmColumn = class extends MusicObject {
3251
3037
  this.getRect();
3252
3038
  return this.shapeRects;
3253
3039
  }
3040
+ getStaticObjects(line) {
3041
+ let staticObjects = [];
3042
+ this.voiceSymbol.forEach((symbol) => {
3043
+ if (symbol) {
3044
+ symbol.getRect();
3045
+ symbol.getStaticObjects(line).forEach((obj) => staticObjects.push(obj));
3046
+ }
3047
+ });
3048
+ this.arpeggios.forEach((arpeggio) => {
3049
+ if (arpeggio.line === line) {
3050
+ arpeggio.getRect();
3051
+ staticObjects.push(arpeggio);
3052
+ }
3053
+ });
3054
+ return staticObjects;
3055
+ }
3254
3056
  get doc() {
3255
3057
  return this.measure.doc;
3256
3058
  }
@@ -3301,6 +3103,7 @@ var ObjRhythmColumn = class extends MusicObject {
3301
3103
  this.setupNoteHeadDisplacements();
3302
3104
  }
3303
3105
  this.requestLayout();
3106
+ this.requestRectUpdate();
3304
3107
  }
3305
3108
  getVoiceSymbol(voiceId) {
3306
3109
  return this.voiceSymbol[voiceId];
@@ -3355,7 +3158,7 @@ var ObjRhythmColumn = class extends MusicObject {
3355
3158
  }
3356
3159
  }
3357
3160
  getNoteHeadDisplacement(noteGroup, note) {
3358
- let data = this.noteHeadDisplacements.find((d) => d.noteGroup === noteGroup && Note6.equals(d.note, note));
3161
+ let data = this.noteHeadDisplacements.find((d) => d.noteGroup === noteGroup && Note5.equals(d.note, note));
3359
3162
  if ((data == null ? void 0 : data.displacement) !== void 0) {
3360
3163
  return data.displacement;
3361
3164
  } else {
@@ -3399,7 +3202,7 @@ var ObjRhythmColumn = class extends MusicObject {
3399
3202
  });
3400
3203
  }
3401
3204
  });
3402
- playerNotes.sort((a, b) => Note6.compareFunc(a.note, b.note));
3205
+ playerNotes.sort((a, b) => Note5.compareFunc(a.note, b.note));
3403
3206
  if (this.hasArpeggio() && this.getArpeggioDir() === 1 /* Down */) {
3404
3207
  playerNotes.reverse();
3405
3208
  }
@@ -3415,6 +3218,7 @@ var ObjRhythmColumn = class extends MusicObject {
3415
3218
  if (!this.needLayout) {
3416
3219
  return;
3417
3220
  }
3221
+ this.requestRectUpdate();
3418
3222
  this.rect = new DivRect();
3419
3223
  let { row } = this;
3420
3224
  let { unitSize } = renderer;
@@ -3452,7 +3256,6 @@ var ObjRhythmColumn = class extends MusicObject {
3452
3256
  this.rect.left = -leftw;
3453
3257
  this.rect.centerX = 0;
3454
3258
  this.rect.right = rightw;
3455
- this.requestRectUpdate();
3456
3259
  this.row.getStaves().forEach((staff) => {
3457
3260
  let minDiatonicId = void 0;
3458
3261
  let maxDiatonicId = void 0;
@@ -3647,7 +3450,7 @@ function isTempoText(text) {
3647
3450
  }
3648
3451
 
3649
3452
  // src/score/engine/extension.ts
3650
- import { MusicError as MusicError10, MusicErrorType as MusicErrorType10 } from "@tspro/web-music-score/core";
3453
+ import { MusicError as MusicError9, MusicErrorType as MusicErrorType9 } from "@tspro/web-music-score/core";
3651
3454
  function getTextAnchorY(linePos) {
3652
3455
  switch (linePos) {
3653
3456
  case "bottom":
@@ -3683,7 +3486,7 @@ var Extension = class extends MusicObjectLink {
3683
3486
  if (head instanceof ObjText) {
3684
3487
  head.updateAnchorY(getTextAnchorY(linePos));
3685
3488
  } else {
3686
- throw new MusicError10(MusicErrorType10.Score, "Update anchor's y-coordinate is only implemented for text objects.");
3489
+ throw new MusicError9(MusicErrorType9.Score, "Update anchor's y-coordinate is only implemented for text objects.");
3687
3490
  }
3688
3491
  }
3689
3492
  isVisible() {
@@ -3819,7 +3622,7 @@ var PlayerColumnProps = class {
3819
3622
  return this.speed;
3820
3623
  }
3821
3624
  getTempo() {
3822
- let speed = Utils6.Math.clamp(this.getSpeed(), 0.1, 10);
3625
+ let speed = Utils5.Math.clamp(this.getSpeed(), 0.1, 10);
3823
3626
  return alterTempoSpeed(this.measure.getTempo(), speed);
3824
3627
  }
3825
3628
  setVolume(volume) {
@@ -3844,7 +3647,7 @@ var PlayerColumnProps = class {
3844
3647
  if (symbolsTicks.length === 0) {
3845
3648
  return 0;
3846
3649
  } else {
3847
- return Utils6.Math.sum(symbolsTicks) / symbolsTicks.length;
3650
+ return Utils5.Math.sum(symbolsTicks) / symbolsTicks.length;
3848
3651
  }
3849
3652
  }
3850
3653
  }
@@ -3992,7 +3795,7 @@ var Player = class _Player {
3992
3795
  } else if (layoutObj.musicObj.getLink() instanceof Extension) {
3993
3796
  let extension = layoutObj.musicObj.getLink();
3994
3797
  let { columnRange, extensionBreakText } = extension.getExtensionRangeInfo();
3995
- let totalTicks = Utils6.Math.sum(columnRange.map((c) => c.getTicksToNextColumn()));
3798
+ let totalTicks = Utils5.Math.sum(columnRange.map((c) => c.getTicksToNextColumn()));
3996
3799
  switch (text) {
3997
3800
  case "accel." /* accel */: {
3998
3801
  let startSpeed = curSpeed;
@@ -4046,11 +3849,11 @@ var Player = class _Player {
4046
3849
  });
4047
3850
  let speedArr = (_a = speedMap.get(col)) != null ? _a : [];
4048
3851
  if (speedArr.length > 0) {
4049
- curSpeed = Utils6.Math.sum(speedArr) / speedArr.length;
3852
+ curSpeed = Utils5.Math.sum(speedArr) / speedArr.length;
4050
3853
  }
4051
3854
  let volumeArr = (_b = volumeMap.get(col)) != null ? _b : [];
4052
3855
  if (volumeArr.length > 0) {
4053
- curVolume = Utils6.Math.sum(volumeArr) / volumeArr.length;
3856
+ curVolume = Utils5.Math.sum(volumeArr) / volumeArr.length;
4054
3857
  }
4055
3858
  col.getPlayerProps().setSpeed(curSpeed);
4056
3859
  col.getPlayerProps().setVolume(curVolume);
@@ -4242,14 +4045,12 @@ var ObjBarLine = class extends MusicObject {
4242
4045
  if (line instanceof ObjStaff) {
4243
4046
  lineCenterY = line.getMiddleLineY();
4244
4047
  lineDotOff = line.getDiatonicSpacing();
4245
- top = line.getTopLineY();
4246
- bottom = line.getBottomLineY();
4247
4048
  } else {
4248
- lineCenterY = (line.getBottom() + line.getTop()) / 2;
4249
- lineDotOff = (line.getBottom() - line.getTop()) / 6;
4250
- top = line.getTopStringY();
4251
- bottom = line.getBottomStringY();
4049
+ lineCenterY = (line.getBottomLineY() + line.getTopLineY()) / 2;
4050
+ lineDotOff = (line.getBottomLineY() - line.getTopLineY()) / 6;
4252
4051
  }
4052
+ top = line.getTopLineY();
4053
+ bottom = line.getBottomLineY();
4253
4054
  switch (barLineType) {
4254
4055
  case 0 /* None */:
4255
4056
  obj.setRect(new DivRect(0, 0, 0, top, 0, bottom));
@@ -4381,8 +4182,8 @@ var ObjBarLineRight = class extends ObjBarLine {
4381
4182
  };
4382
4183
 
4383
4184
  // src/score/engine/obj-ending.ts
4384
- import { Utils as Utils7 } from "@tspro/ts-utils-lib";
4385
- import { MusicError as MusicError11, MusicErrorType as MusicErrorType11 } from "@tspro/web-music-score/core";
4185
+ import { Utils as Utils6 } from "@tspro/ts-utils-lib";
4186
+ import { MusicError as MusicError10, MusicErrorType as MusicErrorType10 } from "@tspro/web-music-score/core";
4386
4187
  var ObjEnding = class extends MusicObject {
4387
4188
  constructor(measure, passages) {
4388
4189
  super(measure);
@@ -4392,10 +4193,10 @@ var ObjEnding = class extends MusicObject {
4392
4193
  __publicField(this, "shapeRects", []);
4393
4194
  __publicField(this, "mi");
4394
4195
  this.mi = new MEnding(this);
4395
- if (!Utils7.Is.isIntegerGte(passages.length, 1)) {
4396
- throw new MusicError11(MusicErrorType11.Score, "Passages is empty.");
4397
- } else if (!this.passages.every((p) => Utils7.Is.isIntegerGte(p, 1))) {
4398
- throw new MusicError11(MusicErrorType11.Score, "Invalid passages: " + this.passages);
4196
+ if (!Utils6.Is.isIntegerGte(passages.length, 1)) {
4197
+ throw new MusicError10(MusicErrorType10.Score, "Passages is empty.");
4198
+ } else if (!this.passages.every((p) => Utils6.Is.isIntegerGte(p, 1))) {
4199
+ throw new MusicError10(MusicErrorType10.Score, "Invalid passages: " + this.passages);
4399
4200
  }
4400
4201
  this.passages.sort((a, b) => a - b);
4401
4202
  let text = this.passages.map((p) => p + ".").join("");
@@ -4484,9 +4285,9 @@ var ObjFermata = class extends MusicObject {
4484
4285
  let { measure } = anchor;
4485
4286
  let { row } = measure;
4486
4287
  if (row.getTopStaff() !== row.getBottomStaff()) {
4487
- return [0 /* AboveStaff */, 1 /* BelowStaff */];
4288
+ return [0 /* Above */, 1 /* Below */];
4488
4289
  } else {
4489
- return [0 /* AboveStaff */];
4290
+ return [0 /* Above */];
4490
4291
  }
4491
4292
  }
4492
4293
  pick(x, y) {
@@ -4507,7 +4308,7 @@ var ObjFermata = class extends MusicObject {
4507
4308
  return;
4508
4309
  }
4509
4310
  let { lineWidth, unitSize } = renderer;
4510
- let upsideDown = this.pos === 1 /* BelowStaff */;
4311
+ let upsideDown = this.pos === 1 /* Below */;
4511
4312
  let dy = (upsideDown ? unitSize : -unitSize) * 0.7;
4512
4313
  let left = this.rect.left;
4513
4314
  let right = this.rect.right;
@@ -4602,14 +4403,14 @@ var ObjExtensionLine = class extends MusicObject {
4602
4403
  };
4603
4404
 
4604
4405
  // src/score/engine/obj-measure.ts
4605
- import { MusicError as MusicError14, MusicErrorType as MusicErrorType14 } from "@tspro/web-music-score/core";
4406
+ import { MusicError as MusicError13, MusicErrorType as MusicErrorType13 } from "@tspro/web-music-score/core";
4606
4407
 
4607
4408
  // src/score/engine/connective-props.ts
4608
- import { Note as Note7 } from "@tspro/web-music-score/theory";
4409
+ import { Note as Note6 } from "@tspro/web-music-score/theory";
4609
4410
 
4610
4411
  // src/score/engine/obj-connective.ts
4611
- import { Utils as Utils8 } from "@tspro/ts-utils-lib";
4612
- import { MusicError as MusicError12, MusicErrorType as MusicErrorType12 } from "@tspro/web-music-score/core";
4412
+ import { Utils as Utils7 } from "@tspro/ts-utils-lib";
4413
+ import { MusicError as MusicError11, MusicErrorType as MusicErrorType11 } from "@tspro/web-music-score/core";
4613
4414
  var ObjConnective = class extends MusicObject {
4614
4415
  constructor(connectiveProps, line, measure, leftNoteGroup, leftNoteId, ...args) {
4615
4416
  super(measure);
@@ -4637,7 +4438,7 @@ var ObjConnective = class extends MusicObject {
4637
4438
  this.rightNoteGroup = args[0];
4638
4439
  this.rightNoteId = args[1];
4639
4440
  this.tieType = void 0;
4640
- } else if (Utils8.Is.isEnumValue(args[0], TieType)) {
4441
+ } else if (Utils7.Is.isEnumValue(args[0], TieType)) {
4641
4442
  this.rightNoteGroup = void 0;
4642
4443
  this.rightNoteId = void 0;
4643
4444
  this.tieType = args[0];
@@ -4698,7 +4499,7 @@ var ObjConnective = class extends MusicObject {
4698
4499
  rx = contentRect.right;
4699
4500
  ry = leftPos.y + (rightPos.y - leftPos.y) * tLeft / (tLeft + tRight);
4700
4501
  } else {
4701
- throw new MusicError12(MusicErrorType12.Score, "Cannot layout connective object because no valid left and right note groups.");
4502
+ throw new MusicError11(MusicErrorType11.Score, "Cannot layout connective object because no valid left and right note groups.");
4702
4503
  }
4703
4504
  let spanDy = arcDir === "up" ? -1 : 1;
4704
4505
  let arcHeight = spanDy * unitSize * Math.log2(rx - lx) / 3;
@@ -4707,7 +4508,7 @@ var ObjConnective = class extends MusicObject {
4707
4508
  this.rx = rx;
4708
4509
  this.ry = ry;
4709
4510
  this.arcHeight = this.connectiveProps.connective === 2 /* Slide */ ? 0 : arcHeight;
4710
- let { nx, ny } = Utils8.Math.calcNormal(lx, ly, rx, ry);
4511
+ let { nx, ny } = Utils7.Math.calcNormal(lx, ly, rx, ry);
4711
4512
  this.cp1x = lx * 0.7 + rx * 0.3 + nx * this.arcHeight;
4712
4513
  this.cp1y = ly * 0.7 + ry * 0.3 + ny * this.arcHeight;
4713
4514
  this.cp2x = lx * 0.3 + rx * 0.7 + nx * this.arcHeight;
@@ -4767,7 +4568,7 @@ var ObjConnective = class extends MusicObject {
4767
4568
  };
4768
4569
 
4769
4570
  // src/score/engine/connective-props.ts
4770
- import { MusicError as MusicError13, MusicErrorType as MusicErrorType13 } from "@tspro/web-music-score/core";
4571
+ import { MusicError as MusicError12, MusicErrorType as MusicErrorType12 } from "@tspro/web-music-score/core";
4771
4572
  var ConnectiveProps = class {
4772
4573
  constructor(connective, span, noteAnchor, startNoteGroup) {
4773
4574
  this.connective = connective;
@@ -4847,7 +4648,7 @@ var ConnectiveProps = class {
4847
4648
  let leftNoteGroup = this.noteGroups[i];
4848
4649
  let rightNoteGroup = this.noteGroups[i + 1];
4849
4650
  leftNoteGroup.notes.forEach((leftNote, leftNoteId) => {
4850
- let rightNoteId = rightNoteGroup.notes.findIndex((rightNote) => Note7.equals(rightNote, leftNote));
4651
+ let rightNoteId = rightNoteGroup.notes.findIndex((rightNote) => Note6.equals(rightNote, leftNote));
4851
4652
  if (rightNoteId >= 0) {
4852
4653
  this.createObjConnective(leftNoteGroup, leftNoteId, rightNoteGroup, rightNoteId);
4853
4654
  }
@@ -4902,7 +4703,7 @@ var ConnectiveProps = class {
4902
4703
  addConnective(leftNoteGroup.measure, leftNoteGroup, leftNoteId, rightNoteGroup, rightNoteId);
4903
4704
  addConnective(rightNoteGroup.measure, leftNoteGroup, leftNoteId, rightNoteGroup, rightNoteId);
4904
4705
  } else {
4905
- throw new MusicError13(MusicErrorType13.Score, "Cannot create connective because it is jumping measures.");
4706
+ throw new MusicError12(MusicErrorType12.Score, "Cannot create connective because it is jumping measures.");
4906
4707
  }
4907
4708
  }
4908
4709
  };
@@ -4910,7 +4711,7 @@ var ConnectiveProps = class {
4910
4711
  // src/score/engine/obj-measure.ts
4911
4712
  function validateVoiceId(voiceId) {
4912
4713
  if (getVoiceIds().indexOf(voiceId) < 0) {
4913
- throw new MusicError14(MusicErrorType14.Score, "Invalid voiceId: " + voiceId);
4714
+ throw new MusicError13(MusicErrorType13.Score, "Invalid voiceId: " + voiceId);
4914
4715
  } else {
4915
4716
  return voiceId;
4916
4717
  }
@@ -4946,7 +4747,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
4946
4747
  __publicField(this, "voiceSymbols", []);
4947
4748
  __publicField(this, "lastAddedRhythmColumn");
4948
4749
  __publicField(this, "lastAddedRhythmSymbol");
4949
- __publicField(this, "addExtensionToMusicObject");
4750
+ __publicField(this, "addExtensionToMusicObjects", []);
4950
4751
  __publicField(this, "layoutObjects", []);
4951
4752
  __publicField(this, "postMeasureBreakWidth", 0);
4952
4753
  __publicField(this, "passCount", 0);
@@ -4958,6 +4759,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
4958
4759
  __publicField(this, "endRepeatPlayCount", 2);
4959
4760
  // play twice.
4960
4761
  __publicField(this, "endRepeatPlayCountText");
4762
+ __publicField(this, "staticObjectsCache", /* @__PURE__ */ new Map());
4961
4763
  __publicField(this, "mi");
4962
4764
  this.mi = new MMeasure(this);
4963
4765
  this.prevMeasure = row.doc.getLastMeasure();
@@ -5006,10 +4808,10 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5006
4808
  if (this.row.hasStaff) {
5007
4809
  diatonicId = this.row.getTopStaff().middleLineDiatonicId;
5008
4810
  } else {
5009
- diatonicId = Note8.getNote("C4").diatonicId;
4811
+ diatonicId = Note7.getNote("C4").diatonicId;
5010
4812
  }
5011
4813
  }
5012
- return this.useDiatonicId[voiceId] = Note8.validateDiatonicId(diatonicId);
4814
+ return this.useDiatonicId[voiceId] = Note7.validateDiatonicId(diatonicId);
5013
4815
  }
5014
4816
  updateOwnStemDir(symbol, setStemDir) {
5015
4817
  var _a, _b;
@@ -5146,7 +4948,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5146
4948
  let scaleType = validateScaleType("" + args[1]);
5147
4949
  this.alterKeySignature = getScale(tonic, scaleType);
5148
4950
  } catch (e) {
5149
- throw new MusicError14(MusicErrorType14.Score, "Cannot set key signature because invalid args: " + args);
4951
+ throw new MusicError13(MusicErrorType13.Score, "Cannot set key signature because invalid args: " + args);
5150
4952
  }
5151
4953
  }
5152
4954
  this.updateKeySignature();
@@ -5220,25 +5022,18 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5220
5022
  getPostMeasureBreakWidth() {
5221
5023
  return this.postMeasureBreakWidth;
5222
5024
  }
5223
- addLayoutObject(musicObj, layoutGroupId, verticalPos) {
5224
- let w = new LayoutObjectWrapper(musicObj, layoutGroupId, verticalPos);
5225
- this.layoutObjects.push(w);
5025
+ addLayoutObject(musicObj, line, layoutGroupId, verticalPos) {
5026
+ this.layoutObjects.push(new LayoutObjectWrapper(musicObj, line, layoutGroupId, verticalPos));
5226
5027
  this.requestLayout();
5028
+ this.requestRectUpdate();
5227
5029
  }
5228
- addFermata(fermata) {
5030
+ addFermata(staffTabOrGroup, fermata) {
5229
5031
  let anchor = fermata === 1 /* AtMeasureEnd */ ? this.barLineRight : this.lastAddedRhythmColumn;
5230
5032
  if (!anchor) {
5231
- throw new MusicError14(MusicErrorType14.Score, "Cannot add Fermata because anchor is undefined.");
5033
+ throw new MusicError13(MusicErrorType13.Score, "Cannot add Fermata because anchor is undefined.");
5232
5034
  }
5233
- let fermataObjArr = anchor.getAnchoredLayoutObjects().map((layoutObj) => layoutObj.musicObj).filter((musicObj) => musicObj instanceof ObjFermata);
5234
- let hasAbove = fermataObjArr.some((obj) => obj.pos === 0 /* AboveStaff */);
5235
- let hasBelow = fermataObjArr.some((obj) => obj.pos === 1 /* BelowStaff */);
5236
- ObjFermata.getFermataPositions(anchor).forEach((fermataPos) => {
5237
- if (fermataPos === 0 /* AboveStaff */ && !hasAbove) {
5238
- this.addLayoutObject(new ObjFermata(anchor, fermataPos), 0 /* Fermata */, fermataPos);
5239
- } else if (fermataPos === 1 /* BelowStaff */ && !hasBelow) {
5240
- this.addLayoutObject(new ObjFermata(anchor, fermataPos), 0 /* Fermata */, fermataPos);
5241
- }
5035
+ this.forEachStaffGroup(staffTabOrGroup, 0 /* Above */, (line, vpos) => {
5036
+ this.addLayoutObject(new ObjFermata(anchor, vpos), line, 0 /* Fermata */, vpos);
5242
5037
  });
5243
5038
  this.disableExtension();
5244
5039
  this.requestLayout();
@@ -5246,15 +5041,20 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5246
5041
  hasFermata(anchor) {
5247
5042
  return this.layoutObjects.some((layoutObj) => layoutObj.musicObj instanceof ObjFermata && layoutObj.anchor === anchor);
5248
5043
  }
5249
- addNavigation(navigation, ...args) {
5044
+ addNavigation(staffTabOrGroup, navigation, ...args) {
5045
+ let addLayoutObjectProps = void 0;
5250
5046
  switch (navigation) {
5251
5047
  case 10 /* Ending */:
5252
5048
  if (this.navigationSet.has(navigation)) {
5253
- throw new MusicError14(MusicErrorType14.Score, "Cannot add ending beasure measure already has one.");
5049
+ throw new MusicError13(MusicErrorType13.Score, "Cannot add ending beasure measure already has one.");
5254
5050
  }
5255
5051
  let anchor = this;
5256
5052
  let passages = args;
5257
- this.addLayoutObject(new ObjEnding(anchor, passages), 3 /* Ending */, 0 /* AboveStaff */);
5053
+ addLayoutObjectProps = {
5054
+ createObj: () => new ObjEnding(anchor, passages),
5055
+ layoutGroupId: 3 /* Ending */,
5056
+ defaultVerticalPos: 0 /* Above */
5057
+ };
5258
5058
  break;
5259
5059
  case 1 /* DC_al_Coda */:
5260
5060
  case 0 /* DC_al_Fine */:
@@ -5262,37 +5062,53 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5262
5062
  case 2 /* DS_al_Fine */: {
5263
5063
  let anchor2 = this.barLineRight;
5264
5064
  let text = getNavigationString(navigation);
5265
- this.addLayoutObject(new ObjText(anchor2, text, 1, 1), 2 /* Navigation */, 0 /* AboveStaff */);
5266
- this.addNavigation(9 /* EndRepeat */);
5065
+ addLayoutObjectProps = {
5066
+ createObj: () => new ObjText(anchor2, text, 1, 1),
5067
+ layoutGroupId: 2 /* Navigation */,
5068
+ defaultVerticalPos: 0 /* Above */
5069
+ };
5070
+ this.addNavigation(staffTabOrGroup, 9 /* EndRepeat */);
5267
5071
  this.endSong();
5268
5072
  break;
5269
5073
  }
5270
5074
  case 7 /* Fine */: {
5271
5075
  let anchor2 = this.barLineRight;
5272
5076
  let text = getNavigationString(navigation);
5273
- this.addLayoutObject(new ObjText(anchor2, text, 1, 1), 2 /* Navigation */, 0 /* AboveStaff */);
5077
+ addLayoutObjectProps = {
5078
+ createObj: () => new ObjText(anchor2, text, 1, 1),
5079
+ layoutGroupId: 2 /* Navigation */,
5080
+ defaultVerticalPos: 0 /* Above */
5081
+ };
5274
5082
  break;
5275
5083
  }
5276
5084
  case 6 /* Segno */:
5277
5085
  case 4 /* Coda */: {
5278
5086
  let anchor2 = this.barLineLeft;
5279
5087
  let text = getNavigationString(navigation);
5280
- this.addLayoutObject(new ObjSpecialText(anchor2, text), 2 /* Navigation */, 0 /* AboveStaff */);
5088
+ addLayoutObjectProps = {
5089
+ createObj: () => new ObjSpecialText(anchor2, text),
5090
+ layoutGroupId: 2 /* Navigation */,
5091
+ defaultVerticalPos: 0 /* Above */
5092
+ };
5281
5093
  break;
5282
5094
  }
5283
5095
  case 5 /* toCoda */: {
5284
5096
  let anchor2 = this.barLineRight;
5285
5097
  let text = getNavigationString(navigation);
5286
- this.addLayoutObject(new ObjSpecialText(anchor2, text), 2 /* Navigation */, 0 /* AboveStaff */);
5098
+ addLayoutObjectProps = {
5099
+ createObj: () => new ObjSpecialText(anchor2, text),
5100
+ layoutGroupId: 2 /* Navigation */,
5101
+ defaultVerticalPos: 0 /* Above */
5102
+ };
5287
5103
  break;
5288
5104
  }
5289
5105
  case 9 /* EndRepeat */:
5290
5106
  if (args.length === 0) {
5291
5107
  this.endRepeatPlayCount = 2;
5292
- } else if (Utils9.Is.isIntegerGte(args[0], 2)) {
5108
+ } else if (Utils8.Is.isIntegerGte(args[0], 2)) {
5293
5109
  this.endRepeatPlayCount = args[0];
5294
5110
  } else {
5295
- throw new MusicError14(MusicErrorType14.Score, "Invalid end repeat play count (should be 2 or greater integer): " + args[0]);
5111
+ throw new MusicError13(MusicErrorType13.Score, "Invalid end repeat play count (should be 2 or greater integer): " + args[0]);
5296
5112
  }
5297
5113
  if (this.endRepeatPlayCount !== 2) {
5298
5114
  let textProps = {
@@ -5303,6 +5119,11 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5303
5119
  }
5304
5120
  break;
5305
5121
  }
5122
+ if (addLayoutObjectProps) {
5123
+ this.forEachStaffGroup(staffTabOrGroup, addLayoutObjectProps.defaultVerticalPos, (line, vpos) => {
5124
+ this.addLayoutObject(addLayoutObjectProps.createObj(), line, addLayoutObjectProps.layoutGroupId, vpos);
5125
+ });
5126
+ }
5306
5127
  this.navigationSet.add(navigation);
5307
5128
  this.disableExtension();
5308
5129
  }
@@ -5318,70 +5139,125 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5318
5139
  addConnective(connective, ...args) {
5319
5140
  let anchor = this.lastAddedRhythmSymbol;
5320
5141
  if (!(anchor instanceof ObjNoteGroup)) {
5321
- throw new MusicError14(MusicErrorType14.Score, "Connective can be added to note group only.");
5142
+ throw new MusicError13(MusicErrorType13.Score, "Connective can be added to note group only.");
5322
5143
  }
5323
5144
  if (connective === 0 /* Tie */) {
5324
- let tieSpan = Utils9.Is.isInteger(args[0]) || Utils9.Is.isEnumValue(args[0], TieType) ? args[0] : 2;
5325
- let noteAnchor = Utils9.Is.isEnumValue(args[1], NoteAnchor) ? args[1] : 0 /* Auto */;
5145
+ let tieSpan = Utils8.Is.isInteger(args[0]) || Utils8.Is.isEnumValue(args[0], TieType) ? args[0] : 2;
5146
+ let noteAnchor = Utils8.Is.isEnumValue(args[1], NoteAnchor) ? args[1] : 0 /* Auto */;
5326
5147
  anchor.startConnective(new ConnectiveProps(0 /* Tie */, tieSpan, noteAnchor, anchor));
5327
5148
  } else if (connective === 1 /* Slur */) {
5328
- let slurSpan = Utils9.Is.isInteger(args[0]) ? args[0] : 2;
5329
- let noteAnchor = Utils9.Is.isEnumValue(args[1], NoteAnchor) ? args[1] : 0 /* Auto */;
5149
+ let slurSpan = Utils8.Is.isInteger(args[0]) ? args[0] : 2;
5150
+ let noteAnchor = Utils8.Is.isEnumValue(args[1], NoteAnchor) ? args[1] : 0 /* Auto */;
5330
5151
  anchor.startConnective(new ConnectiveProps(1 /* Slur */, slurSpan, noteAnchor, anchor));
5331
5152
  } else if (connective === 2 /* Slide */) {
5332
- let noteAnchor = Utils9.Is.isEnumValue(args[0], NoteAnchor) ? args[0] : 0 /* Auto */;
5153
+ let noteAnchor = Utils8.Is.isEnumValue(args[0], NoteAnchor) ? args[0] : 0 /* Auto */;
5333
5154
  anchor.startConnective(new ConnectiveProps(2 /* Slide */, 2, noteAnchor, anchor));
5334
5155
  }
5335
5156
  }
5336
- addLabel(label, text) {
5157
+ forEachStaffGroup(staffTabOrGroup, defaultVerticalPos, add) {
5158
+ const lines = this.row.getNotationLines();
5159
+ const performAdd = (lineId, vpos, depth) => {
5160
+ if (depth >= 5) {
5161
+ return;
5162
+ }
5163
+ let success = false;
5164
+ if (typeof lineId === "number") {
5165
+ if (lines[lineId]) {
5166
+ add(lines[lineId], vpos);
5167
+ success = true;
5168
+ }
5169
+ } else if (typeof lineId === "string" && lineId.length > 0) {
5170
+ lines.filter((l) => l.name === lineId).forEach((line) => {
5171
+ add(line, vpos);
5172
+ success = true;
5173
+ });
5174
+ }
5175
+ if (typeof lineId === "string" && !success) {
5176
+ let grp = this.doc.getStaffGroup(lineId);
5177
+ if (grp) {
5178
+ (Utils8.Is.isArray(grp.staffsTabsAndGroups) ? grp.staffsTabsAndGroups : [grp.staffsTabsAndGroups]).forEach((lineId2) => {
5179
+ switch (grp.verticalPosition) {
5180
+ case 0 /* Above */:
5181
+ performAdd(lineId2, 0 /* Above */, depth + 1);
5182
+ break;
5183
+ case 1 /* Below */:
5184
+ performAdd(lineId2, 1 /* Below */, depth + 1);
5185
+ break;
5186
+ case 2 /* Both */:
5187
+ performAdd(lineId2, 0 /* Above */, depth + 1);
5188
+ performAdd(lineId2, 1 /* Below */, depth + 1);
5189
+ break;
5190
+ case 3 /* Auto */:
5191
+ performAdd(lineId2, defaultVerticalPos, depth + 1);
5192
+ break;
5193
+ }
5194
+ });
5195
+ }
5196
+ }
5197
+ };
5198
+ if (staffTabOrGroup === void 0) {
5199
+ if (lines.length >= 2 && lines[0] instanceof ObjStaff && lines[0].staffConfig.clef === "G" /* G */ && lines[0].isGrand() && lines[1] instanceof ObjStaff && lines[1].staffConfig.clef === "F" /* F */ && lines[1].isGrand()) {
5200
+ performAdd(defaultVerticalPos === 1 /* Below */ ? 1 : 0, defaultVerticalPos, 0);
5201
+ } else {
5202
+ performAdd(0, defaultVerticalPos, 0);
5203
+ }
5204
+ } else {
5205
+ performAdd(staffTabOrGroup, defaultVerticalPos, 0);
5206
+ }
5207
+ }
5208
+ addLabel(staffTabOrGroup, label, text) {
5337
5209
  let anchor = this.lastAddedRhythmColumn;
5338
5210
  if (!anchor) {
5339
- throw new MusicError14(MusicErrorType14.Score, "Cannot add label because anchor is undefined.");
5211
+ throw new MusicError13(MusicErrorType13.Score, "Cannot add label because anchor is undefined.");
5340
5212
  } else if (text.length === 0) {
5341
- throw new MusicError14(MusicErrorType14.Score, "Cannot add label because label text is empty.");
5213
+ throw new MusicError13(MusicErrorType13.Score, "Cannot add label because label text is empty.");
5342
5214
  }
5343
5215
  let textProps = { text };
5344
5216
  let layoutGroupId;
5345
- let verticalPos;
5217
+ let defaultVerticalPos;
5346
5218
  switch (label) {
5347
5219
  case 0 /* Note */:
5348
5220
  layoutGroupId = 1 /* NoteLabel */;
5349
- verticalPos = 1 /* BelowStaff */;
5221
+ defaultVerticalPos = 1 /* Below */;
5350
5222
  break;
5351
5223
  case 1 /* Chord */:
5352
5224
  layoutGroupId = 6 /* ChordLabel */;
5353
- verticalPos = 0 /* AboveStaff */;
5225
+ defaultVerticalPos = 0 /* Above */;
5354
5226
  break;
5355
5227
  }
5356
- let textObj = new ObjText(anchor, textProps, 0.5, 1);
5357
- this.addLayoutObject(textObj, layoutGroupId, verticalPos);
5358
- this.enableExtension(textObj);
5228
+ this.forEachStaffGroup(staffTabOrGroup, defaultVerticalPos, (line, vpos) => {
5229
+ let textObj = new ObjText(anchor, textProps, 0.5, 1);
5230
+ this.addLayoutObject(textObj, line, layoutGroupId, vpos);
5231
+ this.enableExtension(textObj);
5232
+ });
5359
5233
  }
5360
- addAnnotation(annotation, text) {
5234
+ addAnnotation(staffTabOrGroup, annotation, text) {
5361
5235
  let anchor = this.lastAddedRhythmColumn;
5362
5236
  if (!anchor) {
5363
- throw new MusicError14(MusicErrorType14.Score, "Cannot add annotation because anchor is undefined.");
5237
+ throw new MusicError13(MusicErrorType13.Score, "Cannot add annotation because anchor is undefined.");
5364
5238
  } else if (text.length === 0) {
5365
- throw new MusicError14(MusicErrorType14.Score, "Cannot add annotation because annotation text is empty.");
5239
+ throw new MusicError13(MusicErrorType13.Score, "Cannot add annotation because annotation text is empty.");
5366
5240
  }
5367
5241
  let textProps = { text };
5368
5242
  let layoutGroupId;
5369
- let verticalPos;
5243
+ let defaultVerticalPos;
5370
5244
  switch (annotation) {
5371
5245
  case 0 /* Dynamics */:
5372
5246
  layoutGroupId = 5 /* DynamicsAnnotation */;
5373
- verticalPos = 0 /* AboveStaff */;
5247
+ defaultVerticalPos = 0 /* Above */;
5374
5248
  textProps.italic = true;
5375
5249
  break;
5376
5250
  case 1 /* Tempo */:
5377
5251
  layoutGroupId = 4 /* TempoAnnotation */;
5378
- verticalPos = 0 /* AboveStaff */;
5252
+ defaultVerticalPos = 0 /* Above */;
5379
5253
  textProps.italic = true;
5380
5254
  break;
5381
5255
  }
5382
- let textObj = new ObjText(anchor, textProps, 0.5, 1);
5383
- this.addLayoutObject(textObj, layoutGroupId, verticalPos);
5384
- this.enableExtension(textObj);
5256
+ this.forEachStaffGroup(staffTabOrGroup, defaultVerticalPos, (line, vpos) => {
5257
+ let textObj = new ObjText(anchor, textProps, 0.5, 1);
5258
+ this.addLayoutObject(textObj, line, layoutGroupId, vpos);
5259
+ this.enableExtension(textObj);
5260
+ });
5385
5261
  }
5386
5262
  endSong() {
5387
5263
  this.isEndSong = true;
@@ -5403,27 +5279,29 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5403
5279
  this.doc.requestNewRow();
5404
5280
  this.disableExtension();
5405
5281
  }
5406
- enableExtension(musicObj) {
5407
- this.addExtensionToMusicObject = musicObj;
5282
+ enableExtension(musicObject) {
5283
+ this.addExtensionToMusicObjects.push(musicObject);
5408
5284
  }
5409
5285
  disableExtension() {
5410
- this.addExtensionToMusicObject = void 0;
5286
+ this.addExtensionToMusicObjects = [];
5411
5287
  }
5412
5288
  addExtension(extensionLength, extensionVisible) {
5413
- let musicObj = this.addExtensionToMusicObject;
5414
- let anchor = musicObj == null ? void 0 : musicObj.getParent();
5415
- if (musicObj instanceof ObjText && anchor instanceof ObjRhythmColumn) {
5416
- let lineStyle = "dashed";
5417
- let linePos = "bottom";
5418
- let extension = new Extension(musicObj, anchor, extensionLength, extensionVisible, lineStyle, linePos);
5419
- musicObj.setLink(extension);
5420
- this.disableExtension();
5421
- this.requestLayout();
5422
- } else if (musicObj === void 0) {
5423
- throw new MusicError14(MusicErrorType14.Score, "Cannot add extension because music object to attach it to is undefined.");
5424
- } else {
5425
- throw new MusicError14(MusicErrorType14.Score, "Cannot add extension becaue no compatible music object to attach it to.");
5289
+ this.addExtensionToMusicObjects.forEach((musicObj) => {
5290
+ let anchor = musicObj.getParent();
5291
+ if (musicObj instanceof ObjText && anchor instanceof ObjRhythmColumn) {
5292
+ let lineStyle = "dashed";
5293
+ let linePos = "bottom";
5294
+ let extension = new Extension(musicObj, anchor, extensionLength, extensionVisible, lineStyle, linePos);
5295
+ musicObj.setLink(extension);
5296
+ } else {
5297
+ throw new MusicError13(MusicErrorType13.Score, "Cannot add extension becaue no compatible music object to attach it to.");
5298
+ }
5299
+ });
5300
+ if (this.addExtensionToMusicObjects.length === 0) {
5301
+ throw new MusicError13(MusicErrorType13.Score, "Cannot add extension because music object to attach it to is undefined.");
5426
5302
  }
5303
+ this.disableExtension();
5304
+ this.requestLayout();
5427
5305
  }
5428
5306
  addRhythmSymbol(voiceId, symbol) {
5429
5307
  let { col } = symbol;
@@ -5435,7 +5313,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5435
5313
  this.lastAddedRhythmSymbol = symbol;
5436
5314
  }
5437
5315
  addNoteGroup(voiceId, notes, noteLength, options) {
5438
- let notes2 = notes.map((note) => typeof note === "string" ? Note8.getNote(note) : note);
5316
+ let notes2 = notes.map((note) => typeof note === "string" ? Note7.getNote(note) : note);
5439
5317
  let col = this.getRhythmColumn(voiceId);
5440
5318
  this.addRhythmSymbol(voiceId, new ObjNoteGroup(col, voiceId, notes2, noteLength, options));
5441
5319
  }
@@ -5467,7 +5345,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5467
5345
  return col2;
5468
5346
  }
5469
5347
  }
5470
- throw new MusicError14(MusicErrorType14.Score, "Error in rhythm column. Should never get here.");
5348
+ throw new MusicError13(MusicErrorType13.Score, "Error in rhythm column. Should never get here.");
5471
5349
  }
5472
5350
  getMeasureTicks() {
5473
5351
  return this.getTimeSignature().measureTicks;
@@ -5519,11 +5397,15 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5519
5397
  getStaffLineRight() {
5520
5398
  return this.barLineRight.getRect().centerX;
5521
5399
  }
5522
- getStaticObjects() {
5523
- return [
5524
- ...this.getColumns(),
5525
- ...this.layoutObjects.filter((layoutObj) => layoutObj.isPositionResolved()).map((layoutObj) => layoutObj.musicObj)
5526
- ];
5400
+ getStaticObjects(line) {
5401
+ let staticObjects = this.staticObjectsCache.get(line);
5402
+ if (!staticObjects) {
5403
+ staticObjects = [];
5404
+ this.getColumns().forEach((col) => col.getStaticObjects(line).forEach((obj) => staticObjects == null ? void 0 : staticObjects.push(obj)));
5405
+ this.staticObjectsCache.set(line, staticObjects);
5406
+ }
5407
+ let layoutObjects = this.layoutObjects.filter((layoutObj) => layoutObj.line === line && layoutObj.isPositionResolved()).map((layoutObj) => layoutObj.musicObj);
5408
+ return layoutObjects.length > 0 ? [...staticObjects, ...layoutObjects] : staticObjects;
5527
5409
  }
5528
5410
  removeLayoutObjects(musicObj) {
5529
5411
  this.layoutObjects = this.layoutObjects.filter((layoutObj) => {
@@ -5551,16 +5433,22 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5551
5433
  }
5552
5434
  createExtensions() {
5553
5435
  this.layoutObjects.forEach((layoutObj) => {
5554
- if (layoutObj.musicObj.getLink() instanceof Extension) {
5555
- let extension = layoutObj.musicObj.getLink();
5556
- if (extension.getHead() === layoutObj.musicObj) {
5557
- extension.getTails().forEach((musicObj) => layoutObj.measure.removeLayoutObjects(musicObj));
5436
+ var _a;
5437
+ let { musicObj, measure, layoutGroupId, verticalPos, line } = layoutObj;
5438
+ if (musicObj.getLink() instanceof Extension) {
5439
+ let extension = musicObj.getLink();
5440
+ if (extension.getHead() === musicObj) {
5441
+ extension.getTails().forEach((musicObj2) => measure.removeLayoutObjects(musicObj2));
5558
5442
  let { startColumn, endColumn } = extension.getExtensionRangeInfo();
5559
5443
  if (extension.isVisible() && startColumn !== endColumn) {
5560
5444
  for (let m = startColumn.measure; m !== void 0; m = m === endColumn.measure ? void 0 : m.getNextMeasure()) {
5561
5445
  let leftObj = m === startColumn.measure ? extension.getHead() : m.getBarLineLeft();
5562
5446
  let rightObj = m === endColumn.measure ? endColumn : m.getBarLineRight();
5563
- m.addLayoutObject(new ObjExtensionLine(m, extension, leftObj, rightObj), layoutObj.layoutGroupId, layoutObj.verticalPos);
5447
+ const lines = m.row.getNotationLines();
5448
+ let line2 = (_a = lines.find((l) => l.name !== "" && l.name === line.name)) != null ? _a : lines[line.id];
5449
+ if (line2) {
5450
+ m.addLayoutObject(new ObjExtensionLine(m, extension, leftObj, rightObj), line2, layoutGroupId, verticalPos);
5451
+ }
5564
5452
  }
5565
5453
  }
5566
5454
  }
@@ -5667,7 +5555,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5667
5555
  let consumedTicks = this.getConsumedTicks(voiceId);
5668
5556
  let remainingTicks = measureTicks - consumedTicks;
5669
5557
  let rests = [];
5670
- let noteLengthValues = Utils9.Enum.getEnumValues(NoteLength6);
5558
+ let noteLengthValues = Utils8.Enum.getEnumValues(NoteLength6);
5671
5559
  while (remainingTicks > 0) {
5672
5560
  noteLengthValues.forEach((restLength) => {
5673
5561
  let restValue = new RhythmProps4(restLength, false);
@@ -5697,6 +5585,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5697
5585
  if (!this.needLayout) {
5698
5586
  return;
5699
5587
  }
5588
+ this.staticObjectsCache.clear();
5700
5589
  this.requestRectUpdate();
5701
5590
  let { unitSize } = renderer;
5702
5591
  this.postMeasureBreakWidth = this.hasPostMeasureBreak() ? DocumentSettings.PostMeasureBreakWidth * unitSize : 0;
@@ -5744,6 +5633,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5744
5633
  if (this.endRepeatPlayCountText) {
5745
5634
  this.endRepeatPlayCountText.layout(renderer);
5746
5635
  }
5636
+ this.layoutObjects.forEach((layoutObj) => layoutObj.layout(renderer));
5747
5637
  let padding = renderer.unitSize;
5748
5638
  this.leftSolidAreaWidth = this.tabStringNotesWidth + Math.max(0, ...this.signatures.map((signature) => signature.getRect().width)) + this.barLineLeft.getRect().width + padding;
5749
5639
  this.rightSolidAreaWidth = padding + this.barLineRight.getRect().width;
@@ -5775,7 +5665,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5775
5665
  let columnsAreaLeft = this.rect.left + this.leftSolidAreaWidth;
5776
5666
  let columnsAreaRight = this.rect.right - this.rightSolidAreaWidth;
5777
5667
  let columnsAreaWidth = columnsAreaRight - columnsAreaLeft;
5778
- let columnsWidth = Utils9.Math.sum(this.columns.map((col) => col.getRect().width));
5668
+ let columnsWidth = Utils8.Math.sum(this.columns.map((col) => col.getRect().width));
5779
5669
  let columnScale = columnsAreaWidth / columnsWidth;
5780
5670
  let columnLeft = columnsAreaLeft;
5781
5671
  this.columns.forEach((col) => {
@@ -5820,7 +5710,8 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5820
5710
  ...this.columns.filter((col) => !col.isEmpty()).map((col) => col.getRect().top),
5821
5711
  this.barLineRight.getRect().top,
5822
5712
  ...this.connectives.map((c) => c.getRect().top),
5823
- ...this.beamGroups.filter((b) => !b.isEmpty()).map((b) => b.getRect().top)
5713
+ ...this.beamGroups.filter((b) => !b.isEmpty()).map((b) => b.getRect().top),
5714
+ ...this.layoutObjects.filter((o) => o.isPositionResolved()).map((o) => o.musicObj.getRect().top)
5824
5715
  );
5825
5716
  this.rect.bottom = Math.max(
5826
5717
  ...this.signatures.map((s) => s.getRect().bottom),
@@ -5829,12 +5720,20 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5829
5720
  ...this.columns.filter((col) => !col.isEmpty()).map((col) => col.getRect().bottom),
5830
5721
  this.barLineRight.getRect().bottom,
5831
5722
  ...this.connectives.map((c) => c.getRect().bottom),
5832
- ...this.beamGroups.filter((b) => !b.isEmpty()).map((b) => b.getRect().bottom)
5723
+ ...this.beamGroups.filter((b) => !b.isEmpty()).map((b) => b.getRect().bottom),
5724
+ ...this.layoutObjects.filter((o) => o.isPositionResolved()).map((o) => o.musicObj.getRect().bottom)
5833
5725
  );
5726
+ if (this === this.row.getLastMeasure()) {
5727
+ this.rect.right = Math.max(
5728
+ this.rect.right,
5729
+ ...this.layoutObjects.filter((o) => o.isPositionResolved() && o.musicObj instanceof ObjFermata).map((o) => o.musicObj.getRect().right)
5730
+ );
5731
+ }
5834
5732
  this.row.getNotationLines().forEach((line) => {
5835
5733
  this.rect.top = Math.min(this.rect.top, line.calcTop());
5836
5734
  this.rect.bottom = Math.max(this.rect.bottom, line.calcBottom());
5837
5735
  });
5736
+ this.row.requestRectUpdate();
5838
5737
  }
5839
5738
  offset(dx, dy) {
5840
5739
  this.signatures.forEach((signature) => signature.offset(dx, 0));
@@ -5847,7 +5746,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5847
5746
  }
5848
5747
  this.connectives.forEach((connective) => connective.offset(dx, 0));
5849
5748
  this.beamGroups.forEach((beam) => beam.offset(dx, dy));
5850
- this.layoutObjects.forEach((layoutObj) => layoutObj.musicObj.offset(dx, dy));
5749
+ this.layoutObjects.forEach((layoutObj) => layoutObj.offset(dx, 0));
5851
5750
  this.rect.offsetInPlace(dx, dy);
5852
5751
  this.requestRectUpdate();
5853
5752
  }
@@ -5862,7 +5761,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5862
5761
  for (let p = line.bottomLineDiatonicId; p <= line.topLineDiatonicId; p += 2) {
5863
5762
  drawLine(line.getDiatonicIdY(p));
5864
5763
  }
5865
- } else {
5764
+ } else if (line instanceof ObjTab) {
5866
5765
  for (let stringId = 0; stringId < 6; stringId++) {
5867
5766
  drawLine(line.getStringY(stringId));
5868
5767
  }
@@ -5885,7 +5784,7 @@ __publicField(_ObjMeasure, "MinFlexContentWidth", 10);
5885
5784
  var ObjMeasure2 = _ObjMeasure;
5886
5785
 
5887
5786
  // src/score/engine/layout-object.ts
5888
- import { MusicError as MusicError15, MusicErrorType as MusicErrorType15 } from "@tspro/web-music-score/core";
5787
+ import { MusicError as MusicError14, MusicErrorType as MusicErrorType14 } from "@tspro/web-music-score/core";
5889
5788
  var WidenColumnList = [1 /* NoteLabel */, 6 /* ChordLabel */];
5890
5789
  var RowAlignList = [2 /* Navigation */, 3 /* Ending */, 4 /* TempoAnnotation */, 5 /* DynamicsAnnotation */, 6 /* ChordLabel */];
5891
5790
  function requireParentMeasure(p) {
@@ -5895,11 +5794,19 @@ function requireParentMeasure(p) {
5895
5794
  }
5896
5795
  p = p.getParent();
5897
5796
  }
5898
- throw new MusicError15(MusicErrorType15.Score, "Parent measure is required but not found!");
5797
+ throw new MusicError14(MusicErrorType14.Score, "Parent measure is required but not found!");
5899
5798
  }
5799
+ var StaffGroup = class {
5800
+ constructor(groupName, staffsTabsAndGroups, verticalPosition) {
5801
+ this.groupName = groupName;
5802
+ this.staffsTabsAndGroups = staffsTabsAndGroups;
5803
+ this.verticalPosition = verticalPosition;
5804
+ }
5805
+ };
5900
5806
  var LayoutObjectWrapper = class {
5901
- constructor(musicObj, layoutGroupId, verticalPos) {
5807
+ constructor(musicObj, line, layoutGroupId, verticalPos) {
5902
5808
  this.musicObj = musicObj;
5809
+ this.line = line;
5903
5810
  this.layoutGroupId = layoutGroupId;
5904
5811
  this.verticalPos = verticalPos;
5905
5812
  __publicField(this, "anchor");
@@ -5907,15 +5814,15 @@ var LayoutObjectWrapper = class {
5907
5814
  __publicField(this, "row");
5908
5815
  __publicField(this, "layoutGroup");
5909
5816
  __publicField(this, "positionResolved", true);
5910
- this.measure = requireParentMeasure(musicObj);
5817
+ this.measure = requireParentMeasure(this.musicObj);
5911
5818
  this.row = this.measure.row;
5912
5819
  let anchor = this.musicObj.getParent();
5913
5820
  if (!anchor) {
5914
- throw new MusicError15(MusicErrorType15.Score, "Parent music object is required as an anchor.");
5821
+ throw new MusicError14(MusicErrorType14.Score, "Parent music object is required as an anchor.");
5915
5822
  }
5916
5823
  this.anchor = anchor;
5917
5824
  this.anchor.addAnchoredLayoutObject(this);
5918
- this.layoutGroup = this.measure.doc.getLayoutGroup(layoutGroupId);
5825
+ this.layoutGroup = this.line.getLayoutGroup(layoutGroupId);
5919
5826
  this.layoutGroup.add(this);
5920
5827
  }
5921
5828
  clearPositionResolved() {
@@ -5928,20 +5835,19 @@ var LayoutObjectWrapper = class {
5928
5835
  return this.positionResolved;
5929
5836
  }
5930
5837
  resolveClosestToStaffY(renderer) {
5931
- let { musicObj, measure, verticalPos } = this;
5932
- let { row } = measure;
5933
- let staffTop = row.hasStaff ? row.getTopStaff().getTopLineY() : row.getRect().centerY;
5934
- let staffBottom = row.hasStaff ? row.getBottomStaff().getBottomLineY() : row.getRect().centerY;
5935
- let staffPadding = renderer.unitSize * 2;
5936
- let y = verticalPos === 1 /* BelowStaff */ ? staffBottom + staffPadding + musicObj.getRect().toph : staffTop - staffPadding - musicObj.getRect().bottomh;
5937
- let staticObjects = measure.getStaticObjects();
5838
+ let { musicObj, measure, verticalPos, line } = this;
5839
+ let lineTop = line.getTopLineY();
5840
+ let lineBottom = line.getBottomLineY();
5841
+ let linePadding = renderer.unitSize * 2;
5842
+ let y = verticalPos === 1 /* Below */ ? lineBottom + linePadding + musicObj.getRect().toph : lineTop - linePadding - musicObj.getRect().bottomh;
5843
+ let staticObjects = measure.getStaticObjects(line);
5938
5844
  let objShapeRects = musicObj.getShapeRects();
5939
5845
  staticObjects.forEach((staticObj) => {
5940
5846
  let staticShapeRects = staticObj.getShapeRects();
5941
5847
  objShapeRects.forEach((objR) => {
5942
5848
  staticShapeRects.forEach((staticR) => {
5943
5849
  if (DivRect.overlapX(objR, staticR)) {
5944
- y = verticalPos === 1 /* BelowStaff */ ? Math.max(y, staticR.bottom + objR.toph + objR.centerY) : Math.min(y, staticR.top - objR.bottomh - objR.centerY);
5850
+ y = verticalPos === 1 /* Below */ ? Math.max(y, staticR.bottom + objR.toph + objR.centerY) : Math.min(y, staticR.top - objR.bottomh - objR.centerY);
5945
5851
  }
5946
5852
  });
5947
5853
  });
@@ -5955,6 +5861,15 @@ var LayoutObjectWrapper = class {
5955
5861
  return void 0;
5956
5862
  }
5957
5863
  }
5864
+ layout(renderer) {
5865
+ this.line.addObject(this);
5866
+ }
5867
+ offset(dx, dy) {
5868
+ this.musicObj.offset(dx, dy);
5869
+ }
5870
+ getRect() {
5871
+ return this.musicObj.getRect();
5872
+ }
5958
5873
  };
5959
5874
  var LayoutGroup = class {
5960
5875
  constructor(layoutGroupId) {
@@ -5962,8 +5877,8 @@ var LayoutGroup = class {
5962
5877
  __publicField(this, "layoutObjectTable", []);
5963
5878
  __publicField(this, "rowAlign");
5964
5879
  __publicField(this, "widensColumn");
5965
- this.layoutObjectTable[0 /* AboveStaff */] = [];
5966
- this.layoutObjectTable[1 /* BelowStaff */] = [];
5880
+ this.layoutObjectTable[0 /* Above */] = [];
5881
+ this.layoutObjectTable[1 /* Below */] = [];
5967
5882
  this.rowAlign = RowAlignList.indexOf(layoutGroupId) >= 0;
5968
5883
  this.widensColumn = WidenColumnList.indexOf(layoutGroupId) >= 0;
5969
5884
  }
@@ -5991,6 +5906,333 @@ var LayoutGroup = class {
5991
5906
  }
5992
5907
  };
5993
5908
 
5909
+ // src/score/engine/obj-staff-and-tab.ts
5910
+ var ObjNotationLine4 = class extends MusicObject {
5911
+ constructor(parent) {
5912
+ super(parent);
5913
+ __publicField(this, "objects", []);
5914
+ __publicField(this, "layoutGroups", []);
5915
+ }
5916
+ addObject(o) {
5917
+ this.objects.push(o);
5918
+ }
5919
+ removeObjects() {
5920
+ this.objects.length = 0;
5921
+ }
5922
+ getLayoutGroup(lauoutGroupId) {
5923
+ let layoutGroup = this.layoutGroups[lauoutGroupId];
5924
+ if (!layoutGroup) {
5925
+ layoutGroup = this.layoutGroups[lauoutGroupId] = new LayoutGroup(lauoutGroupId);
5926
+ }
5927
+ return layoutGroup;
5928
+ }
5929
+ resetLayoutGroups(renderer) {
5930
+ this.layoutGroups.forEach((layoutGroup) => {
5931
+ if (layoutGroup) {
5932
+ layoutGroup.clearPositionAndLayout(renderer);
5933
+ }
5934
+ });
5935
+ }
5936
+ layoutLayoutGroups(renderer) {
5937
+ this.layoutGroups.forEach((layoutGroup) => {
5938
+ if (layoutGroup) {
5939
+ this.layoutLayoutGroup(renderer, layoutGroup, 0 /* Above */);
5940
+ this.layoutLayoutGroup(renderer, layoutGroup, 1 /* Below */);
5941
+ }
5942
+ });
5943
+ }
5944
+ setObjectY(layoutObj, y) {
5945
+ if (y === void 0) {
5946
+ return;
5947
+ }
5948
+ layoutObj.offset(0, y - layoutObj.getRect().centerY);
5949
+ layoutObj.setPositionResolved();
5950
+ }
5951
+ alignObjectsY(renderer, layoutObjArr) {
5952
+ layoutObjArr = layoutObjArr.filter((layoutObj) => !layoutObj.isPositionResolved());
5953
+ let rowY;
5954
+ layoutObjArr.forEach((layoutObj) => {
5955
+ let y = layoutObj.resolveClosestToStaffY(renderer);
5956
+ rowY = layoutObj.verticalPos === 1 /* Below */ ? Math.max(y, rowY != null ? rowY : y) : Math.min(y, rowY != null ? rowY : y);
5957
+ });
5958
+ layoutObjArr.forEach((layoutObj) => this.setObjectY(layoutObj, rowY));
5959
+ }
5960
+ layoutLayoutGroup(renderer, layoutGroup, verticalPos) {
5961
+ let rowLayoutObjs = layoutGroup.getLayoutObjects(verticalPos).filter((layoutObj) => !layoutObj.isPositionResolved());
5962
+ rowLayoutObjs.forEach((layoutObj) => {
5963
+ let { musicObj, anchor } = layoutObj;
5964
+ if (musicObj instanceof ObjEnding || musicObj instanceof ObjExtensionLine) {
5965
+ musicObj.layoutFitToMeasure(renderer);
5966
+ } else {
5967
+ musicObj.offset(anchor.getRect().centerX - musicObj.getRect().centerX, 0);
5968
+ }
5969
+ });
5970
+ if (layoutGroup.rowAlign) {
5971
+ this.alignObjectsY(renderer, rowLayoutObjs);
5972
+ } else {
5973
+ rowLayoutObjs.forEach((layoutObj) => {
5974
+ let link = layoutObj.musicObj.getLink();
5975
+ if (link && link.getHead() === layoutObj.musicObj) {
5976
+ let objectParts = [link.getHead(), ...link.getTails()];
5977
+ let layoutObjs = rowLayoutObjs.filter((layoutObj2) => objectParts.some((o) => o === layoutObj2.musicObj));
5978
+ this.alignObjectsY(renderer, layoutObjs);
5979
+ } else {
5980
+ this.alignObjectsY(renderer, [layoutObj]);
5981
+ }
5982
+ });
5983
+ }
5984
+ }
5985
+ };
5986
+ var ObjStaff = class extends ObjNotationLine4 {
5987
+ constructor(row, staffConfig, id) {
5988
+ super(row);
5989
+ this.row = row;
5990
+ this.staffConfig = staffConfig;
5991
+ this.id = id;
5992
+ __publicField(this, "clefImageAsset");
5993
+ __publicField(this, "clefLineDiatonicId");
5994
+ __publicField(this, "topLineDiatonicId");
5995
+ __publicField(this, "middleLineDiatonicId");
5996
+ __publicField(this, "bottomLineDiatonicId");
5997
+ __publicField(this, "minDiatonicId");
5998
+ __publicField(this, "maxDiatonicId");
5999
+ __publicField(this, "joinedGrandStaff");
6000
+ __publicField(this, "topLineY", 0);
6001
+ __publicField(this, "bottomLineY", 0);
6002
+ __publicField(this, "mi");
6003
+ const getDiatonicId = (noteName, isOctaveDown) => Note8.getNote(noteName).diatonicId - (isOctaveDown ? 7 : 0);
6004
+ if (staffConfig.clef === "G" /* G */) {
6005
+ this.clefImageAsset = 0 /* TrebleClefPng */;
6006
+ this.clefLineDiatonicId = getDiatonicId("G4", staffConfig.isOctaveDown === true);
6007
+ this.middleLineDiatonicId = this.clefLineDiatonicId + 2;
6008
+ } else {
6009
+ this.clefImageAsset = 1 /* BassClefPng */;
6010
+ this.clefLineDiatonicId = getDiatonicId("F3", staffConfig.isOctaveDown === true);
6011
+ this.middleLineDiatonicId = this.clefLineDiatonicId - 2;
6012
+ }
6013
+ this.topLineDiatonicId = this.middleLineDiatonicId + 4;
6014
+ this.bottomLineDiatonicId = this.middleLineDiatonicId - 4;
6015
+ this.minDiatonicId = staffConfig.minNote !== void 0 ? Math.min(getDiatonicId(staffConfig.minNote, false), this.bottomLineDiatonicId) : void 0;
6016
+ this.maxDiatonicId = staffConfig.maxNote !== void 0 ? Math.max(getDiatonicId(staffConfig.maxNote, false), this.topLineDiatonicId) : void 0;
6017
+ this.mi = new MStaff(this);
6018
+ }
6019
+ getMusicInterface() {
6020
+ return this.mi;
6021
+ }
6022
+ get isOctaveDown() {
6023
+ return this.staffConfig.isOctaveDown === true;
6024
+ }
6025
+ get name() {
6026
+ var _a;
6027
+ return (_a = this.staffConfig.name) != null ? _a : "";
6028
+ }
6029
+ getTopLineY() {
6030
+ return this.topLineY;
6031
+ }
6032
+ getMiddleLineY() {
6033
+ return (this.topLineY + this.bottomLineY) / 2;
6034
+ }
6035
+ getBottomLineY() {
6036
+ return this.bottomLineY;
6037
+ }
6038
+ joinGrandStaff(staff) {
6039
+ if (staff !== this) {
6040
+ this.joinedGrandStaff = staff;
6041
+ }
6042
+ }
6043
+ getLineSpacing() {
6044
+ return (this.bottomLineY - this.topLineY) / 4;
6045
+ }
6046
+ getDiatonicSpacing() {
6047
+ return this.getLineSpacing() / 2;
6048
+ }
6049
+ containsDiatonicId(diatonicId) {
6050
+ Note8.validateDiatonicId(diatonicId);
6051
+ return (this.minDiatonicId === void 0 || diatonicId >= this.minDiatonicId) && (this.maxDiatonicId === void 0 || diatonicId <= this.maxDiatonicId);
6052
+ }
6053
+ getDiatonicIdY(diatonicId) {
6054
+ if (this.containsDiatonicId(diatonicId)) {
6055
+ return this.bottomLineY + (this.bottomLineDiatonicId - diatonicId) * this.getDiatonicSpacing();
6056
+ } else if (this.joinedGrandStaff && this.joinedGrandStaff.containsDiatonicId(diatonicId)) {
6057
+ return this.joinedGrandStaff.getDiatonicIdY(diatonicId);
6058
+ } else {
6059
+ throw new MusicError15(MusicErrorType15.Score, "Staff does not contain diatonicId " + diatonicId);
6060
+ }
6061
+ }
6062
+ getActualStaff(diatonicId) {
6063
+ if (this.containsDiatonicId(diatonicId)) {
6064
+ return this;
6065
+ } else if (this.joinedGrandStaff && this.joinedGrandStaff.containsDiatonicId(diatonicId)) {
6066
+ return this.joinedGrandStaff;
6067
+ } else {
6068
+ throw new MusicError15(MusicErrorType15.Score, "Staff does not contain diatonicId " + diatonicId);
6069
+ }
6070
+ }
6071
+ getDiatonicIdAt(y) {
6072
+ let diatonicId = Math.round(this.bottomLineDiatonicId - (y - this.bottomLineY) / this.getDiatonicSpacing());
6073
+ return this.containsDiatonicId(diatonicId) ? diatonicId : void 0;
6074
+ }
6075
+ isLine(diatonicId) {
6076
+ return diatonicId % 2 === this.middleLineDiatonicId % 2;
6077
+ }
6078
+ isSpace(diatonicId) {
6079
+ return diatonicId % 2 !== this.middleLineDiatonicId % 2;
6080
+ }
6081
+ containsVoiceId(voiceId) {
6082
+ return !this.staffConfig.voiceIds || this.staffConfig.voiceIds.includes(voiceId);
6083
+ }
6084
+ isGrand() {
6085
+ return this.staffConfig.isGrand === true;
6086
+ }
6087
+ calcTop() {
6088
+ let top = this.topLineY;
6089
+ this.objects.forEach((o) => top = Math.min(top, o.getRect().top));
6090
+ if (this.maxDiatonicId !== void 0) {
6091
+ let y = this.getDiatonicIdY(this.maxDiatonicId);
6092
+ let y2 = this.getDiatonicIdY(this.maxDiatonicId - 1);
6093
+ top = Math.min(top, y - Math.abs(y2 - y) + 1);
6094
+ }
6095
+ return top;
6096
+ }
6097
+ calcBottom() {
6098
+ let bottom = this.bottomLineY;
6099
+ this.objects.forEach((o) => bottom = Math.max(bottom, o.getRect().bottom));
6100
+ if (this.minDiatonicId !== void 0) {
6101
+ let y = this.getDiatonicIdY(this.minDiatonicId);
6102
+ let y2 = this.getDiatonicIdY(this.minDiatonicId + 1);
6103
+ bottom = Math.max(bottom, y + Math.abs(y2 - y) - 1);
6104
+ }
6105
+ return bottom;
6106
+ }
6107
+ pick(x, y) {
6108
+ return [this];
6109
+ }
6110
+ layoutHeight(renderer) {
6111
+ let { unitSize } = renderer;
6112
+ let h = unitSize * DocumentSettings.StaffHeight;
6113
+ this.topLineY = -h / 2;
6114
+ this.bottomLineY = h / 2;
6115
+ this.rect = new DivRect(0, 0, this.topLineY, this.bottomLineY);
6116
+ }
6117
+ layoutWidth(renderer) {
6118
+ this.rect.left = this.row.getRect().left;
6119
+ this.rect.right = this.row.getRect().right;
6120
+ }
6121
+ offset(dx, dy) {
6122
+ this.topLineY += dy;
6123
+ this.bottomLineY += dy;
6124
+ this.objects.forEach((o) => {
6125
+ if (o.offsetInPlace) {
6126
+ o.offsetInPlace(0, dy);
6127
+ } else if (o.offset) {
6128
+ o.offset(0, dy);
6129
+ }
6130
+ });
6131
+ this.rect.offsetInPlace(dx, dy);
6132
+ }
6133
+ draw(renderer) {
6134
+ }
6135
+ };
6136
+ var ObjTab = class extends ObjNotationLine4 {
6137
+ constructor(row, tabConfig, id) {
6138
+ super(row);
6139
+ this.row = row;
6140
+ this.tabConfig = tabConfig;
6141
+ this.id = id;
6142
+ __publicField(this, "top", 0);
6143
+ __publicField(this, "bottom", 0);
6144
+ __publicField(this, "tuningName");
6145
+ __publicField(this, "tuningStrings");
6146
+ __publicField(this, "mi");
6147
+ if (Utils9.Is.isArray(tabConfig.tuning)) {
6148
+ this.tuningName = void 0;
6149
+ this.tuningStrings = tabConfig.tuning.map((noteName) => Note8.getNote(noteName)).reverse();
6150
+ } else if (typeof tabConfig.tuning === "string") {
6151
+ this.tuningName = validateTuningName(tabConfig.tuning);
6152
+ this.tuningStrings = getTuningStrings(this.tuningName);
6153
+ } else {
6154
+ this.tuningName = "Standard";
6155
+ this.tuningStrings = getTuningStrings(this.tuningName);
6156
+ }
6157
+ this.mi = new MTab(this);
6158
+ }
6159
+ getMusicInterface() {
6160
+ return this.mi;
6161
+ }
6162
+ get name() {
6163
+ var _a;
6164
+ return (_a = this.tabConfig.name) != null ? _a : "";
6165
+ }
6166
+ getTuningName() {
6167
+ return this.tuningName;
6168
+ }
6169
+ getTuningStrings() {
6170
+ return this.tuningStrings;
6171
+ }
6172
+ /** Return Y coordinate of string. */
6173
+ getStringY(stringId) {
6174
+ return this.top + (this.bottom - this.top) / 6 * (stringId + 0.5);
6175
+ }
6176
+ getTopStringY() {
6177
+ return this.getStringY(0);
6178
+ }
6179
+ getBottomStringY() {
6180
+ return this.getStringY(5);
6181
+ }
6182
+ getTopLineY() {
6183
+ return this.getTopStringY();
6184
+ }
6185
+ getBottomLineY() {
6186
+ return this.getBottomStringY();
6187
+ }
6188
+ getTop() {
6189
+ return this.top;
6190
+ }
6191
+ getBottom() {
6192
+ return this.bottom;
6193
+ }
6194
+ containsVoiceId(voiceId) {
6195
+ return !this.tabConfig.voiceIds || this.tabConfig.voiceIds.includes(voiceId);
6196
+ }
6197
+ containsDiatonicId(diatonicId) {
6198
+ return true;
6199
+ }
6200
+ calcTop() {
6201
+ return this.top;
6202
+ }
6203
+ calcBottom() {
6204
+ return this.bottom;
6205
+ }
6206
+ pick(x, y) {
6207
+ return [this];
6208
+ }
6209
+ layoutHeight(renderer) {
6210
+ let { unitSize } = renderer;
6211
+ let h = unitSize * DocumentSettings.TabHeight;
6212
+ this.top = -h / 2;
6213
+ this.bottom = h / 2;
6214
+ this.rect = new DivRect(0, 0, this.top, this.bottom);
6215
+ }
6216
+ layoutWidth(renderer) {
6217
+ this.rect.left = this.row.getRect().left;
6218
+ this.rect.right = this.row.getRect().right;
6219
+ }
6220
+ offset(dx, dy) {
6221
+ this.top += dy;
6222
+ this.bottom += dy;
6223
+ this.objects.forEach((o) => {
6224
+ if (o.offsetInPlace) {
6225
+ o.offsetInPlace(0, dy);
6226
+ } else if (o.offset) {
6227
+ o.offset(0, dy);
6228
+ }
6229
+ });
6230
+ this.rect.offsetInPlace(dx, dy);
6231
+ }
6232
+ draw(renderer) {
6233
+ }
6234
+ };
6235
+
5994
6236
  // src/score/engine/obj-score-row.ts
5995
6237
  import { MusicError as MusicError16, MusicErrorType as MusicErrorType16 } from "@tspro/web-music-score/core";
5996
6238
  var ObjScoreRow = class extends MusicObject {
@@ -6019,7 +6261,7 @@ var ObjScoreRow = class extends MusicObject {
6019
6261
  return this.mi;
6020
6262
  }
6021
6263
  createNotationLines() {
6022
- let notationLines = this.scoreConfig.map((cfg) => cfg.type === "staff" ? new ObjStaff(this, cfg) : new ObjTab(this, cfg));
6264
+ let notationLines = this.scoreConfig.map((cfg, index) => cfg.type === "staff" ? new ObjStaff(this, cfg, index) : new ObjTab(this, cfg, index));
6023
6265
  for (let i = 0; i < notationLines.length - 1; i++) {
6024
6266
  let treble = notationLines[i];
6025
6267
  let bass = notationLines[i + 1];
@@ -6071,6 +6313,12 @@ var ObjScoreRow = class extends MusicObject {
6071
6313
  }
6072
6314
  return void 0;
6073
6315
  }
6316
+ resetLayoutGroups(renderer) {
6317
+ this.notationLines.forEach((line) => line.resetLayoutGroups(renderer));
6318
+ }
6319
+ layoutLayoutGroups(renderer) {
6320
+ this.notationLines.forEach((line) => line.layoutLayoutGroups(renderer));
6321
+ }
6074
6322
  pick(x, y) {
6075
6323
  if (!this.getRect().contains(x, y)) {
6076
6324
  return [];
@@ -6151,7 +6399,6 @@ var ObjScoreRow = class extends MusicObject {
6151
6399
  this.minWidth = 0;
6152
6400
  this.measures.forEach((m) => {
6153
6401
  m.layout(renderer);
6154
- this.rect.expandInPlace(new DivRect(0, 0, m.getRect().top, m.getRect().bottom));
6155
6402
  this.minWidth += m.getMinWidth();
6156
6403
  this.minWidth += m.getPostMeasureBreakWidth();
6157
6404
  });
@@ -6185,6 +6432,13 @@ var ObjScoreRow = class extends MusicObject {
6185
6432
  m.layoutBeams(renderer);
6186
6433
  });
6187
6434
  }
6435
+ updateRect() {
6436
+ let left = this.measures.length > 0 ? this.measures[0].getRect().left : 0;
6437
+ let right = this.measures.length > 0 ? this.measures[this.measures.length - 1].getRect().right : 0;
6438
+ let top = Math.min(0, ...this.measures.map((m) => m.getRect().top));
6439
+ let bottom = Math.max(0, ...this.measures.map((m) => m.getRect().bottom));
6440
+ this.rect = new DivRect(left, right, top, bottom);
6441
+ }
6188
6442
  alignStemsToBeams() {
6189
6443
  this.measures.forEach((m) => m.alignStemsToBeams());
6190
6444
  }
@@ -6201,7 +6455,6 @@ var ObjScoreRow = class extends MusicObject {
6201
6455
  cur.offset(0, prev.calcBottom() - cur.calcTop() + sep);
6202
6456
  }
6203
6457
  }
6204
- this.requestRectUpdate();
6205
6458
  this.measures.forEach((m) => {
6206
6459
  m.requestRectUpdate();
6207
6460
  m.getBarLineLeft().requestRectUpdate();
@@ -6214,59 +6467,12 @@ var ObjScoreRow = class extends MusicObject {
6214
6467
  });
6215
6468
  });
6216
6469
  });
6217
- let lines = this.getNotationLines();
6218
- this.rect.top = lines[0].calcTop();
6219
- this.rect.bottom = lines[lines.length - 1].calcBottom();
6220
6470
  this.alignStemsToBeams();
6221
- }
6222
- updateRect() {
6223
- }
6224
- setObjectY(layoutObj, y) {
6225
- if (y === void 0) {
6226
- return;
6227
- }
6228
- let { measure, musicObj } = layoutObj;
6229
- musicObj.offset(0, y - musicObj.getRect().centerY);
6230
- layoutObj.setPositionResolved();
6231
- measure.getRect().expandInPlace(musicObj.getRect());
6232
- this.rect.expandInPlace(measure.getRect());
6233
- }
6234
- alignObjectsY(renderer, layoutObjArr) {
6235
- layoutObjArr = layoutObjArr.filter((layoutObj) => !layoutObj.isPositionResolved());
6236
- let rowY;
6237
- layoutObjArr.forEach((layoutObj) => {
6238
- let y = layoutObj.resolveClosestToStaffY(renderer);
6239
- rowY = layoutObj.verticalPos === 1 /* BelowStaff */ ? Math.max(y, rowY != null ? rowY : y) : Math.min(y, rowY != null ? rowY : y);
6240
- });
6241
- layoutObjArr.forEach((layoutObj) => this.setObjectY(layoutObj, rowY));
6242
- }
6243
- layoutLayoutGroup(renderer, layoutGroup, verticalPos) {
6244
- let rowLayoutObjs = layoutGroup.getLayoutObjects(verticalPos).filter((layoutObj) => layoutObj.row === this && !layoutObj.isPositionResolved());
6245
- rowLayoutObjs.forEach((layoutObj) => {
6246
- let { musicObj, anchor } = layoutObj;
6247
- if (musicObj instanceof ObjEnding || musicObj instanceof ObjExtensionLine) {
6248
- musicObj.layoutFitToMeasure(renderer);
6249
- } else {
6250
- musicObj.offset(anchor.getRect().centerX - musicObj.getRect().centerX, 0);
6251
- }
6252
- });
6253
- if (layoutGroup.rowAlign) {
6254
- this.alignObjectsY(renderer, rowLayoutObjs);
6255
- } else {
6256
- rowLayoutObjs.forEach((layoutObj) => {
6257
- let link = layoutObj.musicObj.getLink();
6258
- if (link && link.getHead() === layoutObj.musicObj) {
6259
- let objectParts = [link.getHead(), ...link.getTails()];
6260
- let layoutObjs = rowLayoutObjs.filter((layoutObj2) => objectParts.some((o) => o === layoutObj2.musicObj));
6261
- this.alignObjectsY(renderer, layoutObjs);
6262
- } else {
6263
- this.alignObjectsY(renderer, [layoutObj]);
6264
- }
6265
- });
6266
- }
6471
+ this.requestRectUpdate();
6267
6472
  }
6268
6473
  layoutPadding(renderer) {
6269
6474
  let p = renderer.unitSize / 2;
6475
+ this.getRect();
6270
6476
  this.rect.left -= p;
6271
6477
  this.rect.right += p;
6272
6478
  this.rect.top -= p;
@@ -6290,21 +6496,10 @@ var ObjScoreRow = class extends MusicObject {
6290
6496
  ctx.save();
6291
6497
  ctx.rect(this.getRect().left, this.getRect().top, this.getRect().width, this.getRect().height);
6292
6498
  ctx.clip();
6293
- if (this.getFirstMeasure() && this.notationLines.length > 1 || this.notationLines.length === 1 && this.notationLines[0] instanceof ObjTab) {
6499
+ if (this.getFirstMeasure() && (this.notationLines.length > 1 || this.notationLines[0] instanceof ObjTab)) {
6294
6500
  let left = this.getFirstMeasure().getStaffLineLeft();
6295
- let tops = [];
6296
- let bottoms = [];
6297
- this.notationLines.forEach((line) => {
6298
- if (line instanceof ObjStaff) {
6299
- tops.push(line.getTopLineY());
6300
- bottoms.push(line.getBottomLineY());
6301
- } else {
6302
- tops.push(line.getTopStringY());
6303
- bottoms.push(line.getBottomStringY());
6304
- }
6305
- });
6306
- let top = Math.min(...tops);
6307
- let bottom = Math.max(...bottoms);
6501
+ let top = Math.min(...this.notationLines.map((line) => line.getTopLineY()));
6502
+ let bottom = Math.max(...this.notationLines.map((line) => line.getBottomLineY()));
6308
6503
  renderer.drawLine(left, top, left, bottom);
6309
6504
  }
6310
6505
  this.measures.forEach((m) => m.draw(renderer));
@@ -6415,9 +6610,9 @@ var ObjDocument = class extends MusicObject {
6415
6610
  __publicField(this, "measuresPerRow", Infinity);
6416
6611
  __publicField(this, "curScoreConfig", [{ type: "staff", clef: "G" /* G */ }]);
6417
6612
  __publicField(this, "header");
6418
- __publicField(this, "layoutGroups", []);
6419
6613
  __publicField(this, "newRowRequested", false);
6420
6614
  __publicField(this, "allConnectiveProps", []);
6615
+ __publicField(this, "staffGroups", /* @__PURE__ */ new Map());
6421
6616
  __publicField(this, "mi");
6422
6617
  this.mi = new MDocument2(this);
6423
6618
  }
@@ -6483,13 +6678,6 @@ var ObjDocument = class extends MusicObject {
6483
6678
  addConnectiveProps(connectiveProps) {
6484
6679
  this.allConnectiveProps.push(connectiveProps);
6485
6680
  }
6486
- getLayoutGroup(lauoutGroupId) {
6487
- let layoutGroup = this.layoutGroups[lauoutGroupId];
6488
- if (!layoutGroup) {
6489
- layoutGroup = this.layoutGroups[lauoutGroupId] = new LayoutGroup(lauoutGroupId);
6490
- }
6491
- return layoutGroup;
6492
- }
6493
6681
  setRenderer(renderer) {
6494
6682
  if (this.renderer === renderer) {
6495
6683
  return;
@@ -6555,6 +6743,12 @@ var ObjDocument = class extends MusicObject {
6555
6743
  this.requestLayout();
6556
6744
  return measure;
6557
6745
  }
6746
+ addStaffGroup(groupName, layoutElements, verticalPosition) {
6747
+ this.staffGroups.set(groupName, new StaffGroup(groupName, layoutElements, verticalPosition));
6748
+ }
6749
+ getStaffGroup(groupName) {
6750
+ return this.staffGroups.get(groupName);
6751
+ }
6558
6752
  getVoiceSymbols(voiceId) {
6559
6753
  let voiceSymbols = [];
6560
6754
  this.forEachMeasure((m) => voiceSymbols = voiceSymbols.concat(m.getVoiceSymbols(voiceId)));
@@ -6602,21 +6796,15 @@ var ObjDocument = class extends MusicObject {
6602
6796
  this.forEachMeasure((m) => m.createExtensions());
6603
6797
  this.allConnectiveProps.forEach((props) => props.removeConnectives());
6604
6798
  this.allConnectiveProps.forEach((props) => props.createConnectives());
6605
- let layoutGroups = this.layoutGroups.filter((layoutGroup) => !!layoutGroup);
6606
- layoutGroups.forEach((layoutGroup) => layoutGroup.clearPositionAndLayout(renderer));
6799
+ this.rows.forEach((row) => row.resetLayoutGroups(renderer));
6607
6800
  this.rows.forEach((row) => row.layout(renderer));
6608
6801
  let rowWidth = Math.max(
6609
6802
  DocumentSettings.DocumentMinWidth * unitSize,
6610
6803
  ...this.rows.map((row) => 1.4 * row.getMinWidth())
6611
6804
  );
6612
6805
  this.rows.forEach((row) => row.layoutWidth(renderer, rowWidth));
6806
+ this.rows.forEach((row) => row.layoutLayoutGroups(renderer));
6613
6807
  this.rows.forEach((row) => row.layoutPositionLines(renderer));
6614
- layoutGroups.forEach((layoutGroup) => {
6615
- this.rows.forEach((row) => {
6616
- row.layoutLayoutGroup(renderer, layoutGroup, 0 /* AboveStaff */);
6617
- row.layoutLayoutGroup(renderer, layoutGroup, 1 /* BelowStaff */);
6618
- });
6619
- });
6620
6808
  this.rows.forEach((row) => row.layoutPadding(renderer));
6621
6809
  this.rect = new DivRect();
6622
6810
  if (this.header) {
@@ -6841,21 +7029,64 @@ var DocumentBuilder = class {
6841
7029
  this.getMeasure().addRest(voiceId, restLength, options);
6842
7030
  return this;
6843
7031
  }
6844
- addFermata(fermata) {
6845
- assertArg(Utils11.Is.isEnumValueOrUndefined(fermata, Fermata), "fermata", fermata);
6846
- this.getMeasure().addFermata(fermata != null ? fermata : 0 /* AtNote */);
7032
+ addFermataInternal(staffTabOrGroup, fermata) {
7033
+ assertArg(Utils11.Is.isStringOrUndefined(staffTabOrGroup) || Utils11.Is.isIntegerGte(staffTabOrGroup, 0), "staffTabOrGroup", staffTabOrGroup);
7034
+ assertArg(Utils11.Is.isEnumValue(fermata, Fermata), "fermata", fermata);
7035
+ this.getMeasure().addFermata(staffTabOrGroup, fermata);
6847
7036
  return this;
6848
7037
  }
6849
- addNavigation(navigation, ...args) {
7038
+ addFermata(fermata = 0 /* AtNote */) {
7039
+ return this.addFermataInternal(void 0, fermata);
7040
+ }
7041
+ /** @param staffTabOrGroup - staff/tab index (0=top), staff/tab name, or staff group name. */
7042
+ addFermataTo(staffTabOrGroup, fermata = 0 /* AtNote */) {
7043
+ return this.addFermataInternal(staffTabOrGroup, fermata);
7044
+ }
7045
+ addNavigationInternal(staffTabOrGroup, navigation, ...args) {
7046
+ assertArg(Utils11.Is.isStringOrUndefined(staffTabOrGroup) || Utils11.Is.isIntegerGte(staffTabOrGroup, 0), "staffTabOrGroup", staffTabOrGroup);
6850
7047
  assertArg(Utils11.Is.isEnumValue(navigation, Navigation), "navigation", navigation);
6851
7048
  if (navigation === 9 /* EndRepeat */ && args.length > 0) {
6852
7049
  assertArg(Utils11.Is.isIntegerGte(args[0], 1), "playCount", args[0]);
6853
7050
  } else if (navigation === 10 /* Ending */ && args.length > 0) {
6854
7051
  assertArg(args.every((passage) => Utils11.Is.isIntegerGte(passage, 1)), "passages", args);
6855
7052
  }
6856
- this.getMeasure().addNavigation(navigation, ...args);
7053
+ this.getMeasure().addNavigation(staffTabOrGroup, navigation, ...args);
6857
7054
  return this;
6858
7055
  }
7056
+ addNavigation(navigation, ...args) {
7057
+ return this.addNavigationInternal(void 0, navigation, ...args);
7058
+ }
7059
+ addNavigationTo(staffTabOrGroup, navigation, ...args) {
7060
+ return this.addNavigationInternal(staffTabOrGroup, navigation, ...args);
7061
+ }
7062
+ addLabelInternal(staffTabOrGroup, label, text) {
7063
+ assertArg(Utils11.Is.isStringOrUndefined(staffTabOrGroup) || Utils11.Is.isIntegerGte(staffTabOrGroup, 0), "staffTabOrGroup", staffTabOrGroup);
7064
+ assertArg(Utils11.Is.isEnumValue(label, Label), "label", label);
7065
+ assertArg(Utils11.Is.isString(text), "text", text);
7066
+ this.getMeasure().addLabel(staffTabOrGroup, label, text);
7067
+ return this;
7068
+ }
7069
+ addLabel(label, text) {
7070
+ return this.addLabelInternal(void 0, label, text);
7071
+ }
7072
+ /** @param staffTabOrGroup - staff/tab index (0=top), staff/tab name, or staff group name. */
7073
+ addLabelTo(staffTabOrGroup, label, text) {
7074
+ return this.addLabelInternal(staffTabOrGroup, label, text);
7075
+ }
7076
+ addAnnotationInternal(staffTabOrGroup, annotation, text) {
7077
+ assertArg(Utils11.Is.isStringOrUndefined(staffTabOrGroup) || Utils11.Is.isIntegerGte(staffTabOrGroup, 0), "staffTabOrGroup", staffTabOrGroup);
7078
+ assertArg(Utils11.Is.isEnumValue(annotation, Annotation), "annotation", annotation);
7079
+ assertArg(Utils11.Is.isString(text), "text", text);
7080
+ this.getMeasure().addAnnotation(staffTabOrGroup, annotation, text);
7081
+ return this;
7082
+ }
7083
+ addAnnotation(annotation, text) {
7084
+ return this.addAnnotationInternal(void 0, annotation, text);
7085
+ }
7086
+ /** @param staffTabOrGroup - staff/tab index (0=top), staff/tab name, or staff group name. */
7087
+ addAnnotationTo(staffTabOrGroup, annotation, text) {
7088
+ return this.addAnnotationInternal(staffTabOrGroup, annotation, text);
7089
+ }
6859
7090
  addConnective(connective, ...args) {
6860
7091
  assertArg(Utils11.Is.isEnumValue(connective, Connective), "connective", connective);
6861
7092
  if (connective === 0 /* Tie */) {
@@ -6877,24 +7108,30 @@ var DocumentBuilder = class {
6877
7108
  }
6878
7109
  return this;
6879
7110
  }
6880
- addLabel(label, text) {
6881
- assertArg(Utils11.Is.isEnumValue(label, Label), "label", label);
6882
- assertArg(Utils11.Is.isString(text), "text", text);
6883
- this.getMeasure().addLabel(label, text);
6884
- return this;
6885
- }
6886
- addAnnotation(annotation, text) {
6887
- assertArg(Utils11.Is.isEnumValue(annotation, Annotation), "annotation", annotation);
6888
- assertArg(Utils11.Is.isString(text), "text", text);
6889
- this.getMeasure().addAnnotation(annotation, text);
6890
- return this;
6891
- }
6892
7111
  addExtension(extensionLength, extensionVisible) {
6893
7112
  assertArg(Utils11.Is.isIntegerGte(extensionLength, 0) || extensionLength === Infinity || Utils11.Is.isEnumValue(extensionLength, NoteLength7), "extendionLength", extensionLength);
6894
7113
  assertArg(Utils11.Is.isBooleanOrUndefined(extensionVisible), "extensionVisible", extensionVisible);
6895
7114
  this.getMeasure().addExtension(extensionLength, extensionVisible != null ? extensionVisible : true);
6896
7115
  return this;
6897
7116
  }
7117
+ /**
7118
+ *
7119
+ * @param groupName - Name of staff group.
7120
+ * @param staffsTabsAndGroups - staff/tab index (0=top), staff/tab name, or staff group name. Single value or array.
7121
+ * @param verticalPosition - Vertical position, are elements added above, below or both.
7122
+ * @returns
7123
+ */
7124
+ addStaffGroup(groupName, staffsTabsAndGroups, verticalPosition = 3 /* Auto */) {
7125
+ assertArg(Utils11.Is.isString(groupName) && groupName.length > 0, "groupName", groupName);
7126
+ assertArg(
7127
+ Utils11.Is.isString(staffsTabsAndGroups) && staffsTabsAndGroups.length > 0 || Utils11.Is.isIntegerGte(staffsTabsAndGroups, 0) || Utils11.Is.isArray(staffsTabsAndGroups) && staffsTabsAndGroups.every((line) => Utils11.Is.isString(line) && line.length > 0 || Utils11.Is.isIntegerGte(line, 0)),
7128
+ "staffsTabsAndGroups",
7129
+ staffsTabsAndGroups
7130
+ );
7131
+ assertArg(Utils11.Is.isEnumValue(verticalPosition, VerticalPosition), "verticalPosition", verticalPosition);
7132
+ this.doc.addStaffGroup(groupName, staffsTabsAndGroups, verticalPosition);
7133
+ return this;
7134
+ }
6898
7135
  endSong() {
6899
7136
  this.getMeasure().endSong();
6900
7137
  return this;
@@ -7665,6 +7902,7 @@ export {
7665
7902
  StaffPreset,
7666
7903
  Stem,
7667
7904
  TieType,
7905
+ VerticalPosition,
7668
7906
  getStringNumbers,
7669
7907
  getVoiceIds
7670
7908
  };