@tspro/web-music-score 3.0.0 → 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,4 +1,4 @@
1
- /* WebMusicScore v3.0.0 | (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
  "use strict";
3
3
  var __create = Object.create;
4
4
  var __defProp = Object.defineProperty;
@@ -81,6 +81,7 @@ __export(score_exports, {
81
81
  StaffPreset: () => StaffPreset,
82
82
  Stem: () => Stem,
83
83
  TieType: () => TieType,
84
+ VerticalPosition: () => VerticalPosition,
84
85
  getStringNumbers: () => getStringNumbers,
85
86
  getVoiceIds: () => getVoiceIds
86
87
  });
@@ -413,6 +414,13 @@ var Connective = /* @__PURE__ */ ((Connective3) => {
413
414
  Connective3[Connective3["Slide"] = 2] = "Slide";
414
415
  return Connective3;
415
416
  })(Connective || {});
417
+ var VerticalPosition = /* @__PURE__ */ ((VerticalPosition4) => {
418
+ VerticalPosition4[VerticalPosition4["Above"] = 0] = "Above";
419
+ VerticalPosition4[VerticalPosition4["Below"] = 1] = "Below";
420
+ VerticalPosition4[VerticalPosition4["Both"] = 2] = "Both";
421
+ VerticalPosition4[VerticalPosition4["Auto"] = 3] = "Auto";
422
+ return VerticalPosition4;
423
+ })(VerticalPosition || {});
416
424
  var PlayState = /* @__PURE__ */ ((PlayState2) => {
417
425
  PlayState2[PlayState2["Playing"] = 0] = "Playing";
418
426
  PlayState2[PlayState2["Paused"] = 1] = "Paused";
@@ -527,7 +535,7 @@ var MusicObject = class {
527
535
  var import_theory12 = require("@tspro/web-music-score/theory");
528
536
 
529
537
  // src/score/engine/obj-staff-and-tab.ts
530
- var import_theory = require("@tspro/web-music-score/theory");
538
+ var import_theory11 = require("@tspro/web-music-score/theory");
531
539
 
532
540
  // src/score/engine/renderer.ts
533
541
  var import_ts_utils_lib2 = require("@tspro/ts-utils-lib");
@@ -945,260 +953,16 @@ var Renderer = class {
945
953
  };
946
954
 
947
955
  // src/score/engine/obj-staff-and-tab.ts
948
- var import_core3 = require("@tspro/web-music-score/core");
949
- var import_ts_utils_lib3 = require("@tspro/ts-utils-lib");
950
- var ObjStaff = class extends MusicObject {
951
- constructor(row, staffConfig) {
952
- super(row);
953
- this.row = row;
954
- this.staffConfig = staffConfig;
955
- __publicField(this, "clefImageAsset");
956
- __publicField(this, "clefLineDiatonicId");
957
- __publicField(this, "topLineDiatonicId");
958
- __publicField(this, "middleLineDiatonicId");
959
- __publicField(this, "bottomLineDiatonicId");
960
- __publicField(this, "minDiatonicId");
961
- __publicField(this, "maxDiatonicId");
962
- __publicField(this, "joinedGrandStaff");
963
- __publicField(this, "topLineY", 0);
964
- __publicField(this, "bottomLineY", 0);
965
- __publicField(this, "objects", []);
966
- __publicField(this, "mi");
967
- const getDiatonicId = (noteName, isOctaveDown) => import_theory.Note.getNote(noteName).diatonicId - (isOctaveDown ? 7 : 0);
968
- if (staffConfig.clef === "G" /* G */) {
969
- this.clefImageAsset = 0 /* TrebleClefPng */;
970
- this.clefLineDiatonicId = getDiatonicId("G4", staffConfig.isOctaveDown === true);
971
- this.middleLineDiatonicId = this.clefLineDiatonicId + 2;
972
- } else {
973
- this.clefImageAsset = 1 /* BassClefPng */;
974
- this.clefLineDiatonicId = getDiatonicId("F3", staffConfig.isOctaveDown === true);
975
- this.middleLineDiatonicId = this.clefLineDiatonicId - 2;
976
- }
977
- this.topLineDiatonicId = this.middleLineDiatonicId + 4;
978
- this.bottomLineDiatonicId = this.middleLineDiatonicId - 4;
979
- this.minDiatonicId = staffConfig.minNote !== void 0 ? Math.min(getDiatonicId(staffConfig.minNote, false), this.bottomLineDiatonicId) : void 0;
980
- this.maxDiatonicId = staffConfig.maxNote !== void 0 ? Math.max(getDiatonicId(staffConfig.maxNote, false), this.topLineDiatonicId) : void 0;
981
- this.mi = new MStaff(this);
982
- }
983
- getMusicInterface() {
984
- return this.mi;
985
- }
986
- get isOctaveDown() {
987
- return this.staffConfig.isOctaveDown === true;
988
- }
989
- getTopLineY() {
990
- return this.topLineY;
991
- }
992
- getMiddleLineY() {
993
- return (this.topLineY + this.bottomLineY) / 2;
994
- }
995
- getBottomLineY() {
996
- return this.bottomLineY;
997
- }
998
- joinGrandStaff(staff) {
999
- if (staff !== this) {
1000
- this.joinedGrandStaff = staff;
1001
- }
1002
- }
1003
- getLineSpacing() {
1004
- return (this.bottomLineY - this.topLineY) / 4;
1005
- }
1006
- getDiatonicSpacing() {
1007
- return this.getLineSpacing() / 2;
1008
- }
1009
- containsDiatonicId(diatonicId) {
1010
- import_theory.Note.validateDiatonicId(diatonicId);
1011
- return (this.minDiatonicId === void 0 || diatonicId >= this.minDiatonicId) && (this.maxDiatonicId === void 0 || diatonicId <= this.maxDiatonicId);
1012
- }
1013
- getDiatonicIdY(diatonicId) {
1014
- if (this.containsDiatonicId(diatonicId)) {
1015
- return this.bottomLineY + (this.bottomLineDiatonicId - diatonicId) * this.getDiatonicSpacing();
1016
- } else if (this.joinedGrandStaff && this.joinedGrandStaff.containsDiatonicId(diatonicId)) {
1017
- return this.joinedGrandStaff.getDiatonicIdY(diatonicId);
1018
- } else {
1019
- throw new import_core3.MusicError(import_core3.MusicErrorType.Score, "Staff does not contain diatonicId " + diatonicId);
1020
- }
1021
- }
1022
- getActualStaff(diatonicId) {
1023
- if (this.containsDiatonicId(diatonicId)) {
1024
- return this;
1025
- } else if (this.joinedGrandStaff && this.joinedGrandStaff.containsDiatonicId(diatonicId)) {
1026
- return this.joinedGrandStaff;
1027
- } else {
1028
- throw new import_core3.MusicError(import_core3.MusicErrorType.Score, "Staff does not contain diatonicId " + diatonicId);
1029
- }
1030
- }
1031
- getDiatonicIdAt(y) {
1032
- let diatonicId = Math.round(this.bottomLineDiatonicId - (y - this.bottomLineY) / this.getDiatonicSpacing());
1033
- return this.containsDiatonicId(diatonicId) ? diatonicId : void 0;
1034
- }
1035
- isLine(diatonicId) {
1036
- return diatonicId % 2 === this.middleLineDiatonicId % 2;
1037
- }
1038
- isSpace(diatonicId) {
1039
- return diatonicId % 2 !== this.middleLineDiatonicId % 2;
1040
- }
1041
- containsVoiceId(voiceId) {
1042
- return !this.staffConfig.voiceIds || this.staffConfig.voiceIds.includes(voiceId);
1043
- }
1044
- isGrand() {
1045
- return this.staffConfig.isGrand === true;
1046
- }
1047
- calcTop() {
1048
- let top = this.topLineY;
1049
- this.objects.forEach((o) => top = Math.min(top, o.getRect().top));
1050
- if (this.maxDiatonicId !== void 0) {
1051
- let y = this.getDiatonicIdY(this.maxDiatonicId);
1052
- let y2 = this.getDiatonicIdY(this.maxDiatonicId - 1);
1053
- top = Math.min(top, y - Math.abs(y2 - y) + 1);
1054
- }
1055
- return top;
1056
- }
1057
- calcBottom() {
1058
- let bottom = this.bottomLineY;
1059
- this.objects.forEach((o) => bottom = Math.max(bottom, o.getRect().bottom));
1060
- if (this.minDiatonicId !== void 0) {
1061
- let y = this.getDiatonicIdY(this.minDiatonicId);
1062
- let y2 = this.getDiatonicIdY(this.minDiatonicId + 1);
1063
- bottom = Math.max(bottom, y + Math.abs(y2 - y) - 1);
1064
- }
1065
- return bottom;
1066
- }
1067
- addObject(o) {
1068
- this.objects.push(o);
1069
- }
1070
- removeObjects() {
1071
- this.objects.length = 0;
1072
- }
1073
- pick(x, y) {
1074
- return [this];
1075
- }
1076
- layoutHeight(renderer) {
1077
- let { unitSize } = renderer;
1078
- let h = unitSize * DocumentSettings.StaffHeight;
1079
- this.topLineY = -h / 2;
1080
- this.bottomLineY = h / 2;
1081
- this.rect = new DivRect(0, 0, this.topLineY, this.bottomLineY);
1082
- }
1083
- layoutWidth(renderer) {
1084
- this.rect.left = this.row.getRect().left;
1085
- this.rect.right = this.row.getRect().right;
1086
- }
1087
- offset(dx, dy) {
1088
- this.topLineY += dy;
1089
- this.bottomLineY += dy;
1090
- this.objects.forEach((o) => {
1091
- if (o.offsetInPlace) {
1092
- o.offsetInPlace(0, dy);
1093
- } else if (o.offset) {
1094
- o.offset(0, dy);
1095
- }
1096
- });
1097
- this.rect.offsetInPlace(dx, dy);
1098
- }
1099
- draw(renderer) {
1100
- }
1101
- };
1102
- var ObjTab = class extends MusicObject {
1103
- constructor(row, tabConfig) {
1104
- super(row);
1105
- this.row = row;
1106
- this.tabConfig = tabConfig;
1107
- __publicField(this, "top", 0);
1108
- __publicField(this, "bottom", 0);
1109
- __publicField(this, "objects", []);
1110
- __publicField(this, "tuningName");
1111
- __publicField(this, "tuningStrings");
1112
- __publicField(this, "mi");
1113
- if (import_ts_utils_lib3.Utils.Is.isArray(tabConfig.tuning)) {
1114
- this.tuningName = void 0;
1115
- this.tuningStrings = tabConfig.tuning.map((noteName) => import_theory.Note.getNote(noteName)).reverse();
1116
- } else if (typeof tabConfig.tuning === "string") {
1117
- this.tuningName = (0, import_theory.validateTuningName)(tabConfig.tuning);
1118
- this.tuningStrings = (0, import_theory.getTuningStrings)(this.tuningName);
1119
- } else {
1120
- this.tuningName = "Standard";
1121
- this.tuningStrings = (0, import_theory.getTuningStrings)(this.tuningName);
1122
- }
1123
- this.mi = new MTab(this);
1124
- }
1125
- getMusicInterface() {
1126
- return this.mi;
1127
- }
1128
- getTuningName() {
1129
- return this.tuningName;
1130
- }
1131
- getTuningStrings() {
1132
- return this.tuningStrings;
1133
- }
1134
- /** Return Y coordinate of string. */
1135
- getStringY(stringId) {
1136
- return this.top + (this.bottom - this.top) / 6 * (stringId + 0.5);
1137
- }
1138
- getTopStringY() {
1139
- return this.getStringY(0);
1140
- }
1141
- getBottomStringY() {
1142
- return this.getStringY(5);
1143
- }
1144
- getTop() {
1145
- return this.top;
1146
- }
1147
- getBottom() {
1148
- return this.bottom;
1149
- }
1150
- containsVoiceId(voiceId) {
1151
- return !this.tabConfig.voiceIds || this.tabConfig.voiceIds.includes(voiceId);
1152
- }
1153
- calcTop() {
1154
- return this.top;
1155
- }
1156
- calcBottom() {
1157
- return this.bottom;
1158
- }
1159
- addObject(o) {
1160
- this.objects.push(o);
1161
- }
1162
- removeObjects() {
1163
- this.objects.length = 0;
1164
- }
1165
- pick(x, y) {
1166
- return [this];
1167
- }
1168
- layoutHeight(renderer) {
1169
- let { unitSize } = renderer;
1170
- let h = unitSize * DocumentSettings.TabHeight;
1171
- this.top = -h / 2;
1172
- this.bottom = h / 2;
1173
- this.rect = new DivRect(0, 0, this.top, this.bottom);
1174
- }
1175
- layoutWidth(renderer) {
1176
- this.rect.left = this.row.getRect().left;
1177
- this.rect.right = this.row.getRect().right;
1178
- }
1179
- offset(dx, dy) {
1180
- this.top += dy;
1181
- this.bottom += dy;
1182
- this.objects.forEach((o) => {
1183
- if (o.offsetInPlace) {
1184
- o.offsetInPlace(0, dy);
1185
- } else if (o.offset) {
1186
- o.offset(0, dy);
1187
- }
1188
- });
1189
- this.rect.offsetInPlace(dx, dy);
1190
- }
1191
- draw(renderer) {
1192
- }
1193
- };
956
+ var import_core15 = require("@tspro/web-music-score/core");
957
+ var import_ts_utils_lib9 = require("@tspro/ts-utils-lib");
1194
958
 
1195
959
  // src/score/engine/obj-measure.ts
1196
- var import_ts_utils_lib9 = require("@tspro/ts-utils-lib");
960
+ var import_ts_utils_lib8 = require("@tspro/ts-utils-lib");
961
+ var import_theory9 = require("@tspro/web-music-score/theory");
1197
962
  var import_theory10 = require("@tspro/web-music-score/theory");
1198
- var import_theory11 = require("@tspro/web-music-score/theory");
1199
963
 
1200
964
  // src/score/engine/acc-state.ts
1201
- var import_theory2 = require("@tspro/web-music-score/theory");
965
+ var import_theory = require("@tspro/web-music-score/theory");
1202
966
  var AccidentalState = class {
1203
967
  constructor(measure) {
1204
968
  this.measure = measure;
@@ -1206,7 +970,7 @@ var AccidentalState = class {
1206
970
  }
1207
971
  getAccidentalFromKeySignature(diatonicId) {
1208
972
  let ks = this.measure.getKeySignature();
1209
- let accNote = ks.getOrderedAccidentalNotes().find((accNote2) => accNote2.diatonicClass === import_theory2.Note.getDiatonicClass(diatonicId));
973
+ let accNote = ks.getOrderedAccidentalNotes().find((accNote2) => accNote2.diatonicClass === import_theory.Note.getDiatonicClass(diatonicId));
1210
974
  return accNote ? accNote.accidental : void 0;
1211
975
  }
1212
976
  setAccidental(note) {
@@ -1220,7 +984,7 @@ var AccidentalState = class {
1220
984
  };
1221
985
 
1222
986
  // src/score/engine/obj-signature.ts
1223
- var import_theory3 = require("@tspro/web-music-score/theory");
987
+ var import_theory2 = require("@tspro/web-music-score/theory");
1224
988
 
1225
989
  // src/score/engine/obj-image.ts
1226
990
  var ObjImage = class extends MusicObject {
@@ -1268,7 +1032,7 @@ var ObjImage = class extends MusicObject {
1268
1032
  };
1269
1033
 
1270
1034
  // src/score/engine/obj-accidental.ts
1271
- var import_core4 = require("@tspro/web-music-score/core");
1035
+ var import_core3 = require("@tspro/web-music-score/core");
1272
1036
  var ObjAccidental = class extends MusicObject {
1273
1037
  constructor(parent, diatonicId, accidental, color = "black") {
1274
1038
  super(parent);
@@ -1303,7 +1067,7 @@ var ObjAccidental = class extends MusicObject {
1303
1067
  this.rect = DivRect.createSections(unitSize * 1, unitSize * 1, unitSize * 1, unitSize * 1);
1304
1068
  break;
1305
1069
  default:
1306
- throw new import_core4.MusicError(import_core4.MusicErrorType.Score, "Invalid accidental value: " + this.accidental);
1070
+ throw new import_core3.MusicError(import_core3.MusicErrorType.Score, "Invalid accidental value: " + this.accidental);
1307
1071
  }
1308
1072
  }
1309
1073
  offset(dx, dy) {
@@ -1516,7 +1280,7 @@ var ObjText = class extends MusicObject {
1516
1280
  };
1517
1281
 
1518
1282
  // src/score/engine/obj-signature.ts
1519
- var import_core5 = require("@tspro/web-music-score/core");
1283
+ var import_core4 = require("@tspro/web-music-score/core");
1520
1284
  var ObjSignature = class extends MusicObject {
1521
1285
  constructor(measure, staff) {
1522
1286
  super(measure);
@@ -1561,7 +1325,7 @@ var ObjSignature = class extends MusicObject {
1561
1325
  let newKeySignature = measure.getKeySignature();
1562
1326
  this.ksNeutralizeAccidentals = [];
1563
1327
  this.ksNewAccidentals = [];
1564
- if (prevKeySignature && !import_theory3.KeySignature.equals(newKeySignature, prevKeySignature)) {
1328
+ if (prevKeySignature && !import_theory2.KeySignature.equals(newKeySignature, prevKeySignature)) {
1565
1329
  prevKeySignature.getOrderedAccidentalNotes().forEach((accNote) => {
1566
1330
  this.ksNeutralizeAccidentals.push(new ObjAccidental(this, this.getAccidentalDiatonicId(accNote), 0));
1567
1331
  });
@@ -1587,7 +1351,7 @@ var ObjSignature = class extends MusicObject {
1587
1351
  }
1588
1352
  updateTempo(showTempo) {
1589
1353
  if (showTempo) {
1590
- let tempoStr = (0, import_theory3.getTempoString)(this.measure.getTempo());
1354
+ let tempoStr = (0, import_theory2.getTempoString)(this.measure.getTempo());
1591
1355
  this.tempoText = new ObjText(this, tempoStr, 0.5, 1);
1592
1356
  } else {
1593
1357
  this.tempoText = void 0;
@@ -1610,9 +1374,9 @@ var ObjSignature = class extends MusicObject {
1610
1374
  }
1611
1375
  }
1612
1376
  if (bottomAccidentalDiatonicId !== void 0) {
1613
- return import_theory3.Note.findNextDiatonicIdAbove(accNote.diatonicId, bottomAccidentalDiatonicId, false);
1377
+ return import_theory2.Note.findNextDiatonicIdAbove(accNote.diatonicId, bottomAccidentalDiatonicId, false);
1614
1378
  } else {
1615
- throw new import_core5.MusicError(import_core5.MusicErrorType.Score, "Cannot get accidental diatonicId because note has no accidental.");
1379
+ throw new import_core4.MusicError(import_core4.MusicErrorType.Score, "Cannot get accidental diatonicId because note has no accidental.");
1616
1380
  }
1617
1381
  }
1618
1382
  pick(x, y) {
@@ -1782,22 +1546,24 @@ var ObjSignature = class extends MusicObject {
1782
1546
  };
1783
1547
 
1784
1548
  // src/score/engine/player.ts
1785
- var import_ts_utils_lib6 = require("@tspro/ts-utils-lib");
1786
- var import_theory8 = require("@tspro/web-music-score/theory");
1549
+ var import_ts_utils_lib5 = require("@tspro/ts-utils-lib");
1550
+ var import_theory7 = require("@tspro/web-music-score/theory");
1787
1551
  var Audio = __toESM(require("@tspro/web-music-score/audio"));
1788
1552
 
1789
1553
  // src/score/engine/obj-rhythm-column.ts
1790
- var import_theory7 = require("@tspro/web-music-score/theory");
1554
+ var import_theory6 = require("@tspro/web-music-score/theory");
1791
1555
 
1792
1556
  // src/score/engine/obj-arpeggio.ts
1793
- var _ObjArpeggio = class _ObjArpeggio extends MusicObject {
1794
- constructor(col, arpeggioDir) {
1557
+ var ObjArpeggio = class extends MusicObject {
1558
+ constructor(col, line, arpeggioDir) {
1795
1559
  super(col);
1796
1560
  this.col = col;
1561
+ this.line = line;
1797
1562
  this.arpeggioDir = arpeggioDir;
1798
1563
  __publicField(this, "topArrowHeight", 0);
1799
1564
  __publicField(this, "bottomArrowHeight", 0);
1800
1565
  __publicField(this, "cycleHeight", 0);
1566
+ __publicField(this, "numCycles", 0);
1801
1567
  __publicField(this, "color", "black");
1802
1568
  __publicField(this, "mi");
1803
1569
  this.mi = new MArpeggio(this);
@@ -1812,10 +1578,13 @@ var _ObjArpeggio = class _ObjArpeggio extends MusicObject {
1812
1578
  let { unitSize } = renderer;
1813
1579
  this.topArrowHeight = this.arpeggioDir === 0 /* Up */ ? unitSize : 0;
1814
1580
  this.bottomArrowHeight = this.arpeggioDir === 1 /* Down */ ? unitSize : 0;
1581
+ let top = this.line.getTopLineY();
1582
+ let bottom = this.line.getBottomLineY();
1815
1583
  this.cycleHeight = unitSize * 2;
1584
+ this.numCycles = Math.ceil((bottom - top) / this.cycleHeight) + 2;
1816
1585
  let width = unitSize * 2;
1817
- let height = _ObjArpeggio.NumCycles * this.cycleHeight + this.topArrowHeight + this.bottomArrowHeight;
1818
- this.rect = new DivRect(-width / 2, width / 2, -height / 2, height / 2);
1586
+ let height = this.numCycles * this.cycleHeight;
1587
+ this.rect = new DivRect(-width / 2, width / 2, -height / 2 - this.topArrowHeight, height / 2 + this.bottomArrowHeight);
1819
1588
  }
1820
1589
  offset(dx, dy) {
1821
1590
  this.rect.offsetInPlace(dx, dy);
@@ -1825,14 +1594,13 @@ var _ObjArpeggio = class _ObjArpeggio extends MusicObject {
1825
1594
  if (!ctx) {
1826
1595
  return;
1827
1596
  }
1828
- let { lineWidth, unitSize } = renderer;
1597
+ let { lineWidth } = renderer;
1829
1598
  let { rect, topArrowHeight, bottomArrowHeight } = this;
1830
1599
  renderer.drawDebugRect(this.rect);
1831
1600
  ctx.strokeStyle = ctx.fillStyle = this.color;
1832
1601
  ctx.lineWidth = lineWidth * 2;
1833
1602
  ctx.beginPath();
1834
- for (let i = 0; i < _ObjArpeggio.NumCycles; i++) {
1835
- let y = rect.top + topArrowHeight + i * this.cycleHeight;
1603
+ for (let i = 0, y = rect.top + topArrowHeight; i < this.numCycles; i++, y += this.cycleHeight) {
1836
1604
  ctx.moveTo(rect.centerX, y);
1837
1605
  ctx.quadraticCurveTo(rect.left, y + this.cycleHeight / 4, rect.centerX, y + this.cycleHeight / 2);
1838
1606
  ctx.quadraticCurveTo(rect.right, y + this.cycleHeight * 3 / 4, rect.centerX, y + this.cycleHeight);
@@ -1841,31 +1609,29 @@ var _ObjArpeggio = class _ObjArpeggio extends MusicObject {
1841
1609
  if (topArrowHeight > 0) {
1842
1610
  ctx.beginPath();
1843
1611
  ctx.moveTo(rect.centerX, rect.top);
1844
- ctx.lineTo(rect.right, rect.top + unitSize);
1845
- ctx.lineTo(rect.left, rect.top + unitSize);
1612
+ ctx.lineTo(rect.right, rect.top + topArrowHeight);
1613
+ ctx.lineTo(rect.left, rect.top + topArrowHeight);
1846
1614
  ctx.fill();
1847
1615
  }
1848
1616
  if (bottomArrowHeight > 0) {
1849
1617
  ctx.beginPath();
1850
1618
  ctx.moveTo(rect.centerX, rect.bottom);
1851
- ctx.lineTo(rect.left, rect.bottom - unitSize);
1852
- ctx.lineTo(rect.right, rect.bottom - unitSize);
1619
+ ctx.lineTo(rect.left, rect.bottom - bottomArrowHeight);
1620
+ ctx.lineTo(rect.right, rect.bottom - bottomArrowHeight);
1853
1621
  ctx.fill();
1854
1622
  }
1855
1623
  }
1856
1624
  };
1857
- __publicField(_ObjArpeggio, "NumCycles", 5);
1858
- var ObjArpeggio = _ObjArpeggio;
1859
1625
 
1860
1626
  // src/score/engine/obj-rest.ts
1861
- var import_theory4 = require("@tspro/web-music-score/theory");
1862
- var import_core6 = require("@tspro/web-music-score/core");
1627
+ var import_theory3 = require("@tspro/web-music-score/theory");
1628
+ var import_core5 = require("@tspro/web-music-score/core");
1863
1629
  function getDiatonicIdFromStaffPos(staffPos) {
1864
1630
  if (typeof staffPos === "number") {
1865
- return import_theory4.Note.getChromaticNote(staffPos).diatonicId;
1631
+ return import_theory3.Note.getChromaticNote(staffPos).diatonicId;
1866
1632
  } else if (typeof staffPos === "string") {
1867
- return import_theory4.Note.getNote(staffPos).diatonicId;
1868
- } else if (staffPos instanceof import_theory4.Note) {
1633
+ return import_theory3.Note.getNote(staffPos).diatonicId;
1634
+ } else if (staffPos instanceof import_theory3.Note) {
1869
1635
  return staffPos.diatonicId;
1870
1636
  } else {
1871
1637
  return void 0;
@@ -1921,7 +1687,7 @@ var ObjRest = class extends MusicObject {
1921
1687
  let hasStaff = this.row.hasStaff;
1922
1688
  let staff2 = this.row.getStaff(diatonicId);
1923
1689
  if (hasStaff && !staff2) {
1924
- throw new import_core6.MusicError(import_core6.MusicErrorType.Score, "Rest staffPos is out of staff boundaries!");
1690
+ throw new import_core5.MusicError(import_core5.MusicErrorType.Score, "Rest staffPos is out of staff boundaries!");
1925
1691
  }
1926
1692
  }
1927
1693
  this.ownDiatonicId = this.measure.updateOwnDiatonicId(voiceId, diatonicId);
@@ -1935,7 +1701,7 @@ var ObjRest = class extends MusicObject {
1935
1701
  }
1936
1702
  this.color = (_a = options == null ? void 0 : options.color) != null ? _a : "black";
1937
1703
  this.hide = (_b = options == null ? void 0 : options.hide) != null ? _b : false;
1938
- this.rhythmProps = new import_theory4.RhythmProps(noteLength, options == null ? void 0 : options.dotted, options == null ? void 0 : options.triplet);
1704
+ this.rhythmProps = new import_theory3.RhythmProps(noteLength, options == null ? void 0 : options.dotted, options == null ? void 0 : options.triplet);
1939
1705
  this.mi = new MRest(this);
1940
1706
  }
1941
1707
  getMusicInterface() {
@@ -1962,6 +1728,15 @@ var ObjRest = class extends MusicObject {
1962
1728
  get triplet() {
1963
1729
  return this.rhythmProps.triplet;
1964
1730
  }
1731
+ getStaticObjects(line) {
1732
+ let staticObjects = [];
1733
+ this.staffObjects.forEach((obj) => {
1734
+ if (obj.staff === line) {
1735
+ staticObjects.push(obj);
1736
+ }
1737
+ });
1738
+ return staticObjects;
1739
+ }
1965
1740
  pick(x, y) {
1966
1741
  if (!this.getRect().contains(x, y)) {
1967
1742
  return [];
@@ -2000,22 +1775,22 @@ var ObjRest = class extends MusicObject {
2000
1775
  }
2001
1776
  getRestDotVerticalDisplacement(noteLength) {
2002
1777
  switch (noteLength) {
2003
- case import_theory4.NoteLength.Whole:
1778
+ case import_theory3.NoteLength.Whole:
2004
1779
  return 1;
2005
- case import_theory4.NoteLength.Half:
1780
+ case import_theory3.NoteLength.Half:
2006
1781
  return -1;
2007
- case import_theory4.NoteLength.Quarter:
1782
+ case import_theory3.NoteLength.Quarter:
2008
1783
  return -1;
2009
- case import_theory4.NoteLength.Eighth:
1784
+ case import_theory3.NoteLength.Eighth:
2010
1785
  return -1;
2011
- case import_theory4.NoteLength.Sixteenth:
1786
+ case import_theory3.NoteLength.Sixteenth:
2012
1787
  return -1;
2013
- case import_theory4.NoteLength.ThirtySecond:
1788
+ case import_theory3.NoteLength.ThirtySecond:
2014
1789
  return -3;
2015
- case import_theory4.NoteLength.SixtyFourth:
1790
+ case import_theory3.NoteLength.SixtyFourth:
2016
1791
  return -3;
2017
1792
  default:
2018
- throw new import_core6.MusicError(import_core6.MusicErrorType.Score, "Cannot get rest dot vertical displacement because note length is invalid.");
1793
+ throw new import_core5.MusicError(import_core5.MusicErrorType.Score, "Cannot get rest dot vertical displacement because note length is invalid.");
2019
1794
  }
2020
1795
  }
2021
1796
  updateAccidentalState(accState) {
@@ -2033,17 +1808,17 @@ var ObjRest = class extends MusicObject {
2033
1808
  let rightw = 0;
2034
1809
  let toph = 0;
2035
1810
  let bottomh = 0;
2036
- if (noteLength === import_theory4.NoteLength.Whole) {
1811
+ if (noteLength === import_theory3.NoteLength.Whole) {
2037
1812
  leftw = unitSize;
2038
1813
  rightw = unitSize;
2039
1814
  toph = 0;
2040
1815
  bottomh = unitSize;
2041
- } else if (noteLength === import_theory4.NoteLength.Half) {
1816
+ } else if (noteLength === import_theory3.NoteLength.Half) {
2042
1817
  leftw = unitSize;
2043
1818
  rightw = unitSize;
2044
1819
  toph = unitSize;
2045
1820
  bottomh = 0;
2046
- } else if (noteLength === import_theory4.NoteLength.Quarter) {
1821
+ } else if (noteLength === import_theory3.NoteLength.Quarter) {
2047
1822
  leftw = unitSize * 1;
2048
1823
  rightw = unitSize * 1;
2049
1824
  toph = unitSize * 3.2;
@@ -2102,11 +1877,11 @@ var ObjRest = class extends MusicObject {
2102
1877
  let { dotRect, restRect } = obj;
2103
1878
  let x = restRect.centerX;
2104
1879
  let y = restRect.centerY;
2105
- if (noteLength === import_theory4.NoteLength.Whole) {
1880
+ if (noteLength === import_theory3.NoteLength.Whole) {
2106
1881
  ctx.fillRect(x - unitSize, y, unitSize * 2, unitSize);
2107
- } else if (noteLength === import_theory4.NoteLength.Half) {
1882
+ } else if (noteLength === import_theory3.NoteLength.Half) {
2108
1883
  ctx.fillRect(x - unitSize, y - unitSize, unitSize * 2, unitSize);
2109
- } else if (noteLength === import_theory4.NoteLength.Quarter) {
1884
+ } else if (noteLength === import_theory3.NoteLength.Quarter) {
2110
1885
  ctx.beginPath();
2111
1886
  ctx.moveTo(x - unitSize * 0.6, y - unitSize * 3.2);
2112
1887
  ctx.lineTo(x + unitSize * 0.7, y - unitSize * 1.5);
@@ -2172,13 +1947,13 @@ var ObjRest = class extends MusicObject {
2172
1947
  };
2173
1948
 
2174
1949
  // src/score/engine/obj-note-group.ts
2175
- var import_ts_utils_lib5 = require("@tspro/ts-utils-lib");
2176
- var import_theory6 = require("@tspro/web-music-score/theory");
2177
-
2178
- // src/score/engine/obj-beam-group.ts
2179
1950
  var import_ts_utils_lib4 = require("@tspro/ts-utils-lib");
2180
1951
  var import_theory5 = require("@tspro/web-music-score/theory");
2181
- var import_core7 = require("@tspro/web-music-score/core");
1952
+
1953
+ // src/score/engine/obj-beam-group.ts
1954
+ var import_ts_utils_lib3 = require("@tspro/ts-utils-lib");
1955
+ var import_theory4 = require("@tspro/web-music-score/theory");
1956
+ var import_core6 = require("@tspro/web-music-score/core");
2182
1957
  var adjustBeamAngle = (dx, dy) => {
2183
1958
  let T = DocumentSettings.BeamAngleFactor;
2184
1959
  if (!Number.isFinite(T) || T === 0) {
@@ -2255,19 +2030,19 @@ var ObjBeamGroup = class _ObjBeamGroup extends MusicObject {
2255
2030
  __publicField(this, "staffObjects", []);
2256
2031
  this.mi = new MBeamGroup(this);
2257
2032
  if (!symbols.every((s) => s.measure === symbols[0].measure)) {
2258
- throw new import_core7.MusicError(import_core7.MusicErrorType.Score, "All beam group symbols are not in same measure.");
2033
+ throw new import_core6.MusicError(import_core6.MusicErrorType.Score, "All beam group symbols are not in same measure.");
2259
2034
  } else if (symbols.length < 2) {
2260
- throw new import_core7.MusicError(import_core7.MusicErrorType.Score, "Beam group need minimum 2 symbols, but " + symbols.length + " given.");
2035
+ throw new import_core6.MusicError(import_core6.MusicErrorType.Score, "Beam group need minimum 2 symbols, but " + symbols.length + " given.");
2261
2036
  }
2262
2037
  if (triplet) {
2263
2038
  if (!symbols.every((s) => s.triplet)) {
2264
- throw new import_core7.MusicError(import_core7.MusicErrorType.Score, "Not every symbol's triplet property is true.");
2039
+ throw new import_core6.MusicError(import_core6.MusicErrorType.Score, "Not every symbol's triplet property is true.");
2265
2040
  }
2266
2041
  let isGroup = symbols.length < 3 || symbols.some((s) => !(s instanceof ObjNoteGroup)) || symbols.some((s) => s.rhythmProps.flagCount !== symbols[0].rhythmProps.flagCount);
2267
2042
  if (symbols.length === 3 && symbols[0] instanceof ObjNoteGroup && symbols[symbols.length - 1] instanceof ObjNoteGroup && symbols[0].rhythmProps.flagCount === symbols[symbols.length - 1].rhythmProps.flagCount) {
2268
2043
  isGroup = false;
2269
2044
  }
2270
- if (symbols.some((s) => s.rhythmProps.noteLength >= import_theory5.NoteLength.Quarter)) {
2045
+ if (symbols.some((s) => s.rhythmProps.noteLength >= import_theory4.NoteLength.Quarter)) {
2271
2046
  isGroup = true;
2272
2047
  }
2273
2048
  this.type = isGroup ? 2 /* TripletGroup */ : 1 /* TripletBeam */;
@@ -2279,7 +2054,7 @@ var ObjBeamGroup = class _ObjBeamGroup extends MusicObject {
2279
2054
  symbols.forEach((s) => s.setBeamGroup(this));
2280
2055
  symbols[0].measure.addBeamGroup(this);
2281
2056
  } else {
2282
- throw new import_core7.MusicError(import_core7.MusicErrorType.Score, "Cannot add beam group because some symbol already has one.");
2057
+ throw new import_core6.MusicError(import_core6.MusicErrorType.Score, "Cannot add beam group because some symbol already has one.");
2283
2058
  }
2284
2059
  }
2285
2060
  static createBeam(noteGroups) {
@@ -2291,10 +2066,10 @@ var ObjBeamGroup = class _ObjBeamGroup extends MusicObject {
2291
2066
  if (!symbols.every((s) => s.triplet)) {
2292
2067
  return false;
2293
2068
  }
2294
- let MaxTripletNoteLenght = import_theory5.NoteLength.Half;
2069
+ let MaxTripletNoteLenght = import_theory4.NoteLength.Half;
2295
2070
  let len = symbols.map((s) => s.rhythmProps.noteLength);
2296
2071
  if (symbols.length == 2) {
2297
- if (len[0] <= MaxTripletNoteLenght && len[1] === len[0] / 2 && len[0] / 2 >= import_theory5.MinNoteLength || len[1] <= MaxTripletNoteLenght && len[0] === len[1] / 2 && len[1] / 2 >= import_theory5.MinNoteLength) {
2072
+ if (len[0] <= MaxTripletNoteLenght && len[1] === len[0] / 2 && len[0] / 2 >= import_theory4.MinNoteLength || len[1] <= MaxTripletNoteLenght && len[0] === len[1] / 2 && len[1] / 2 >= import_theory4.MinNoteLength) {
2298
2073
  new _ObjBeamGroup(symbols, true);
2299
2074
  return true;
2300
2075
  }
@@ -2418,7 +2193,7 @@ var ObjBeamGroup = class _ObjBeamGroup extends MusicObject {
2418
2193
  symbolY.forEach((symY, i) => {
2419
2194
  let symX = symbolX[i];
2420
2195
  if (symX !== void 0 && symY !== void 0) {
2421
- let beamY = import_ts_utils_lib4.Utils.Math.interpolateY(leftX, leftY, rightX, rightY, symX);
2196
+ let beamY = import_ts_utils_lib3.Utils.Math.interpolateY(leftX, leftY, rightX, rightY, symX);
2422
2197
  let raiseY = symY - beamY;
2423
2198
  if (stemDir === 1 /* Up */ && raiseY < 0) {
2424
2199
  raiseBeamY = Math.min(raiseBeamY, raiseY);
@@ -2433,8 +2208,8 @@ var ObjBeamGroup = class _ObjBeamGroup extends MusicObject {
2433
2208
  let obj = new ObjStaffBeamGroup(mainStaff, this);
2434
2209
  if (this.type === 2 /* TripletGroup */) {
2435
2210
  let ef = unitSize / (rightX - leftX);
2436
- let l = import_ts_utils_lib4.Utils.Math.interpolateCoord(leftX, leftY + groupLineDy, rightX, rightY + groupLineDy, -ef);
2437
- let r = import_ts_utils_lib4.Utils.Math.interpolateCoord(leftX, leftY + groupLineDy, rightX, rightY + groupLineDy, 1 + ef);
2211
+ let l = import_ts_utils_lib3.Utils.Math.interpolateCoord(leftX, leftY + groupLineDy, rightX, rightY + groupLineDy, -ef);
2212
+ let r = import_ts_utils_lib3.Utils.Math.interpolateCoord(leftX, leftY + groupLineDy, rightX, rightY + groupLineDy, 1 + ef);
2438
2213
  obj.points.push(new BeamPoint(leftStaff, this, leftSymbol, l.x, l.y));
2439
2214
  obj.points.push(new BeamPoint(rightStaff, this, rightSymbol, r.x, r.y));
2440
2215
  obj.tripletNumberOffsetY = 0;
@@ -2492,7 +2267,7 @@ var ObjBeamGroup = class _ObjBeamGroup extends MusicObject {
2492
2267
  obj.points.forEach((pt) => {
2493
2268
  if (pt.symbol instanceof ObjNoteGroup) {
2494
2269
  if (pt !== left && pt !== right) {
2495
- pt.y = import_ts_utils_lib4.Utils.Math.interpolateY(left.x, left.y, right.x, right.y, pt.x);
2270
+ pt.y = import_ts_utils_lib3.Utils.Math.interpolateY(left.x, left.y, right.x, right.y, pt.x);
2496
2271
  }
2497
2272
  pt.symbol.setStemTipY(pt.staff, pt.y);
2498
2273
  }
@@ -2517,8 +2292,8 @@ var ObjBeamGroup = class _ObjBeamGroup extends MusicObject {
2517
2292
  let r = obj.points[obj.points.length - 1];
2518
2293
  if (l && r) {
2519
2294
  let tf = obj.tripletNumber ? obj.tripletNumber.getRect().width / (r.x - l.x) * 1.2 : 0;
2520
- let lc = import_ts_utils_lib4.Utils.Math.interpolateCoord(l.x, l.y, r.x, r.y, 0.5 - tf / 2);
2521
- let rc = import_ts_utils_lib4.Utils.Math.interpolateCoord(l.x, l.y, r.x, r.y, 0.5 + tf / 2);
2295
+ let lc = import_ts_utils_lib3.Utils.Math.interpolateCoord(l.x, l.y, r.x, r.y, 0.5 - tf / 2);
2296
+ let rc = import_ts_utils_lib3.Utils.Math.interpolateCoord(l.x, l.y, r.x, r.y, 0.5 + tf / 2);
2522
2297
  let tipH = this.stemDir === 1 /* Up */ ? unitSize : -unitSize;
2523
2298
  renderer.drawLine(l.x, l.y, lc.x, lc.y, color, lineWidth);
2524
2299
  renderer.drawLine(rc.x, rc.y, r.x, r.y, color, lineWidth);
@@ -2561,13 +2336,13 @@ var ObjBeamGroup = class _ObjBeamGroup extends MusicObject {
2561
2336
  };
2562
2337
 
2563
2338
  // src/score/engine/obj-note-group.ts
2564
- var import_core8 = require("@tspro/web-music-score/core");
2339
+ var import_core7 = require("@tspro/web-music-score/core");
2565
2340
  function sortNoteStringData(notes, strings) {
2566
- let stringArr = import_ts_utils_lib5.Utils.Arr.isArray(strings) ? strings : strings !== void 0 ? [strings] : [];
2341
+ let stringArr = import_ts_utils_lib4.Utils.Arr.isArray(strings) ? strings : strings !== void 0 ? [strings] : [];
2567
2342
  let noteStringData = notes.map((note, i) => {
2568
2343
  return { note, string: stringArr[i] };
2569
2344
  });
2570
- noteStringData = import_ts_utils_lib5.Utils.Arr.removeDuplicatesCmp(noteStringData, (a, b) => import_theory6.Note.equals(a.note, b.note)).sort((a, b) => import_theory6.Note.compareFunc(a.note, b.note));
2345
+ noteStringData = import_ts_utils_lib4.Utils.Arr.removeDuplicatesCmp(noteStringData, (a, b) => import_theory5.Note.equals(a.note, b.note)).sort((a, b) => import_theory5.Note.compareFunc(a.note, b.note));
2571
2346
  return {
2572
2347
  notes: noteStringData.map((e) => e.note),
2573
2348
  strings: noteStringData.every((e) => e.string === void 0) ? void 0 : noteStringData.map((e) => e.string)
@@ -2681,8 +2456,8 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2681
2456
  __publicField(this, "staffObjects", []);
2682
2457
  __publicField(this, "tabObjects", []);
2683
2458
  __publicField(this, "mi");
2684
- if (!import_ts_utils_lib5.Utils.Is.isIntegerGte(notes.length, 1)) {
2685
- throw new import_core8.MusicError(import_core8.MusicErrorType.Score, "Cannot create note group object because notes array is empty.");
2459
+ if (!import_ts_utils_lib4.Utils.Is.isIntegerGte(notes.length, 1)) {
2460
+ throw new import_core7.MusicError(import_core7.MusicErrorType.Score, "Cannot create note group object because notes array is empty.");
2686
2461
  }
2687
2462
  let noteStringData = sortNoteStringData(notes, options == null ? void 0 : options.string);
2688
2463
  this.notes = noteStringData.notes;
@@ -2695,7 +2470,7 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2695
2470
  this.staccato = (_b = options == null ? void 0 : options.staccato) != null ? _b : false;
2696
2471
  this.diamond = (_c = options == null ? void 0 : options.diamond) != null ? _c : false;
2697
2472
  this.arpeggio = solveArpeggio(options == null ? void 0 : options.arpeggio);
2698
- this.rhythmProps = new import_theory6.RhythmProps(noteLength, options == null ? void 0 : options.dotted, options == null ? void 0 : options.triplet);
2473
+ this.rhythmProps = new import_theory5.RhythmProps(noteLength, options == null ? void 0 : options.dotted, options == null ? void 0 : options.triplet);
2699
2474
  this.mi = new MNoteGroup(this);
2700
2475
  }
2701
2476
  getMusicInterface() {
@@ -2721,13 +2496,27 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2721
2496
  }
2722
2497
  startConnective(connectiveProps) {
2723
2498
  if (!this.row.hasStaff && connectiveProps.connective === 0 /* Tie */) {
2724
- throw new import_core8.MusicError(import_core8.MusicErrorType.Score, "Ties not implemented for guitar tabs alone, staff is required!");
2499
+ throw new import_core7.MusicError(import_core7.MusicErrorType.Score, "Ties not implemented for guitar tabs alone, staff is required!");
2725
2500
  } else if (!this.row.hasStaff && connectiveProps.connective === 1 /* Slur */) {
2726
- throw new import_core8.MusicError(import_core8.MusicErrorType.Score, "Slurs not implemented for guitar tabs alone, staff is required!");
2501
+ throw new import_core7.MusicError(import_core7.MusicErrorType.Score, "Slurs not implemented for guitar tabs alone, staff is required!");
2727
2502
  }
2728
2503
  this.startConnnectives.push(connectiveProps);
2729
2504
  this.doc.addConnectiveProps(connectiveProps);
2730
2505
  }
2506
+ getStaticObjects(line) {
2507
+ let staticObjects = [];
2508
+ this.staffObjects.forEach((obj) => {
2509
+ if (obj.staff === line) {
2510
+ staticObjects.push(obj);
2511
+ }
2512
+ });
2513
+ this.tabObjects.forEach((obj) => {
2514
+ if (obj.tab === line) {
2515
+ staticObjects.push(obj);
2516
+ }
2517
+ });
2518
+ return staticObjects;
2519
+ }
2731
2520
  pick(x, y) {
2732
2521
  if (!this.getRect().contains(x, y)) {
2733
2522
  return [];
@@ -2756,7 +2545,7 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2756
2545
  if (line instanceof ObjStaff) {
2757
2546
  let staff = line;
2758
2547
  if (noteIndex < 0 || noteIndex >= this.notes.length) {
2759
- throw new import_core8.MusicError(import_core8.MusicErrorType.Score, "Invalid noteIndex: " + noteIndex);
2548
+ throw new import_core7.MusicError(import_core7.MusicErrorType.Score, "Invalid noteIndex: " + noteIndex);
2760
2549
  }
2761
2550
  let obj = this.staffObjects.find((obj2) => obj2.staff === staff);
2762
2551
  if (!obj || noteIndex < 0 || noteIndex >= obj.noteHeadRects.length) {
@@ -2804,7 +2593,7 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2804
2593
  case 4 /* StemTip */:
2805
2594
  return { x: centerX, y: stemTip.centerY + (stemDir === 1 /* Up */ ? -padding : padding) };
2806
2595
  default:
2807
- throw new import_core8.MusicError(import_core8.MusicErrorType.Score, "Invalid noteAnchor: " + noteAnchor);
2596
+ throw new import_core7.MusicError(import_core7.MusicErrorType.Score, "Invalid noteAnchor: " + noteAnchor);
2808
2597
  }
2809
2598
  } else {
2810
2599
  let tab = line;
@@ -2903,7 +2692,7 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2903
2692
  getStemHeight(renderer) {
2904
2693
  let { unitSize } = renderer;
2905
2694
  let { noteLength, flagCount } = this.rhythmProps;
2906
- if (noteLength >= import_theory6.NoteLength.Whole) {
2695
+ if (noteLength >= import_theory5.NoteLength.Whole) {
2907
2696
  return 0;
2908
2697
  } else {
2909
2698
  let addY = this.hasBeamCount() ? DocumentSettings.BeamSeparation : DocumentSettings.FlagSeparation;
@@ -2936,15 +2725,15 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2936
2725
  return Math.max(this.rhythmProps.ticks, this.measure.getMeasureTicks() - this.col.positionTicks);
2937
2726
  }
2938
2727
  let prev = tieNoteGroups[j - 1];
2939
- if (prev && prev.notes.some((n) => import_theory6.Note.equals(n, note))) {
2728
+ if (prev && prev.notes.some((n) => import_theory5.Note.equals(n, note))) {
2940
2729
  return 0;
2941
2730
  }
2942
2731
  tieNoteGroups = tieNoteGroups.slice(j);
2943
- j = tieNoteGroups.findIndex((ng) => ng.notes.every((n) => !import_theory6.Note.equals(n, note)));
2732
+ j = tieNoteGroups.findIndex((ng) => ng.notes.every((n) => !import_theory5.Note.equals(n, note)));
2944
2733
  if (j >= 0) {
2945
2734
  tieNoteGroups = tieNoteGroups.slice(0, j);
2946
2735
  }
2947
- return import_ts_utils_lib5.Utils.Math.sum(tieNoteGroups.map((ng) => ng.rhythmProps.ticks));
2736
+ return import_ts_utils_lib4.Utils.Math.sum(tieNoteGroups.map((ng) => ng.rhythmProps.ticks));
2948
2737
  });
2949
2738
  return tiedTicks.length === 0 ? this.rhythmProps.ticks : Math.max(...tiedTicks);
2950
2739
  }
@@ -3105,7 +2894,7 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
3105
2894
  ctx.strokeStyle = ctx.fillStyle = color;
3106
2895
  ctx.lineWidth = lineWidth;
3107
2896
  obj.noteHeadRects.forEach((r) => {
3108
- let outlinedNoteHead = noteLength >= import_theory6.NoteLength.Half;
2897
+ let outlinedNoteHead = noteLength >= import_theory5.NoteLength.Half;
3109
2898
  if (this.diamond) {
3110
2899
  if (outlinedNoteHead) {
3111
2900
  ctx.beginPath();
@@ -3236,7 +3025,7 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
3236
3025
  }
3237
3026
  });
3238
3027
  } else {
3239
- throw new import_core8.MusicError(import_core8.MusicErrorType.Score, "Cannot set triplet beam count because triplet beam group type is invalid.");
3028
+ throw new import_core7.MusicError(import_core7.MusicErrorType.Score, "Cannot set triplet beam count because triplet beam group type is invalid.");
3240
3029
  }
3241
3030
  }
3242
3031
  getDotVerticalDisplacement(staff, diatonicId, stemDir) {
@@ -3262,9 +3051,9 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
3262
3051
  };
3263
3052
 
3264
3053
  // src/score/engine/obj-rhythm-column.ts
3265
- var import_core9 = require("@tspro/web-music-score/core");
3054
+ var import_core8 = require("@tspro/web-music-score/core");
3266
3055
  var noteHeadDataCompareFunc = (a, b) => {
3267
- let cmp = import_theory7.Note.compareFunc(a.note, b.note);
3056
+ let cmp = import_theory6.Note.compareFunc(a.note, b.note);
3268
3057
  if (cmp === 0) {
3269
3058
  cmp = a.noteGroup.stemDir === b.noteGroup.stemDir ? 0 : a.noteGroup.stemDir === 1 /* Up */ ? 1 : -1;
3270
3059
  }
@@ -3305,7 +3094,7 @@ var ObjRhythmColumn = class extends MusicObject {
3305
3094
  if (colId >= 0 && colId < this.measure.getColumnCount()) {
3306
3095
  return this.measure.getColumn(colId + 1);
3307
3096
  } else {
3308
- throw new import_core9.MusicError(import_core9.MusicErrorType.Score, "Cannot get next column in measure because current column's id in mesure is invalid.");
3097
+ throw new import_core8.MusicError(import_core8.MusicErrorType.Score, "Cannot get next column in measure because current column's id in mesure is invalid.");
3309
3098
  }
3310
3099
  }
3311
3100
  /**
@@ -3332,6 +3121,22 @@ var ObjRhythmColumn = class extends MusicObject {
3332
3121
  this.getRect();
3333
3122
  return this.shapeRects;
3334
3123
  }
3124
+ getStaticObjects(line) {
3125
+ let staticObjects = [];
3126
+ this.voiceSymbol.forEach((symbol) => {
3127
+ if (symbol) {
3128
+ symbol.getRect();
3129
+ symbol.getStaticObjects(line).forEach((obj) => staticObjects.push(obj));
3130
+ }
3131
+ });
3132
+ this.arpeggios.forEach((arpeggio) => {
3133
+ if (arpeggio.line === line) {
3134
+ arpeggio.getRect();
3135
+ staticObjects.push(arpeggio);
3136
+ }
3137
+ });
3138
+ return staticObjects;
3139
+ }
3335
3140
  get doc() {
3336
3141
  return this.measure.doc;
3337
3142
  }
@@ -3369,7 +3174,7 @@ var ObjRhythmColumn = class extends MusicObject {
3369
3174
  validateVoiceId(voiceId);
3370
3175
  this.voiceSymbol[voiceId] = symbol;
3371
3176
  if (symbol instanceof ObjRest) {
3372
- if (!symbol.hide && symbol.noteLength >= import_theory7.NoteLength.Half) {
3177
+ if (!symbol.hide && symbol.noteLength >= import_theory6.NoteLength.Half) {
3373
3178
  this.minDiatonicId = this.minDiatonicId === void 0 ? symbol.ownDiatonicId : Math.min(this.minDiatonicId, symbol.ownDiatonicId);
3374
3179
  this.maxDiatonicId = this.maxDiatonicId === void 0 ? symbol.ownDiatonicId : Math.max(this.maxDiatonicId, symbol.ownDiatonicId);
3375
3180
  }
@@ -3382,6 +3187,7 @@ var ObjRhythmColumn = class extends MusicObject {
3382
3187
  this.setupNoteHeadDisplacements();
3383
3188
  }
3384
3189
  this.requestLayout();
3190
+ this.requestRectUpdate();
3385
3191
  }
3386
3192
  getVoiceSymbol(voiceId) {
3387
3193
  return this.voiceSymbol[voiceId];
@@ -3390,11 +3196,11 @@ var ObjRhythmColumn = class extends MusicObject {
3390
3196
  let maxNoteLength = Math.max(...this.voiceSymbol.map((s) => s.rhythmProps.noteLength));
3391
3197
  let w = DocumentSettings.NoteHeadWidth;
3392
3198
  switch (maxNoteLength) {
3393
- case import_theory7.NoteLength.Whole:
3199
+ case import_theory6.NoteLength.Whole:
3394
3200
  return w * 5;
3395
- case import_theory7.NoteLength.Half:
3201
+ case import_theory6.NoteLength.Half:
3396
3202
  return w * 3;
3397
- case import_theory7.NoteLength.Quarter:
3203
+ case import_theory6.NoteLength.Quarter:
3398
3204
  return w * 2;
3399
3205
  default:
3400
3206
  return w;
@@ -3436,7 +3242,7 @@ var ObjRhythmColumn = class extends MusicObject {
3436
3242
  }
3437
3243
  }
3438
3244
  getNoteHeadDisplacement(noteGroup, note) {
3439
- let data = this.noteHeadDisplacements.find((d) => d.noteGroup === noteGroup && import_theory7.Note.equals(d.note, note));
3245
+ let data = this.noteHeadDisplacements.find((d) => d.noteGroup === noteGroup && import_theory6.Note.equals(d.note, note));
3440
3246
  if ((data == null ? void 0 : data.displacement) !== void 0) {
3441
3247
  return data.displacement;
3442
3248
  } else {
@@ -3480,7 +3286,7 @@ var ObjRhythmColumn = class extends MusicObject {
3480
3286
  });
3481
3287
  }
3482
3288
  });
3483
- playerNotes.sort((a, b) => import_theory7.Note.compareFunc(a.note, b.note));
3289
+ playerNotes.sort((a, b) => import_theory6.Note.compareFunc(a.note, b.note));
3484
3290
  if (this.hasArpeggio() && this.getArpeggioDir() === 1 /* Down */) {
3485
3291
  playerNotes.reverse();
3486
3292
  }
@@ -3496,6 +3302,7 @@ var ObjRhythmColumn = class extends MusicObject {
3496
3302
  if (!this.needLayout) {
3497
3303
  return;
3498
3304
  }
3305
+ this.requestRectUpdate();
3499
3306
  this.rect = new DivRect();
3500
3307
  let { row } = this;
3501
3308
  let { unitSize } = renderer;
@@ -3510,12 +3317,12 @@ var ObjRhythmColumn = class extends MusicObject {
3510
3317
  });
3511
3318
  if (this.arpeggioDir !== void 0) {
3512
3319
  let arpeggioWidth = 0;
3513
- this.arpeggios = row.getStaves().map((staff) => {
3514
- let arpeggio = new ObjArpeggio(this, this.getArpeggioDir());
3320
+ this.arpeggios = row.getNotationLines().map((line) => {
3321
+ let arpeggio = new ObjArpeggio(this, line, this.getArpeggioDir());
3515
3322
  arpeggio.layout(renderer);
3516
- arpeggio.offset(-leftw - arpeggio.getRect().right, staff.getMiddleLineY() - arpeggio.getRect().centerY);
3323
+ arpeggio.offset(-leftw - arpeggio.getRect().right, line.getRect().centerY - arpeggio.getRect().centerY);
3517
3324
  arpeggioWidth = Math.max(arpeggioWidth, arpeggio.getRect().width);
3518
- staff.addObject(arpeggio);
3325
+ line.addObject(arpeggio);
3519
3326
  return arpeggio;
3520
3327
  });
3521
3328
  leftw += arpeggioWidth;
@@ -3533,7 +3340,6 @@ var ObjRhythmColumn = class extends MusicObject {
3533
3340
  this.rect.left = -leftw;
3534
3341
  this.rect.centerX = 0;
3535
3342
  this.rect.right = rightw;
3536
- this.requestRectUpdate();
3537
3343
  this.row.getStaves().forEach((staff) => {
3538
3344
  let minDiatonicId = void 0;
3539
3345
  let maxDiatonicId = void 0;
@@ -3728,7 +3534,7 @@ function isTempoText(text) {
3728
3534
  }
3729
3535
 
3730
3536
  // src/score/engine/extension.ts
3731
- var import_core10 = require("@tspro/web-music-score/core");
3537
+ var import_core9 = require("@tspro/web-music-score/core");
3732
3538
  function getTextAnchorY(linePos) {
3733
3539
  switch (linePos) {
3734
3540
  case "bottom":
@@ -3764,7 +3570,7 @@ var Extension = class extends MusicObjectLink {
3764
3570
  if (head instanceof ObjText) {
3765
3571
  head.updateAnchorY(getTextAnchorY(linePos));
3766
3572
  } else {
3767
- throw new import_core10.MusicError(import_core10.MusicErrorType.Score, "Update anchor's y-coordinate is only implemented for text objects.");
3573
+ throw new import_core9.MusicError(import_core9.MusicErrorType.Score, "Update anchor's y-coordinate is only implemented for text objects.");
3768
3574
  }
3769
3575
  }
3770
3576
  isVisible() {
@@ -3844,7 +3650,7 @@ var RitardandoSpeedDiv = 2;
3844
3650
  var CrescendoVolumeAdd = 0.5;
3845
3651
  var DiminuendoVolumeSub = 0.5;
3846
3652
  function calcTicksDuration(ticks, tempo) {
3847
- let beatTicks = new import_theory8.RhythmProps(tempo.options.beatLength, tempo.options.dotted).ticks;
3653
+ let beatTicks = new import_theory7.RhythmProps(tempo.options.beatLength, tempo.options.dotted).ticks;
3848
3654
  let ticksPerMinute = tempo.beatsPerMinute * beatTicks;
3849
3655
  return 60 * ticks / ticksPerMinute;
3850
3656
  }
@@ -3900,8 +3706,8 @@ var PlayerColumnProps = class {
3900
3706
  return this.speed;
3901
3707
  }
3902
3708
  getTempo() {
3903
- let speed = import_ts_utils_lib6.Utils.Math.clamp(this.getSpeed(), 0.1, 10);
3904
- return (0, import_theory8.alterTempoSpeed)(this.measure.getTempo(), speed);
3709
+ let speed = import_ts_utils_lib5.Utils.Math.clamp(this.getSpeed(), 0.1, 10);
3710
+ return (0, import_theory7.alterTempoSpeed)(this.measure.getTempo(), speed);
3905
3711
  }
3906
3712
  setVolume(volume) {
3907
3713
  this.volume = volume;
@@ -3925,7 +3731,7 @@ var PlayerColumnProps = class {
3925
3731
  if (symbolsTicks.length === 0) {
3926
3732
  return 0;
3927
3733
  } else {
3928
- return import_ts_utils_lib6.Utils.Math.sum(symbolsTicks) / symbolsTicks.length;
3734
+ return import_ts_utils_lib5.Utils.Math.sum(symbolsTicks) / symbolsTicks.length;
3929
3735
  }
3930
3736
  }
3931
3737
  }
@@ -4073,7 +3879,7 @@ var Player = class _Player {
4073
3879
  } else if (layoutObj.musicObj.getLink() instanceof Extension) {
4074
3880
  let extension = layoutObj.musicObj.getLink();
4075
3881
  let { columnRange, extensionBreakText } = extension.getExtensionRangeInfo();
4076
- let totalTicks = import_ts_utils_lib6.Utils.Math.sum(columnRange.map((c) => c.getTicksToNextColumn()));
3882
+ let totalTicks = import_ts_utils_lib5.Utils.Math.sum(columnRange.map((c) => c.getTicksToNextColumn()));
4077
3883
  switch (text) {
4078
3884
  case "accel." /* accel */: {
4079
3885
  let startSpeed = curSpeed;
@@ -4127,11 +3933,11 @@ var Player = class _Player {
4127
3933
  });
4128
3934
  let speedArr = (_a = speedMap.get(col)) != null ? _a : [];
4129
3935
  if (speedArr.length > 0) {
4130
- curSpeed = import_ts_utils_lib6.Utils.Math.sum(speedArr) / speedArr.length;
3936
+ curSpeed = import_ts_utils_lib5.Utils.Math.sum(speedArr) / speedArr.length;
4131
3937
  }
4132
3938
  let volumeArr = (_b = volumeMap.get(col)) != null ? _b : [];
4133
3939
  if (volumeArr.length > 0) {
4134
- curVolume = import_ts_utils_lib6.Utils.Math.sum(volumeArr) / volumeArr.length;
3940
+ curVolume = import_ts_utils_lib5.Utils.Math.sum(volumeArr) / volumeArr.length;
4135
3941
  }
4136
3942
  col.getPlayerProps().setSpeed(curSpeed);
4137
3943
  col.getPlayerProps().setVolume(curVolume);
@@ -4169,11 +3975,11 @@ var Player = class _Player {
4169
3975
  } else {
4170
3976
  let playerNotes = col.getPlayerNotes();
4171
3977
  playerNotes.forEach((note, i) => {
4172
- let arpeggioDelayTicks = col.hasArpeggio() ? import_theory8.NoteLength.ThirtySecond * i : 0;
3978
+ let arpeggioDelayTicks = col.hasArpeggio() ? import_theory7.NoteLength.ThirtySecond * i : 0;
4173
3979
  let noteSeconds = getDuration(note.ticks + fermataHoldTicks - arpeggioDelayTicks, tempo);
4174
3980
  if (noteSeconds > 0) {
4175
3981
  if (note.staccato) {
4176
- noteSeconds = Math.min(getDuration(import_theory8.NoteLength.Eighth, tempo) / 2, noteSeconds / 2);
3982
+ noteSeconds = Math.min(getDuration(import_theory7.NoteLength.Eighth, tempo) / 2, noteSeconds / 2);
4177
3983
  }
4178
3984
  let volume = adjustVolume(col.getPlayerProps().getVolume());
4179
3985
  if (note.slur === "slurred") {
@@ -4323,14 +4129,12 @@ var ObjBarLine = class extends MusicObject {
4323
4129
  if (line instanceof ObjStaff) {
4324
4130
  lineCenterY = line.getMiddleLineY();
4325
4131
  lineDotOff = line.getDiatonicSpacing();
4326
- top = line.getTopLineY();
4327
- bottom = line.getBottomLineY();
4328
4132
  } else {
4329
- lineCenterY = (line.getBottom() + line.getTop()) / 2;
4330
- lineDotOff = (line.getBottom() - line.getTop()) / 6;
4331
- top = line.getTopStringY();
4332
- bottom = line.getBottomStringY();
4133
+ lineCenterY = (line.getBottomLineY() + line.getTopLineY()) / 2;
4134
+ lineDotOff = (line.getBottomLineY() - line.getTopLineY()) / 6;
4333
4135
  }
4136
+ top = line.getTopLineY();
4137
+ bottom = line.getBottomLineY();
4334
4138
  switch (barLineType) {
4335
4139
  case 0 /* None */:
4336
4140
  obj.setRect(new DivRect(0, 0, 0, top, 0, bottom));
@@ -4462,8 +4266,8 @@ var ObjBarLineRight = class extends ObjBarLine {
4462
4266
  };
4463
4267
 
4464
4268
  // src/score/engine/obj-ending.ts
4465
- var import_ts_utils_lib7 = require("@tspro/ts-utils-lib");
4466
- var import_core11 = require("@tspro/web-music-score/core");
4269
+ var import_ts_utils_lib6 = require("@tspro/ts-utils-lib");
4270
+ var import_core10 = require("@tspro/web-music-score/core");
4467
4271
  var ObjEnding = class extends MusicObject {
4468
4272
  constructor(measure, passages) {
4469
4273
  super(measure);
@@ -4473,10 +4277,10 @@ var ObjEnding = class extends MusicObject {
4473
4277
  __publicField(this, "shapeRects", []);
4474
4278
  __publicField(this, "mi");
4475
4279
  this.mi = new MEnding(this);
4476
- if (!import_ts_utils_lib7.Utils.Is.isIntegerGte(passages.length, 1)) {
4477
- throw new import_core11.MusicError(import_core11.MusicErrorType.Score, "Passages is empty.");
4478
- } else if (!this.passages.every((p) => import_ts_utils_lib7.Utils.Is.isIntegerGte(p, 1))) {
4479
- throw new import_core11.MusicError(import_core11.MusicErrorType.Score, "Invalid passages: " + this.passages);
4280
+ if (!import_ts_utils_lib6.Utils.Is.isIntegerGte(passages.length, 1)) {
4281
+ throw new import_core10.MusicError(import_core10.MusicErrorType.Score, "Passages is empty.");
4282
+ } else if (!this.passages.every((p) => import_ts_utils_lib6.Utils.Is.isIntegerGte(p, 1))) {
4283
+ throw new import_core10.MusicError(import_core10.MusicErrorType.Score, "Invalid passages: " + this.passages);
4480
4284
  }
4481
4285
  this.passages.sort((a, b) => a - b);
4482
4286
  let text = this.passages.map((p) => p + ".").join("");
@@ -4565,9 +4369,9 @@ var ObjFermata = class extends MusicObject {
4565
4369
  let { measure } = anchor;
4566
4370
  let { row } = measure;
4567
4371
  if (row.getTopStaff() !== row.getBottomStaff()) {
4568
- return [0 /* AboveStaff */, 1 /* BelowStaff */];
4372
+ return [0 /* Above */, 1 /* Below */];
4569
4373
  } else {
4570
- return [0 /* AboveStaff */];
4374
+ return [0 /* Above */];
4571
4375
  }
4572
4376
  }
4573
4377
  pick(x, y) {
@@ -4588,7 +4392,7 @@ var ObjFermata = class extends MusicObject {
4588
4392
  return;
4589
4393
  }
4590
4394
  let { lineWidth, unitSize } = renderer;
4591
- let upsideDown = this.pos === 1 /* BelowStaff */;
4395
+ let upsideDown = this.pos === 1 /* Below */;
4592
4396
  let dy = (upsideDown ? unitSize : -unitSize) * 0.7;
4593
4397
  let left = this.rect.left;
4594
4398
  let right = this.rect.right;
@@ -4683,14 +4487,14 @@ var ObjExtensionLine = class extends MusicObject {
4683
4487
  };
4684
4488
 
4685
4489
  // src/score/engine/obj-measure.ts
4686
- var import_core14 = require("@tspro/web-music-score/core");
4490
+ var import_core13 = require("@tspro/web-music-score/core");
4687
4491
 
4688
4492
  // src/score/engine/connective-props.ts
4689
- var import_theory9 = require("@tspro/web-music-score/theory");
4493
+ var import_theory8 = require("@tspro/web-music-score/theory");
4690
4494
 
4691
4495
  // src/score/engine/obj-connective.ts
4692
- var import_ts_utils_lib8 = require("@tspro/ts-utils-lib");
4693
- var import_core12 = require("@tspro/web-music-score/core");
4496
+ var import_ts_utils_lib7 = require("@tspro/ts-utils-lib");
4497
+ var import_core11 = require("@tspro/web-music-score/core");
4694
4498
  var ObjConnective = class extends MusicObject {
4695
4499
  constructor(connectiveProps, line, measure, leftNoteGroup, leftNoteId, ...args) {
4696
4500
  super(measure);
@@ -4718,7 +4522,7 @@ var ObjConnective = class extends MusicObject {
4718
4522
  this.rightNoteGroup = args[0];
4719
4523
  this.rightNoteId = args[1];
4720
4524
  this.tieType = void 0;
4721
- } else if (import_ts_utils_lib8.Utils.Is.isEnumValue(args[0], TieType)) {
4525
+ } else if (import_ts_utils_lib7.Utils.Is.isEnumValue(args[0], TieType)) {
4722
4526
  this.rightNoteGroup = void 0;
4723
4527
  this.rightNoteId = void 0;
4724
4528
  this.tieType = args[0];
@@ -4779,7 +4583,7 @@ var ObjConnective = class extends MusicObject {
4779
4583
  rx = contentRect.right;
4780
4584
  ry = leftPos.y + (rightPos.y - leftPos.y) * tLeft / (tLeft + tRight);
4781
4585
  } else {
4782
- throw new import_core12.MusicError(import_core12.MusicErrorType.Score, "Cannot layout connective object because no valid left and right note groups.");
4586
+ throw new import_core11.MusicError(import_core11.MusicErrorType.Score, "Cannot layout connective object because no valid left and right note groups.");
4783
4587
  }
4784
4588
  let spanDy = arcDir === "up" ? -1 : 1;
4785
4589
  let arcHeight = spanDy * unitSize * Math.log2(rx - lx) / 3;
@@ -4788,7 +4592,7 @@ var ObjConnective = class extends MusicObject {
4788
4592
  this.rx = rx;
4789
4593
  this.ry = ry;
4790
4594
  this.arcHeight = this.connectiveProps.connective === 2 /* Slide */ ? 0 : arcHeight;
4791
- let { nx, ny } = import_ts_utils_lib8.Utils.Math.calcNormal(lx, ly, rx, ry);
4595
+ let { nx, ny } = import_ts_utils_lib7.Utils.Math.calcNormal(lx, ly, rx, ry);
4792
4596
  this.cp1x = lx * 0.7 + rx * 0.3 + nx * this.arcHeight;
4793
4597
  this.cp1y = ly * 0.7 + ry * 0.3 + ny * this.arcHeight;
4794
4598
  this.cp2x = lx * 0.3 + rx * 0.7 + nx * this.arcHeight;
@@ -4848,7 +4652,7 @@ var ObjConnective = class extends MusicObject {
4848
4652
  };
4849
4653
 
4850
4654
  // src/score/engine/connective-props.ts
4851
- var import_core13 = require("@tspro/web-music-score/core");
4655
+ var import_core12 = require("@tspro/web-music-score/core");
4852
4656
  var ConnectiveProps = class {
4853
4657
  constructor(connective, span, noteAnchor, startNoteGroup) {
4854
4658
  this.connective = connective;
@@ -4928,7 +4732,7 @@ var ConnectiveProps = class {
4928
4732
  let leftNoteGroup = this.noteGroups[i];
4929
4733
  let rightNoteGroup = this.noteGroups[i + 1];
4930
4734
  leftNoteGroup.notes.forEach((leftNote, leftNoteId) => {
4931
- let rightNoteId = rightNoteGroup.notes.findIndex((rightNote) => import_theory9.Note.equals(rightNote, leftNote));
4735
+ let rightNoteId = rightNoteGroup.notes.findIndex((rightNote) => import_theory8.Note.equals(rightNote, leftNote));
4932
4736
  if (rightNoteId >= 0) {
4933
4737
  this.createObjConnective(leftNoteGroup, leftNoteId, rightNoteGroup, rightNoteId);
4934
4738
  }
@@ -4983,7 +4787,7 @@ var ConnectiveProps = class {
4983
4787
  addConnective(leftNoteGroup.measure, leftNoteGroup, leftNoteId, rightNoteGroup, rightNoteId);
4984
4788
  addConnective(rightNoteGroup.measure, leftNoteGroup, leftNoteId, rightNoteGroup, rightNoteId);
4985
4789
  } else {
4986
- throw new import_core13.MusicError(import_core13.MusicErrorType.Score, "Cannot create connective because it is jumping measures.");
4790
+ throw new import_core12.MusicError(import_core12.MusicErrorType.Score, "Cannot create connective because it is jumping measures.");
4987
4791
  }
4988
4792
  }
4989
4793
  };
@@ -4991,7 +4795,7 @@ var ConnectiveProps = class {
4991
4795
  // src/score/engine/obj-measure.ts
4992
4796
  function validateVoiceId(voiceId) {
4993
4797
  if (getVoiceIds().indexOf(voiceId) < 0) {
4994
- throw new import_core14.MusicError(import_core14.MusicErrorType.Score, "Invalid voiceId: " + voiceId);
4798
+ throw new import_core13.MusicError(import_core13.MusicErrorType.Score, "Invalid voiceId: " + voiceId);
4995
4799
  } else {
4996
4800
  return voiceId;
4997
4801
  }
@@ -5002,9 +4806,9 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5002
4806
  this.row = row;
5003
4807
  __publicField(this, "prevMeasure");
5004
4808
  __publicField(this, "nextMeasure");
5005
- __publicField(this, "keySignature", (0, import_theory10.getDefaultKeySignature)());
5006
- __publicField(this, "timeSignature", (0, import_theory11.getDefaultTimeSignature)());
5007
- __publicField(this, "tempo", (0, import_theory11.getDefaultTempo)());
4809
+ __publicField(this, "keySignature", (0, import_theory9.getDefaultKeySignature)());
4810
+ __publicField(this, "timeSignature", (0, import_theory10.getDefaultTimeSignature)());
4811
+ __publicField(this, "tempo", (0, import_theory10.getDefaultTempo)());
5008
4812
  __publicField(this, "alterKeySignature");
5009
4813
  __publicField(this, "alterTimeSignature");
5010
4814
  __publicField(this, "alterTempo");
@@ -5027,7 +4831,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5027
4831
  __publicField(this, "voiceSymbols", []);
5028
4832
  __publicField(this, "lastAddedRhythmColumn");
5029
4833
  __publicField(this, "lastAddedRhythmSymbol");
5030
- __publicField(this, "addExtensionToMusicObject");
4834
+ __publicField(this, "addExtensionToMusicObjects", []);
5031
4835
  __publicField(this, "layoutObjects", []);
5032
4836
  __publicField(this, "postMeasureBreakWidth", 0);
5033
4837
  __publicField(this, "passCount", 0);
@@ -5039,6 +4843,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5039
4843
  __publicField(this, "endRepeatPlayCount", 2);
5040
4844
  // play twice.
5041
4845
  __publicField(this, "endRepeatPlayCountText");
4846
+ __publicField(this, "staticObjectsCache", /* @__PURE__ */ new Map());
5042
4847
  __publicField(this, "mi");
5043
4848
  this.mi = new MMeasure(this);
5044
4849
  this.prevMeasure = row.doc.getLastMeasure();
@@ -5087,10 +4892,10 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5087
4892
  if (this.row.hasStaff) {
5088
4893
  diatonicId = this.row.getTopStaff().middleLineDiatonicId;
5089
4894
  } else {
5090
- diatonicId = import_theory10.Note.getNote("C4").diatonicId;
4895
+ diatonicId = import_theory9.Note.getNote("C4").diatonicId;
5091
4896
  }
5092
4897
  }
5093
- return this.useDiatonicId[voiceId] = import_theory10.Note.validateDiatonicId(diatonicId);
4898
+ return this.useDiatonicId[voiceId] = import_theory9.Note.validateDiatonicId(diatonicId);
5094
4899
  }
5095
4900
  updateOwnStemDir(symbol, setStemDir) {
5096
4901
  var _a, _b;
@@ -5217,23 +5022,23 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5217
5022
  setKeySignature(...args) {
5218
5023
  var _a;
5219
5024
  (_a = this.getPrevMeasure()) == null ? void 0 : _a.endSection();
5220
- if (args[0] instanceof import_theory10.KeySignature) {
5025
+ if (args[0] instanceof import_theory9.KeySignature) {
5221
5026
  this.alterKeySignature = args[0];
5222
- } else if (args[0] instanceof import_theory10.Scale) {
5027
+ } else if (args[0] instanceof import_theory9.Scale) {
5223
5028
  this.alterKeySignature = args[0];
5224
5029
  } else {
5225
5030
  try {
5226
5031
  let tonic = "" + args[0];
5227
- let scaleType = (0, import_theory10.validateScaleType)("" + args[1]);
5228
- this.alterKeySignature = (0, import_theory10.getScale)(tonic, scaleType);
5032
+ let scaleType = (0, import_theory9.validateScaleType)("" + args[1]);
5033
+ this.alterKeySignature = (0, import_theory9.getScale)(tonic, scaleType);
5229
5034
  } catch (e) {
5230
- throw new import_core14.MusicError(import_core14.MusicErrorType.Score, "Cannot set key signature because invalid args: " + args);
5035
+ throw new import_core13.MusicError(import_core13.MusicErrorType.Score, "Cannot set key signature because invalid args: " + args);
5231
5036
  }
5232
5037
  }
5233
5038
  this.updateKeySignature();
5234
5039
  }
5235
5040
  updateKeySignature() {
5236
- this.keySignature = this.prevMeasure ? this.prevMeasure.keySignature : (0, import_theory10.getDefaultKeySignature)();
5041
+ this.keySignature = this.prevMeasure ? this.prevMeasure.keySignature : (0, import_theory9.getDefaultKeySignature)();
5237
5042
  if (this.alterKeySignature) {
5238
5043
  this.keySignature = this.alterKeySignature;
5239
5044
  }
@@ -5248,11 +5053,11 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5248
5053
  setTimeSignature(timeSignature) {
5249
5054
  var _a;
5250
5055
  (_a = this.getPrevMeasure()) == null ? void 0 : _a.endSection();
5251
- this.alterTimeSignature = timeSignature instanceof import_theory11.TimeSignature ? timeSignature : new import_theory11.TimeSignature(timeSignature);
5056
+ this.alterTimeSignature = timeSignature instanceof import_theory10.TimeSignature ? timeSignature : new import_theory10.TimeSignature(timeSignature);
5252
5057
  this.updateTimeSignature();
5253
5058
  }
5254
5059
  updateTimeSignature() {
5255
- this.timeSignature = this.prevMeasure ? this.prevMeasure.timeSignature : (0, import_theory11.getDefaultTimeSignature)();
5060
+ this.timeSignature = this.prevMeasure ? this.prevMeasure.timeSignature : (0, import_theory10.getDefaultTimeSignature)();
5256
5061
  if (this.alterTimeSignature) {
5257
5062
  this.timeSignature = this.alterTimeSignature;
5258
5063
  }
@@ -5273,7 +5078,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5273
5078
  }
5274
5079
  updateTempo() {
5275
5080
  var _a;
5276
- this.tempo = this.prevMeasure ? this.prevMeasure.tempo : (0, import_theory11.getDefaultTempo)();
5081
+ this.tempo = this.prevMeasure ? this.prevMeasure.tempo : (0, import_theory10.getDefaultTempo)();
5277
5082
  if (this.alterTempo) {
5278
5083
  let beatsPerMinute = this.alterTempo.beatsPerMinute;
5279
5084
  let beatLength;
@@ -5301,25 +5106,18 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5301
5106
  getPostMeasureBreakWidth() {
5302
5107
  return this.postMeasureBreakWidth;
5303
5108
  }
5304
- addLayoutObject(musicObj, layoutGroupId, verticalPos) {
5305
- let w = new LayoutObjectWrapper(musicObj, layoutGroupId, verticalPos);
5306
- this.layoutObjects.push(w);
5109
+ addLayoutObject(musicObj, line, layoutGroupId, verticalPos) {
5110
+ this.layoutObjects.push(new LayoutObjectWrapper(musicObj, line, layoutGroupId, verticalPos));
5307
5111
  this.requestLayout();
5112
+ this.requestRectUpdate();
5308
5113
  }
5309
- addFermata(fermata) {
5114
+ addFermata(staffTabOrGroup, fermata) {
5310
5115
  let anchor = fermata === 1 /* AtMeasureEnd */ ? this.barLineRight : this.lastAddedRhythmColumn;
5311
5116
  if (!anchor) {
5312
- throw new import_core14.MusicError(import_core14.MusicErrorType.Score, "Cannot add Fermata because anchor is undefined.");
5117
+ throw new import_core13.MusicError(import_core13.MusicErrorType.Score, "Cannot add Fermata because anchor is undefined.");
5313
5118
  }
5314
- let fermataObjArr = anchor.getAnchoredLayoutObjects().map((layoutObj) => layoutObj.musicObj).filter((musicObj) => musicObj instanceof ObjFermata);
5315
- let hasAbove = fermataObjArr.some((obj) => obj.pos === 0 /* AboveStaff */);
5316
- let hasBelow = fermataObjArr.some((obj) => obj.pos === 1 /* BelowStaff */);
5317
- ObjFermata.getFermataPositions(anchor).forEach((fermataPos) => {
5318
- if (fermataPos === 0 /* AboveStaff */ && !hasAbove) {
5319
- this.addLayoutObject(new ObjFermata(anchor, fermataPos), 0 /* Fermata */, fermataPos);
5320
- } else if (fermataPos === 1 /* BelowStaff */ && !hasBelow) {
5321
- this.addLayoutObject(new ObjFermata(anchor, fermataPos), 0 /* Fermata */, fermataPos);
5322
- }
5119
+ this.forEachStaffGroup(staffTabOrGroup, 0 /* Above */, (line, vpos) => {
5120
+ this.addLayoutObject(new ObjFermata(anchor, vpos), line, 0 /* Fermata */, vpos);
5323
5121
  });
5324
5122
  this.disableExtension();
5325
5123
  this.requestLayout();
@@ -5327,15 +5125,20 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5327
5125
  hasFermata(anchor) {
5328
5126
  return this.layoutObjects.some((layoutObj) => layoutObj.musicObj instanceof ObjFermata && layoutObj.anchor === anchor);
5329
5127
  }
5330
- addNavigation(navigation, ...args) {
5128
+ addNavigation(staffTabOrGroup, navigation, ...args) {
5129
+ let addLayoutObjectProps = void 0;
5331
5130
  switch (navigation) {
5332
5131
  case 10 /* Ending */:
5333
5132
  if (this.navigationSet.has(navigation)) {
5334
- throw new import_core14.MusicError(import_core14.MusicErrorType.Score, "Cannot add ending beasure measure already has one.");
5133
+ throw new import_core13.MusicError(import_core13.MusicErrorType.Score, "Cannot add ending beasure measure already has one.");
5335
5134
  }
5336
5135
  let anchor = this;
5337
5136
  let passages = args;
5338
- this.addLayoutObject(new ObjEnding(anchor, passages), 3 /* Ending */, 0 /* AboveStaff */);
5137
+ addLayoutObjectProps = {
5138
+ createObj: () => new ObjEnding(anchor, passages),
5139
+ layoutGroupId: 3 /* Ending */,
5140
+ defaultVerticalPos: 0 /* Above */
5141
+ };
5339
5142
  break;
5340
5143
  case 1 /* DC_al_Coda */:
5341
5144
  case 0 /* DC_al_Fine */:
@@ -5343,37 +5146,53 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5343
5146
  case 2 /* DS_al_Fine */: {
5344
5147
  let anchor2 = this.barLineRight;
5345
5148
  let text = getNavigationString(navigation);
5346
- this.addLayoutObject(new ObjText(anchor2, text, 1, 1), 2 /* Navigation */, 0 /* AboveStaff */);
5347
- this.addNavigation(9 /* EndRepeat */);
5149
+ addLayoutObjectProps = {
5150
+ createObj: () => new ObjText(anchor2, text, 1, 1),
5151
+ layoutGroupId: 2 /* Navigation */,
5152
+ defaultVerticalPos: 0 /* Above */
5153
+ };
5154
+ this.addNavigation(staffTabOrGroup, 9 /* EndRepeat */);
5348
5155
  this.endSong();
5349
5156
  break;
5350
5157
  }
5351
5158
  case 7 /* Fine */: {
5352
5159
  let anchor2 = this.barLineRight;
5353
5160
  let text = getNavigationString(navigation);
5354
- this.addLayoutObject(new ObjText(anchor2, text, 1, 1), 2 /* Navigation */, 0 /* AboveStaff */);
5161
+ addLayoutObjectProps = {
5162
+ createObj: () => new ObjText(anchor2, text, 1, 1),
5163
+ layoutGroupId: 2 /* Navigation */,
5164
+ defaultVerticalPos: 0 /* Above */
5165
+ };
5355
5166
  break;
5356
5167
  }
5357
5168
  case 6 /* Segno */:
5358
5169
  case 4 /* Coda */: {
5359
5170
  let anchor2 = this.barLineLeft;
5360
5171
  let text = getNavigationString(navigation);
5361
- this.addLayoutObject(new ObjSpecialText(anchor2, text), 2 /* Navigation */, 0 /* AboveStaff */);
5172
+ addLayoutObjectProps = {
5173
+ createObj: () => new ObjSpecialText(anchor2, text),
5174
+ layoutGroupId: 2 /* Navigation */,
5175
+ defaultVerticalPos: 0 /* Above */
5176
+ };
5362
5177
  break;
5363
5178
  }
5364
5179
  case 5 /* toCoda */: {
5365
5180
  let anchor2 = this.barLineRight;
5366
5181
  let text = getNavigationString(navigation);
5367
- this.addLayoutObject(new ObjSpecialText(anchor2, text), 2 /* Navigation */, 0 /* AboveStaff */);
5182
+ addLayoutObjectProps = {
5183
+ createObj: () => new ObjSpecialText(anchor2, text),
5184
+ layoutGroupId: 2 /* Navigation */,
5185
+ defaultVerticalPos: 0 /* Above */
5186
+ };
5368
5187
  break;
5369
5188
  }
5370
5189
  case 9 /* EndRepeat */:
5371
5190
  if (args.length === 0) {
5372
5191
  this.endRepeatPlayCount = 2;
5373
- } else if (import_ts_utils_lib9.Utils.Is.isIntegerGte(args[0], 2)) {
5192
+ } else if (import_ts_utils_lib8.Utils.Is.isIntegerGte(args[0], 2)) {
5374
5193
  this.endRepeatPlayCount = args[0];
5375
5194
  } else {
5376
- throw new import_core14.MusicError(import_core14.MusicErrorType.Score, "Invalid end repeat play count (should be 2 or greater integer): " + args[0]);
5195
+ throw new import_core13.MusicError(import_core13.MusicErrorType.Score, "Invalid end repeat play count (should be 2 or greater integer): " + args[0]);
5377
5196
  }
5378
5197
  if (this.endRepeatPlayCount !== 2) {
5379
5198
  let textProps = {
@@ -5384,6 +5203,11 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5384
5203
  }
5385
5204
  break;
5386
5205
  }
5206
+ if (addLayoutObjectProps) {
5207
+ this.forEachStaffGroup(staffTabOrGroup, addLayoutObjectProps.defaultVerticalPos, (line, vpos) => {
5208
+ this.addLayoutObject(addLayoutObjectProps.createObj(), line, addLayoutObjectProps.layoutGroupId, vpos);
5209
+ });
5210
+ }
5387
5211
  this.navigationSet.add(navigation);
5388
5212
  this.disableExtension();
5389
5213
  }
@@ -5399,70 +5223,125 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5399
5223
  addConnective(connective, ...args) {
5400
5224
  let anchor = this.lastAddedRhythmSymbol;
5401
5225
  if (!(anchor instanceof ObjNoteGroup)) {
5402
- throw new import_core14.MusicError(import_core14.MusicErrorType.Score, "Connective can be added to note group only.");
5226
+ throw new import_core13.MusicError(import_core13.MusicErrorType.Score, "Connective can be added to note group only.");
5403
5227
  }
5404
5228
  if (connective === 0 /* Tie */) {
5405
- let tieSpan = import_ts_utils_lib9.Utils.Is.isInteger(args[0]) || import_ts_utils_lib9.Utils.Is.isEnumValue(args[0], TieType) ? args[0] : 2;
5406
- let noteAnchor = import_ts_utils_lib9.Utils.Is.isEnumValue(args[1], NoteAnchor) ? args[1] : 0 /* Auto */;
5229
+ let tieSpan = import_ts_utils_lib8.Utils.Is.isInteger(args[0]) || import_ts_utils_lib8.Utils.Is.isEnumValue(args[0], TieType) ? args[0] : 2;
5230
+ let noteAnchor = import_ts_utils_lib8.Utils.Is.isEnumValue(args[1], NoteAnchor) ? args[1] : 0 /* Auto */;
5407
5231
  anchor.startConnective(new ConnectiveProps(0 /* Tie */, tieSpan, noteAnchor, anchor));
5408
5232
  } else if (connective === 1 /* Slur */) {
5409
- let slurSpan = import_ts_utils_lib9.Utils.Is.isInteger(args[0]) ? args[0] : 2;
5410
- let noteAnchor = import_ts_utils_lib9.Utils.Is.isEnumValue(args[1], NoteAnchor) ? args[1] : 0 /* Auto */;
5233
+ let slurSpan = import_ts_utils_lib8.Utils.Is.isInteger(args[0]) ? args[0] : 2;
5234
+ let noteAnchor = import_ts_utils_lib8.Utils.Is.isEnumValue(args[1], NoteAnchor) ? args[1] : 0 /* Auto */;
5411
5235
  anchor.startConnective(new ConnectiveProps(1 /* Slur */, slurSpan, noteAnchor, anchor));
5412
5236
  } else if (connective === 2 /* Slide */) {
5413
- let noteAnchor = import_ts_utils_lib9.Utils.Is.isEnumValue(args[0], NoteAnchor) ? args[0] : 0 /* Auto */;
5237
+ let noteAnchor = import_ts_utils_lib8.Utils.Is.isEnumValue(args[0], NoteAnchor) ? args[0] : 0 /* Auto */;
5414
5238
  anchor.startConnective(new ConnectiveProps(2 /* Slide */, 2, noteAnchor, anchor));
5415
5239
  }
5416
5240
  }
5417
- addLabel(label, text) {
5241
+ forEachStaffGroup(staffTabOrGroup, defaultVerticalPos, add) {
5242
+ const lines = this.row.getNotationLines();
5243
+ const performAdd = (lineId, vpos, depth) => {
5244
+ if (depth >= 5) {
5245
+ return;
5246
+ }
5247
+ let success = false;
5248
+ if (typeof lineId === "number") {
5249
+ if (lines[lineId]) {
5250
+ add(lines[lineId], vpos);
5251
+ success = true;
5252
+ }
5253
+ } else if (typeof lineId === "string" && lineId.length > 0) {
5254
+ lines.filter((l) => l.name === lineId).forEach((line) => {
5255
+ add(line, vpos);
5256
+ success = true;
5257
+ });
5258
+ }
5259
+ if (typeof lineId === "string" && !success) {
5260
+ let grp = this.doc.getStaffGroup(lineId);
5261
+ if (grp) {
5262
+ (import_ts_utils_lib8.Utils.Is.isArray(grp.staffsTabsAndGroups) ? grp.staffsTabsAndGroups : [grp.staffsTabsAndGroups]).forEach((lineId2) => {
5263
+ switch (grp.verticalPosition) {
5264
+ case 0 /* Above */:
5265
+ performAdd(lineId2, 0 /* Above */, depth + 1);
5266
+ break;
5267
+ case 1 /* Below */:
5268
+ performAdd(lineId2, 1 /* Below */, depth + 1);
5269
+ break;
5270
+ case 2 /* Both */:
5271
+ performAdd(lineId2, 0 /* Above */, depth + 1);
5272
+ performAdd(lineId2, 1 /* Below */, depth + 1);
5273
+ break;
5274
+ case 3 /* Auto */:
5275
+ performAdd(lineId2, defaultVerticalPos, depth + 1);
5276
+ break;
5277
+ }
5278
+ });
5279
+ }
5280
+ }
5281
+ };
5282
+ if (staffTabOrGroup === void 0) {
5283
+ 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()) {
5284
+ performAdd(defaultVerticalPos === 1 /* Below */ ? 1 : 0, defaultVerticalPos, 0);
5285
+ } else {
5286
+ performAdd(0, defaultVerticalPos, 0);
5287
+ }
5288
+ } else {
5289
+ performAdd(staffTabOrGroup, defaultVerticalPos, 0);
5290
+ }
5291
+ }
5292
+ addLabel(staffTabOrGroup, label, text) {
5418
5293
  let anchor = this.lastAddedRhythmColumn;
5419
5294
  if (!anchor) {
5420
- throw new import_core14.MusicError(import_core14.MusicErrorType.Score, "Cannot add label because anchor is undefined.");
5295
+ throw new import_core13.MusicError(import_core13.MusicErrorType.Score, "Cannot add label because anchor is undefined.");
5421
5296
  } else if (text.length === 0) {
5422
- throw new import_core14.MusicError(import_core14.MusicErrorType.Score, "Cannot add label because label text is empty.");
5297
+ throw new import_core13.MusicError(import_core13.MusicErrorType.Score, "Cannot add label because label text is empty.");
5423
5298
  }
5424
5299
  let textProps = { text };
5425
5300
  let layoutGroupId;
5426
- let verticalPos;
5301
+ let defaultVerticalPos;
5427
5302
  switch (label) {
5428
5303
  case 0 /* Note */:
5429
5304
  layoutGroupId = 1 /* NoteLabel */;
5430
- verticalPos = 1 /* BelowStaff */;
5305
+ defaultVerticalPos = 1 /* Below */;
5431
5306
  break;
5432
5307
  case 1 /* Chord */:
5433
5308
  layoutGroupId = 6 /* ChordLabel */;
5434
- verticalPos = 0 /* AboveStaff */;
5309
+ defaultVerticalPos = 0 /* Above */;
5435
5310
  break;
5436
5311
  }
5437
- let textObj = new ObjText(anchor, textProps, 0.5, 1);
5438
- this.addLayoutObject(textObj, layoutGroupId, verticalPos);
5439
- this.enableExtension(textObj);
5312
+ this.forEachStaffGroup(staffTabOrGroup, defaultVerticalPos, (line, vpos) => {
5313
+ let textObj = new ObjText(anchor, textProps, 0.5, 1);
5314
+ this.addLayoutObject(textObj, line, layoutGroupId, vpos);
5315
+ this.enableExtension(textObj);
5316
+ });
5440
5317
  }
5441
- addAnnotation(annotation, text) {
5318
+ addAnnotation(staffTabOrGroup, annotation, text) {
5442
5319
  let anchor = this.lastAddedRhythmColumn;
5443
5320
  if (!anchor) {
5444
- throw new import_core14.MusicError(import_core14.MusicErrorType.Score, "Cannot add annotation because anchor is undefined.");
5321
+ throw new import_core13.MusicError(import_core13.MusicErrorType.Score, "Cannot add annotation because anchor is undefined.");
5445
5322
  } else if (text.length === 0) {
5446
- throw new import_core14.MusicError(import_core14.MusicErrorType.Score, "Cannot add annotation because annotation text is empty.");
5323
+ throw new import_core13.MusicError(import_core13.MusicErrorType.Score, "Cannot add annotation because annotation text is empty.");
5447
5324
  }
5448
5325
  let textProps = { text };
5449
5326
  let layoutGroupId;
5450
- let verticalPos;
5327
+ let defaultVerticalPos;
5451
5328
  switch (annotation) {
5452
5329
  case 0 /* Dynamics */:
5453
5330
  layoutGroupId = 5 /* DynamicsAnnotation */;
5454
- verticalPos = 0 /* AboveStaff */;
5331
+ defaultVerticalPos = 0 /* Above */;
5455
5332
  textProps.italic = true;
5456
5333
  break;
5457
5334
  case 1 /* Tempo */:
5458
5335
  layoutGroupId = 4 /* TempoAnnotation */;
5459
- verticalPos = 0 /* AboveStaff */;
5336
+ defaultVerticalPos = 0 /* Above */;
5460
5337
  textProps.italic = true;
5461
5338
  break;
5462
5339
  }
5463
- let textObj = new ObjText(anchor, textProps, 0.5, 1);
5464
- this.addLayoutObject(textObj, layoutGroupId, verticalPos);
5465
- this.enableExtension(textObj);
5340
+ this.forEachStaffGroup(staffTabOrGroup, defaultVerticalPos, (line, vpos) => {
5341
+ let textObj = new ObjText(anchor, textProps, 0.5, 1);
5342
+ this.addLayoutObject(textObj, line, layoutGroupId, vpos);
5343
+ this.enableExtension(textObj);
5344
+ });
5466
5345
  }
5467
5346
  endSong() {
5468
5347
  this.isEndSong = true;
@@ -5484,27 +5363,29 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5484
5363
  this.doc.requestNewRow();
5485
5364
  this.disableExtension();
5486
5365
  }
5487
- enableExtension(musicObj) {
5488
- this.addExtensionToMusicObject = musicObj;
5366
+ enableExtension(musicObject) {
5367
+ this.addExtensionToMusicObjects.push(musicObject);
5489
5368
  }
5490
5369
  disableExtension() {
5491
- this.addExtensionToMusicObject = void 0;
5370
+ this.addExtensionToMusicObjects = [];
5492
5371
  }
5493
5372
  addExtension(extensionLength, extensionVisible) {
5494
- let musicObj = this.addExtensionToMusicObject;
5495
- let anchor = musicObj == null ? void 0 : musicObj.getParent();
5496
- if (musicObj instanceof ObjText && anchor instanceof ObjRhythmColumn) {
5497
- let lineStyle = "dashed";
5498
- let linePos = "bottom";
5499
- let extension = new Extension(musicObj, anchor, extensionLength, extensionVisible, lineStyle, linePos);
5500
- musicObj.setLink(extension);
5501
- this.disableExtension();
5502
- this.requestLayout();
5503
- } else if (musicObj === void 0) {
5504
- throw new import_core14.MusicError(import_core14.MusicErrorType.Score, "Cannot add extension because music object to attach it to is undefined.");
5505
- } else {
5506
- throw new import_core14.MusicError(import_core14.MusicErrorType.Score, "Cannot add extension becaue no compatible music object to attach it to.");
5373
+ this.addExtensionToMusicObjects.forEach((musicObj) => {
5374
+ let anchor = musicObj.getParent();
5375
+ if (musicObj instanceof ObjText && anchor instanceof ObjRhythmColumn) {
5376
+ let lineStyle = "dashed";
5377
+ let linePos = "bottom";
5378
+ let extension = new Extension(musicObj, anchor, extensionLength, extensionVisible, lineStyle, linePos);
5379
+ musicObj.setLink(extension);
5380
+ } else {
5381
+ throw new import_core13.MusicError(import_core13.MusicErrorType.Score, "Cannot add extension becaue no compatible music object to attach it to.");
5382
+ }
5383
+ });
5384
+ if (this.addExtensionToMusicObjects.length === 0) {
5385
+ throw new import_core13.MusicError(import_core13.MusicErrorType.Score, "Cannot add extension because music object to attach it to is undefined.");
5507
5386
  }
5387
+ this.disableExtension();
5388
+ this.requestLayout();
5508
5389
  }
5509
5390
  addRhythmSymbol(voiceId, symbol) {
5510
5391
  let { col } = symbol;
@@ -5516,7 +5397,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5516
5397
  this.lastAddedRhythmSymbol = symbol;
5517
5398
  }
5518
5399
  addNoteGroup(voiceId, notes, noteLength, options) {
5519
- let notes2 = notes.map((note) => typeof note === "string" ? import_theory10.Note.getNote(note) : note);
5400
+ let notes2 = notes.map((note) => typeof note === "string" ? import_theory9.Note.getNote(note) : note);
5520
5401
  let col = this.getRhythmColumn(voiceId);
5521
5402
  this.addRhythmSymbol(voiceId, new ObjNoteGroup(col, voiceId, notes2, noteLength, options));
5522
5403
  }
@@ -5548,7 +5429,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5548
5429
  return col2;
5549
5430
  }
5550
5431
  }
5551
- throw new import_core14.MusicError(import_core14.MusicErrorType.Score, "Error in rhythm column. Should never get here.");
5432
+ throw new import_core13.MusicError(import_core13.MusicErrorType.Score, "Error in rhythm column. Should never get here.");
5552
5433
  }
5553
5434
  getMeasureTicks() {
5554
5435
  return this.getTimeSignature().measureTicks;
@@ -5600,11 +5481,15 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5600
5481
  getStaffLineRight() {
5601
5482
  return this.barLineRight.getRect().centerX;
5602
5483
  }
5603
- getStaticObjects() {
5604
- return [
5605
- ...this.getColumns(),
5606
- ...this.layoutObjects.filter((layoutObj) => layoutObj.isPositionResolved()).map((layoutObj) => layoutObj.musicObj)
5607
- ];
5484
+ getStaticObjects(line) {
5485
+ let staticObjects = this.staticObjectsCache.get(line);
5486
+ if (!staticObjects) {
5487
+ staticObjects = [];
5488
+ this.getColumns().forEach((col) => col.getStaticObjects(line).forEach((obj) => staticObjects == null ? void 0 : staticObjects.push(obj)));
5489
+ this.staticObjectsCache.set(line, staticObjects);
5490
+ }
5491
+ let layoutObjects = this.layoutObjects.filter((layoutObj) => layoutObj.line === line && layoutObj.isPositionResolved()).map((layoutObj) => layoutObj.musicObj);
5492
+ return layoutObjects.length > 0 ? [...staticObjects, ...layoutObjects] : staticObjects;
5608
5493
  }
5609
5494
  removeLayoutObjects(musicObj) {
5610
5495
  this.layoutObjects = this.layoutObjects.filter((layoutObj) => {
@@ -5632,16 +5517,22 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5632
5517
  }
5633
5518
  createExtensions() {
5634
5519
  this.layoutObjects.forEach((layoutObj) => {
5635
- if (layoutObj.musicObj.getLink() instanceof Extension) {
5636
- let extension = layoutObj.musicObj.getLink();
5637
- if (extension.getHead() === layoutObj.musicObj) {
5638
- extension.getTails().forEach((musicObj) => layoutObj.measure.removeLayoutObjects(musicObj));
5520
+ var _a;
5521
+ let { musicObj, measure, layoutGroupId, verticalPos, line } = layoutObj;
5522
+ if (musicObj.getLink() instanceof Extension) {
5523
+ let extension = musicObj.getLink();
5524
+ if (extension.getHead() === musicObj) {
5525
+ extension.getTails().forEach((musicObj2) => measure.removeLayoutObjects(musicObj2));
5639
5526
  let { startColumn, endColumn } = extension.getExtensionRangeInfo();
5640
5527
  if (extension.isVisible() && startColumn !== endColumn) {
5641
5528
  for (let m = startColumn.measure; m !== void 0; m = m === endColumn.measure ? void 0 : m.getNextMeasure()) {
5642
5529
  let leftObj = m === startColumn.measure ? extension.getHead() : m.getBarLineLeft();
5643
5530
  let rightObj = m === endColumn.measure ? endColumn : m.getBarLineRight();
5644
- m.addLayoutObject(new ObjExtensionLine(m, extension, leftObj, rightObj), layoutObj.layoutGroupId, layoutObj.verticalPos);
5531
+ const lines = m.row.getNotationLines();
5532
+ let line2 = (_a = lines.find((l) => l.name !== "" && l.name === line.name)) != null ? _a : lines[line.id];
5533
+ if (line2) {
5534
+ m.addLayoutObject(new ObjExtensionLine(m, extension, leftObj, rightObj), line2, layoutGroupId, verticalPos);
5535
+ }
5645
5536
  }
5646
5537
  }
5647
5538
  }
@@ -5748,12 +5639,12 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5748
5639
  let consumedTicks = this.getConsumedTicks(voiceId);
5749
5640
  let remainingTicks = measureTicks - consumedTicks;
5750
5641
  let rests = [];
5751
- let noteLengthValues = import_ts_utils_lib9.Utils.Enum.getEnumValues(import_theory10.NoteLength);
5642
+ let noteLengthValues = import_ts_utils_lib8.Utils.Enum.getEnumValues(import_theory9.NoteLength);
5752
5643
  while (remainingTicks > 0) {
5753
5644
  noteLengthValues.forEach((restLength) => {
5754
- let restValue = new import_theory10.RhythmProps(restLength, false);
5645
+ let restValue = new import_theory9.RhythmProps(restLength, false);
5755
5646
  if (restValue.canDot()) {
5756
- let dottedRestValue = new import_theory10.RhythmProps(restLength, true);
5647
+ let dottedRestValue = new import_theory9.RhythmProps(restLength, true);
5757
5648
  while (dottedRestValue.ticks <= remainingTicks) {
5758
5649
  rests.push(dottedRestValue);
5759
5650
  remainingTicks -= dottedRestValue.ticks;
@@ -5778,6 +5669,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5778
5669
  if (!this.needLayout) {
5779
5670
  return;
5780
5671
  }
5672
+ this.staticObjectsCache.clear();
5781
5673
  this.requestRectUpdate();
5782
5674
  let { unitSize } = renderer;
5783
5675
  this.postMeasureBreakWidth = this.hasPostMeasureBreak() ? DocumentSettings.PostMeasureBreakWidth * unitSize : 0;
@@ -5809,7 +5701,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5809
5701
  if (this === this.row.getFirstMeasure()) {
5810
5702
  this.row.getTabs().forEach((tab) => {
5811
5703
  for (let stringId = 0; stringId < 6; stringId++) {
5812
- let note = tab.getTuningStrings()[stringId].format(import_theory10.PitchNotation.Helmholtz, import_theory10.SymbolSet.Unicode);
5704
+ let note = tab.getTuningStrings()[stringId].format(import_theory9.PitchNotation.Helmholtz, import_theory9.SymbolSet.Unicode);
5813
5705
  let obj = new ObjText(this, { text: note, scale: 0.8 }, 1, 0.5);
5814
5706
  obj.layout(renderer);
5815
5707
  obj.offset(this.tabStringNotesWidth * 0.8, tab.getStringY(stringId));
@@ -5825,6 +5717,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5825
5717
  if (this.endRepeatPlayCountText) {
5826
5718
  this.endRepeatPlayCountText.layout(renderer);
5827
5719
  }
5720
+ this.layoutObjects.forEach((layoutObj) => layoutObj.layout(renderer));
5828
5721
  let padding = renderer.unitSize;
5829
5722
  this.leftSolidAreaWidth = this.tabStringNotesWidth + Math.max(0, ...this.signatures.map((signature) => signature.getRect().width)) + this.barLineLeft.getRect().width + padding;
5830
5723
  this.rightSolidAreaWidth = padding + this.barLineRight.getRect().width;
@@ -5856,7 +5749,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5856
5749
  let columnsAreaLeft = this.rect.left + this.leftSolidAreaWidth;
5857
5750
  let columnsAreaRight = this.rect.right - this.rightSolidAreaWidth;
5858
5751
  let columnsAreaWidth = columnsAreaRight - columnsAreaLeft;
5859
- let columnsWidth = import_ts_utils_lib9.Utils.Math.sum(this.columns.map((col) => col.getRect().width));
5752
+ let columnsWidth = import_ts_utils_lib8.Utils.Math.sum(this.columns.map((col) => col.getRect().width));
5860
5753
  let columnScale = columnsAreaWidth / columnsWidth;
5861
5754
  let columnLeft = columnsAreaLeft;
5862
5755
  this.columns.forEach((col) => {
@@ -5901,7 +5794,8 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5901
5794
  ...this.columns.filter((col) => !col.isEmpty()).map((col) => col.getRect().top),
5902
5795
  this.barLineRight.getRect().top,
5903
5796
  ...this.connectives.map((c) => c.getRect().top),
5904
- ...this.beamGroups.filter((b) => !b.isEmpty()).map((b) => b.getRect().top)
5797
+ ...this.beamGroups.filter((b) => !b.isEmpty()).map((b) => b.getRect().top),
5798
+ ...this.layoutObjects.filter((o) => o.isPositionResolved()).map((o) => o.musicObj.getRect().top)
5905
5799
  );
5906
5800
  this.rect.bottom = Math.max(
5907
5801
  ...this.signatures.map((s) => s.getRect().bottom),
@@ -5910,12 +5804,20 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5910
5804
  ...this.columns.filter((col) => !col.isEmpty()).map((col) => col.getRect().bottom),
5911
5805
  this.barLineRight.getRect().bottom,
5912
5806
  ...this.connectives.map((c) => c.getRect().bottom),
5913
- ...this.beamGroups.filter((b) => !b.isEmpty()).map((b) => b.getRect().bottom)
5807
+ ...this.beamGroups.filter((b) => !b.isEmpty()).map((b) => b.getRect().bottom),
5808
+ ...this.layoutObjects.filter((o) => o.isPositionResolved()).map((o) => o.musicObj.getRect().bottom)
5914
5809
  );
5810
+ if (this === this.row.getLastMeasure()) {
5811
+ this.rect.right = Math.max(
5812
+ this.rect.right,
5813
+ ...this.layoutObjects.filter((o) => o.isPositionResolved() && o.musicObj instanceof ObjFermata).map((o) => o.musicObj.getRect().right)
5814
+ );
5815
+ }
5915
5816
  this.row.getNotationLines().forEach((line) => {
5916
5817
  this.rect.top = Math.min(this.rect.top, line.calcTop());
5917
5818
  this.rect.bottom = Math.max(this.rect.bottom, line.calcBottom());
5918
5819
  });
5820
+ this.row.requestRectUpdate();
5919
5821
  }
5920
5822
  offset(dx, dy) {
5921
5823
  this.signatures.forEach((signature) => signature.offset(dx, 0));
@@ -5928,7 +5830,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5928
5830
  }
5929
5831
  this.connectives.forEach((connective) => connective.offset(dx, 0));
5930
5832
  this.beamGroups.forEach((beam) => beam.offset(dx, dy));
5931
- this.layoutObjects.forEach((layoutObj) => layoutObj.musicObj.offset(dx, dy));
5833
+ this.layoutObjects.forEach((layoutObj) => layoutObj.offset(dx, 0));
5932
5834
  this.rect.offsetInPlace(dx, dy);
5933
5835
  this.requestRectUpdate();
5934
5836
  }
@@ -5943,7 +5845,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5943
5845
  for (let p = line.bottomLineDiatonicId; p <= line.topLineDiatonicId; p += 2) {
5944
5846
  drawLine(line.getDiatonicIdY(p));
5945
5847
  }
5946
- } else {
5848
+ } else if (line instanceof ObjTab) {
5947
5849
  for (let stringId = 0; stringId < 6; stringId++) {
5948
5850
  drawLine(line.getStringY(stringId));
5949
5851
  }
@@ -5966,7 +5868,7 @@ __publicField(_ObjMeasure, "MinFlexContentWidth", 10);
5966
5868
  var ObjMeasure2 = _ObjMeasure;
5967
5869
 
5968
5870
  // src/score/engine/layout-object.ts
5969
- var import_core15 = require("@tspro/web-music-score/core");
5871
+ var import_core14 = require("@tspro/web-music-score/core");
5970
5872
  var WidenColumnList = [1 /* NoteLabel */, 6 /* ChordLabel */];
5971
5873
  var RowAlignList = [2 /* Navigation */, 3 /* Ending */, 4 /* TempoAnnotation */, 5 /* DynamicsAnnotation */, 6 /* ChordLabel */];
5972
5874
  function requireParentMeasure(p) {
@@ -5976,11 +5878,19 @@ function requireParentMeasure(p) {
5976
5878
  }
5977
5879
  p = p.getParent();
5978
5880
  }
5979
- throw new import_core15.MusicError(import_core15.MusicErrorType.Score, "Parent measure is required but not found!");
5881
+ throw new import_core14.MusicError(import_core14.MusicErrorType.Score, "Parent measure is required but not found!");
5980
5882
  }
5883
+ var StaffGroup = class {
5884
+ constructor(groupName, staffsTabsAndGroups, verticalPosition) {
5885
+ this.groupName = groupName;
5886
+ this.staffsTabsAndGroups = staffsTabsAndGroups;
5887
+ this.verticalPosition = verticalPosition;
5888
+ }
5889
+ };
5981
5890
  var LayoutObjectWrapper = class {
5982
- constructor(musicObj, layoutGroupId, verticalPos) {
5891
+ constructor(musicObj, line, layoutGroupId, verticalPos) {
5983
5892
  this.musicObj = musicObj;
5893
+ this.line = line;
5984
5894
  this.layoutGroupId = layoutGroupId;
5985
5895
  this.verticalPos = verticalPos;
5986
5896
  __publicField(this, "anchor");
@@ -5988,15 +5898,15 @@ var LayoutObjectWrapper = class {
5988
5898
  __publicField(this, "row");
5989
5899
  __publicField(this, "layoutGroup");
5990
5900
  __publicField(this, "positionResolved", true);
5991
- this.measure = requireParentMeasure(musicObj);
5901
+ this.measure = requireParentMeasure(this.musicObj);
5992
5902
  this.row = this.measure.row;
5993
5903
  let anchor = this.musicObj.getParent();
5994
5904
  if (!anchor) {
5995
- throw new import_core15.MusicError(import_core15.MusicErrorType.Score, "Parent music object is required as an anchor.");
5905
+ throw new import_core14.MusicError(import_core14.MusicErrorType.Score, "Parent music object is required as an anchor.");
5996
5906
  }
5997
5907
  this.anchor = anchor;
5998
5908
  this.anchor.addAnchoredLayoutObject(this);
5999
- this.layoutGroup = this.measure.doc.getLayoutGroup(layoutGroupId);
5909
+ this.layoutGroup = this.line.getLayoutGroup(layoutGroupId);
6000
5910
  this.layoutGroup.add(this);
6001
5911
  }
6002
5912
  clearPositionResolved() {
@@ -6009,20 +5919,19 @@ var LayoutObjectWrapper = class {
6009
5919
  return this.positionResolved;
6010
5920
  }
6011
5921
  resolveClosestToStaffY(renderer) {
6012
- let { musicObj, measure, verticalPos } = this;
6013
- let { row } = measure;
6014
- let staffTop = row.hasStaff ? row.getTopStaff().getTopLineY() : row.getRect().centerY;
6015
- let staffBottom = row.hasStaff ? row.getBottomStaff().getBottomLineY() : row.getRect().centerY;
6016
- let staffPadding = renderer.unitSize * 2;
6017
- let y = verticalPos === 1 /* BelowStaff */ ? staffBottom + staffPadding + musicObj.getRect().toph : staffTop - staffPadding - musicObj.getRect().bottomh;
6018
- let staticObjects = measure.getStaticObjects();
5922
+ let { musicObj, measure, verticalPos, line } = this;
5923
+ let lineTop = line.getTopLineY();
5924
+ let lineBottom = line.getBottomLineY();
5925
+ let linePadding = renderer.unitSize * 2;
5926
+ let y = verticalPos === 1 /* Below */ ? lineBottom + linePadding + musicObj.getRect().toph : lineTop - linePadding - musicObj.getRect().bottomh;
5927
+ let staticObjects = measure.getStaticObjects(line);
6019
5928
  let objShapeRects = musicObj.getShapeRects();
6020
5929
  staticObjects.forEach((staticObj) => {
6021
5930
  let staticShapeRects = staticObj.getShapeRects();
6022
5931
  objShapeRects.forEach((objR) => {
6023
5932
  staticShapeRects.forEach((staticR) => {
6024
5933
  if (DivRect.overlapX(objR, staticR)) {
6025
- y = verticalPos === 1 /* BelowStaff */ ? Math.max(y, staticR.bottom + objR.toph + objR.centerY) : Math.min(y, staticR.top - objR.bottomh - objR.centerY);
5934
+ y = verticalPos === 1 /* Below */ ? Math.max(y, staticR.bottom + objR.toph + objR.centerY) : Math.min(y, staticR.top - objR.bottomh - objR.centerY);
6026
5935
  }
6027
5936
  });
6028
5937
  });
@@ -6036,6 +5945,15 @@ var LayoutObjectWrapper = class {
6036
5945
  return void 0;
6037
5946
  }
6038
5947
  }
5948
+ layout(renderer) {
5949
+ this.line.addObject(this);
5950
+ }
5951
+ offset(dx, dy) {
5952
+ this.musicObj.offset(dx, dy);
5953
+ }
5954
+ getRect() {
5955
+ return this.musicObj.getRect();
5956
+ }
6039
5957
  };
6040
5958
  var LayoutGroup = class {
6041
5959
  constructor(layoutGroupId) {
@@ -6043,8 +5961,8 @@ var LayoutGroup = class {
6043
5961
  __publicField(this, "layoutObjectTable", []);
6044
5962
  __publicField(this, "rowAlign");
6045
5963
  __publicField(this, "widensColumn");
6046
- this.layoutObjectTable[0 /* AboveStaff */] = [];
6047
- this.layoutObjectTable[1 /* BelowStaff */] = [];
5964
+ this.layoutObjectTable[0 /* Above */] = [];
5965
+ this.layoutObjectTable[1 /* Below */] = [];
6048
5966
  this.rowAlign = RowAlignList.indexOf(layoutGroupId) >= 0;
6049
5967
  this.widensColumn = WidenColumnList.indexOf(layoutGroupId) >= 0;
6050
5968
  }
@@ -6072,6 +5990,333 @@ var LayoutGroup = class {
6072
5990
  }
6073
5991
  };
6074
5992
 
5993
+ // src/score/engine/obj-staff-and-tab.ts
5994
+ var ObjNotationLine4 = class extends MusicObject {
5995
+ constructor(parent) {
5996
+ super(parent);
5997
+ __publicField(this, "objects", []);
5998
+ __publicField(this, "layoutGroups", []);
5999
+ }
6000
+ addObject(o) {
6001
+ this.objects.push(o);
6002
+ }
6003
+ removeObjects() {
6004
+ this.objects.length = 0;
6005
+ }
6006
+ getLayoutGroup(lauoutGroupId) {
6007
+ let layoutGroup = this.layoutGroups[lauoutGroupId];
6008
+ if (!layoutGroup) {
6009
+ layoutGroup = this.layoutGroups[lauoutGroupId] = new LayoutGroup(lauoutGroupId);
6010
+ }
6011
+ return layoutGroup;
6012
+ }
6013
+ resetLayoutGroups(renderer) {
6014
+ this.layoutGroups.forEach((layoutGroup) => {
6015
+ if (layoutGroup) {
6016
+ layoutGroup.clearPositionAndLayout(renderer);
6017
+ }
6018
+ });
6019
+ }
6020
+ layoutLayoutGroups(renderer) {
6021
+ this.layoutGroups.forEach((layoutGroup) => {
6022
+ if (layoutGroup) {
6023
+ this.layoutLayoutGroup(renderer, layoutGroup, 0 /* Above */);
6024
+ this.layoutLayoutGroup(renderer, layoutGroup, 1 /* Below */);
6025
+ }
6026
+ });
6027
+ }
6028
+ setObjectY(layoutObj, y) {
6029
+ if (y === void 0) {
6030
+ return;
6031
+ }
6032
+ layoutObj.offset(0, y - layoutObj.getRect().centerY);
6033
+ layoutObj.setPositionResolved();
6034
+ }
6035
+ alignObjectsY(renderer, layoutObjArr) {
6036
+ layoutObjArr = layoutObjArr.filter((layoutObj) => !layoutObj.isPositionResolved());
6037
+ let rowY;
6038
+ layoutObjArr.forEach((layoutObj) => {
6039
+ let y = layoutObj.resolveClosestToStaffY(renderer);
6040
+ rowY = layoutObj.verticalPos === 1 /* Below */ ? Math.max(y, rowY != null ? rowY : y) : Math.min(y, rowY != null ? rowY : y);
6041
+ });
6042
+ layoutObjArr.forEach((layoutObj) => this.setObjectY(layoutObj, rowY));
6043
+ }
6044
+ layoutLayoutGroup(renderer, layoutGroup, verticalPos) {
6045
+ let rowLayoutObjs = layoutGroup.getLayoutObjects(verticalPos).filter((layoutObj) => !layoutObj.isPositionResolved());
6046
+ rowLayoutObjs.forEach((layoutObj) => {
6047
+ let { musicObj, anchor } = layoutObj;
6048
+ if (musicObj instanceof ObjEnding || musicObj instanceof ObjExtensionLine) {
6049
+ musicObj.layoutFitToMeasure(renderer);
6050
+ } else {
6051
+ musicObj.offset(anchor.getRect().centerX - musicObj.getRect().centerX, 0);
6052
+ }
6053
+ });
6054
+ if (layoutGroup.rowAlign) {
6055
+ this.alignObjectsY(renderer, rowLayoutObjs);
6056
+ } else {
6057
+ rowLayoutObjs.forEach((layoutObj) => {
6058
+ let link = layoutObj.musicObj.getLink();
6059
+ if (link && link.getHead() === layoutObj.musicObj) {
6060
+ let objectParts = [link.getHead(), ...link.getTails()];
6061
+ let layoutObjs = rowLayoutObjs.filter((layoutObj2) => objectParts.some((o) => o === layoutObj2.musicObj));
6062
+ this.alignObjectsY(renderer, layoutObjs);
6063
+ } else {
6064
+ this.alignObjectsY(renderer, [layoutObj]);
6065
+ }
6066
+ });
6067
+ }
6068
+ }
6069
+ };
6070
+ var ObjStaff = class extends ObjNotationLine4 {
6071
+ constructor(row, staffConfig, id) {
6072
+ super(row);
6073
+ this.row = row;
6074
+ this.staffConfig = staffConfig;
6075
+ this.id = id;
6076
+ __publicField(this, "clefImageAsset");
6077
+ __publicField(this, "clefLineDiatonicId");
6078
+ __publicField(this, "topLineDiatonicId");
6079
+ __publicField(this, "middleLineDiatonicId");
6080
+ __publicField(this, "bottomLineDiatonicId");
6081
+ __publicField(this, "minDiatonicId");
6082
+ __publicField(this, "maxDiatonicId");
6083
+ __publicField(this, "joinedGrandStaff");
6084
+ __publicField(this, "topLineY", 0);
6085
+ __publicField(this, "bottomLineY", 0);
6086
+ __publicField(this, "mi");
6087
+ const getDiatonicId = (noteName, isOctaveDown) => import_theory11.Note.getNote(noteName).diatonicId - (isOctaveDown ? 7 : 0);
6088
+ if (staffConfig.clef === "G" /* G */) {
6089
+ this.clefImageAsset = 0 /* TrebleClefPng */;
6090
+ this.clefLineDiatonicId = getDiatonicId("G4", staffConfig.isOctaveDown === true);
6091
+ this.middleLineDiatonicId = this.clefLineDiatonicId + 2;
6092
+ } else {
6093
+ this.clefImageAsset = 1 /* BassClefPng */;
6094
+ this.clefLineDiatonicId = getDiatonicId("F3", staffConfig.isOctaveDown === true);
6095
+ this.middleLineDiatonicId = this.clefLineDiatonicId - 2;
6096
+ }
6097
+ this.topLineDiatonicId = this.middleLineDiatonicId + 4;
6098
+ this.bottomLineDiatonicId = this.middleLineDiatonicId - 4;
6099
+ this.minDiatonicId = staffConfig.minNote !== void 0 ? Math.min(getDiatonicId(staffConfig.minNote, false), this.bottomLineDiatonicId) : void 0;
6100
+ this.maxDiatonicId = staffConfig.maxNote !== void 0 ? Math.max(getDiatonicId(staffConfig.maxNote, false), this.topLineDiatonicId) : void 0;
6101
+ this.mi = new MStaff(this);
6102
+ }
6103
+ getMusicInterface() {
6104
+ return this.mi;
6105
+ }
6106
+ get isOctaveDown() {
6107
+ return this.staffConfig.isOctaveDown === true;
6108
+ }
6109
+ get name() {
6110
+ var _a;
6111
+ return (_a = this.staffConfig.name) != null ? _a : "";
6112
+ }
6113
+ getTopLineY() {
6114
+ return this.topLineY;
6115
+ }
6116
+ getMiddleLineY() {
6117
+ return (this.topLineY + this.bottomLineY) / 2;
6118
+ }
6119
+ getBottomLineY() {
6120
+ return this.bottomLineY;
6121
+ }
6122
+ joinGrandStaff(staff) {
6123
+ if (staff !== this) {
6124
+ this.joinedGrandStaff = staff;
6125
+ }
6126
+ }
6127
+ getLineSpacing() {
6128
+ return (this.bottomLineY - this.topLineY) / 4;
6129
+ }
6130
+ getDiatonicSpacing() {
6131
+ return this.getLineSpacing() / 2;
6132
+ }
6133
+ containsDiatonicId(diatonicId) {
6134
+ import_theory11.Note.validateDiatonicId(diatonicId);
6135
+ return (this.minDiatonicId === void 0 || diatonicId >= this.minDiatonicId) && (this.maxDiatonicId === void 0 || diatonicId <= this.maxDiatonicId);
6136
+ }
6137
+ getDiatonicIdY(diatonicId) {
6138
+ if (this.containsDiatonicId(diatonicId)) {
6139
+ return this.bottomLineY + (this.bottomLineDiatonicId - diatonicId) * this.getDiatonicSpacing();
6140
+ } else if (this.joinedGrandStaff && this.joinedGrandStaff.containsDiatonicId(diatonicId)) {
6141
+ return this.joinedGrandStaff.getDiatonicIdY(diatonicId);
6142
+ } else {
6143
+ throw new import_core15.MusicError(import_core15.MusicErrorType.Score, "Staff does not contain diatonicId " + diatonicId);
6144
+ }
6145
+ }
6146
+ getActualStaff(diatonicId) {
6147
+ if (this.containsDiatonicId(diatonicId)) {
6148
+ return this;
6149
+ } else if (this.joinedGrandStaff && this.joinedGrandStaff.containsDiatonicId(diatonicId)) {
6150
+ return this.joinedGrandStaff;
6151
+ } else {
6152
+ throw new import_core15.MusicError(import_core15.MusicErrorType.Score, "Staff does not contain diatonicId " + diatonicId);
6153
+ }
6154
+ }
6155
+ getDiatonicIdAt(y) {
6156
+ let diatonicId = Math.round(this.bottomLineDiatonicId - (y - this.bottomLineY) / this.getDiatonicSpacing());
6157
+ return this.containsDiatonicId(diatonicId) ? diatonicId : void 0;
6158
+ }
6159
+ isLine(diatonicId) {
6160
+ return diatonicId % 2 === this.middleLineDiatonicId % 2;
6161
+ }
6162
+ isSpace(diatonicId) {
6163
+ return diatonicId % 2 !== this.middleLineDiatonicId % 2;
6164
+ }
6165
+ containsVoiceId(voiceId) {
6166
+ return !this.staffConfig.voiceIds || this.staffConfig.voiceIds.includes(voiceId);
6167
+ }
6168
+ isGrand() {
6169
+ return this.staffConfig.isGrand === true;
6170
+ }
6171
+ calcTop() {
6172
+ let top = this.topLineY;
6173
+ this.objects.forEach((o) => top = Math.min(top, o.getRect().top));
6174
+ if (this.maxDiatonicId !== void 0) {
6175
+ let y = this.getDiatonicIdY(this.maxDiatonicId);
6176
+ let y2 = this.getDiatonicIdY(this.maxDiatonicId - 1);
6177
+ top = Math.min(top, y - Math.abs(y2 - y) + 1);
6178
+ }
6179
+ return top;
6180
+ }
6181
+ calcBottom() {
6182
+ let bottom = this.bottomLineY;
6183
+ this.objects.forEach((o) => bottom = Math.max(bottom, o.getRect().bottom));
6184
+ if (this.minDiatonicId !== void 0) {
6185
+ let y = this.getDiatonicIdY(this.minDiatonicId);
6186
+ let y2 = this.getDiatonicIdY(this.minDiatonicId + 1);
6187
+ bottom = Math.max(bottom, y + Math.abs(y2 - y) - 1);
6188
+ }
6189
+ return bottom;
6190
+ }
6191
+ pick(x, y) {
6192
+ return [this];
6193
+ }
6194
+ layoutHeight(renderer) {
6195
+ let { unitSize } = renderer;
6196
+ let h = unitSize * DocumentSettings.StaffHeight;
6197
+ this.topLineY = -h / 2;
6198
+ this.bottomLineY = h / 2;
6199
+ this.rect = new DivRect(0, 0, this.topLineY, this.bottomLineY);
6200
+ }
6201
+ layoutWidth(renderer) {
6202
+ this.rect.left = this.row.getRect().left;
6203
+ this.rect.right = this.row.getRect().right;
6204
+ }
6205
+ offset(dx, dy) {
6206
+ this.topLineY += dy;
6207
+ this.bottomLineY += dy;
6208
+ this.objects.forEach((o) => {
6209
+ if (o.offsetInPlace) {
6210
+ o.offsetInPlace(0, dy);
6211
+ } else if (o.offset) {
6212
+ o.offset(0, dy);
6213
+ }
6214
+ });
6215
+ this.rect.offsetInPlace(dx, dy);
6216
+ }
6217
+ draw(renderer) {
6218
+ }
6219
+ };
6220
+ var ObjTab = class extends ObjNotationLine4 {
6221
+ constructor(row, tabConfig, id) {
6222
+ super(row);
6223
+ this.row = row;
6224
+ this.tabConfig = tabConfig;
6225
+ this.id = id;
6226
+ __publicField(this, "top", 0);
6227
+ __publicField(this, "bottom", 0);
6228
+ __publicField(this, "tuningName");
6229
+ __publicField(this, "tuningStrings");
6230
+ __publicField(this, "mi");
6231
+ if (import_ts_utils_lib9.Utils.Is.isArray(tabConfig.tuning)) {
6232
+ this.tuningName = void 0;
6233
+ this.tuningStrings = tabConfig.tuning.map((noteName) => import_theory11.Note.getNote(noteName)).reverse();
6234
+ } else if (typeof tabConfig.tuning === "string") {
6235
+ this.tuningName = (0, import_theory11.validateTuningName)(tabConfig.tuning);
6236
+ this.tuningStrings = (0, import_theory11.getTuningStrings)(this.tuningName);
6237
+ } else {
6238
+ this.tuningName = "Standard";
6239
+ this.tuningStrings = (0, import_theory11.getTuningStrings)(this.tuningName);
6240
+ }
6241
+ this.mi = new MTab(this);
6242
+ }
6243
+ getMusicInterface() {
6244
+ return this.mi;
6245
+ }
6246
+ get name() {
6247
+ var _a;
6248
+ return (_a = this.tabConfig.name) != null ? _a : "";
6249
+ }
6250
+ getTuningName() {
6251
+ return this.tuningName;
6252
+ }
6253
+ getTuningStrings() {
6254
+ return this.tuningStrings;
6255
+ }
6256
+ /** Return Y coordinate of string. */
6257
+ getStringY(stringId) {
6258
+ return this.top + (this.bottom - this.top) / 6 * (stringId + 0.5);
6259
+ }
6260
+ getTopStringY() {
6261
+ return this.getStringY(0);
6262
+ }
6263
+ getBottomStringY() {
6264
+ return this.getStringY(5);
6265
+ }
6266
+ getTopLineY() {
6267
+ return this.getTopStringY();
6268
+ }
6269
+ getBottomLineY() {
6270
+ return this.getBottomStringY();
6271
+ }
6272
+ getTop() {
6273
+ return this.top;
6274
+ }
6275
+ getBottom() {
6276
+ return this.bottom;
6277
+ }
6278
+ containsVoiceId(voiceId) {
6279
+ return !this.tabConfig.voiceIds || this.tabConfig.voiceIds.includes(voiceId);
6280
+ }
6281
+ containsDiatonicId(diatonicId) {
6282
+ return true;
6283
+ }
6284
+ calcTop() {
6285
+ return this.top;
6286
+ }
6287
+ calcBottom() {
6288
+ return this.bottom;
6289
+ }
6290
+ pick(x, y) {
6291
+ return [this];
6292
+ }
6293
+ layoutHeight(renderer) {
6294
+ let { unitSize } = renderer;
6295
+ let h = unitSize * DocumentSettings.TabHeight;
6296
+ this.top = -h / 2;
6297
+ this.bottom = h / 2;
6298
+ this.rect = new DivRect(0, 0, this.top, this.bottom);
6299
+ }
6300
+ layoutWidth(renderer) {
6301
+ this.rect.left = this.row.getRect().left;
6302
+ this.rect.right = this.row.getRect().right;
6303
+ }
6304
+ offset(dx, dy) {
6305
+ this.top += dy;
6306
+ this.bottom += dy;
6307
+ this.objects.forEach((o) => {
6308
+ if (o.offsetInPlace) {
6309
+ o.offsetInPlace(0, dy);
6310
+ } else if (o.offset) {
6311
+ o.offset(0, dy);
6312
+ }
6313
+ });
6314
+ this.rect.offsetInPlace(dx, dy);
6315
+ }
6316
+ draw(renderer) {
6317
+ }
6318
+ };
6319
+
6075
6320
  // src/score/engine/obj-score-row.ts
6076
6321
  var import_core16 = require("@tspro/web-music-score/core");
6077
6322
  var ObjScoreRow = class extends MusicObject {
@@ -6100,7 +6345,7 @@ var ObjScoreRow = class extends MusicObject {
6100
6345
  return this.mi;
6101
6346
  }
6102
6347
  createNotationLines() {
6103
- let notationLines = this.scoreConfig.map((cfg) => cfg.type === "staff" ? new ObjStaff(this, cfg) : new ObjTab(this, cfg));
6348
+ let notationLines = this.scoreConfig.map((cfg, index) => cfg.type === "staff" ? new ObjStaff(this, cfg, index) : new ObjTab(this, cfg, index));
6104
6349
  for (let i = 0; i < notationLines.length - 1; i++) {
6105
6350
  let treble = notationLines[i];
6106
6351
  let bass = notationLines[i + 1];
@@ -6152,6 +6397,12 @@ var ObjScoreRow = class extends MusicObject {
6152
6397
  }
6153
6398
  return void 0;
6154
6399
  }
6400
+ resetLayoutGroups(renderer) {
6401
+ this.notationLines.forEach((line) => line.resetLayoutGroups(renderer));
6402
+ }
6403
+ layoutLayoutGroups(renderer) {
6404
+ this.notationLines.forEach((line) => line.layoutLayoutGroups(renderer));
6405
+ }
6155
6406
  pick(x, y) {
6156
6407
  if (!this.getRect().contains(x, y)) {
6157
6408
  return [];
@@ -6232,7 +6483,6 @@ var ObjScoreRow = class extends MusicObject {
6232
6483
  this.minWidth = 0;
6233
6484
  this.measures.forEach((m) => {
6234
6485
  m.layout(renderer);
6235
- this.rect.expandInPlace(new DivRect(0, 0, m.getRect().top, m.getRect().bottom));
6236
6486
  this.minWidth += m.getMinWidth();
6237
6487
  this.minWidth += m.getPostMeasureBreakWidth();
6238
6488
  });
@@ -6266,6 +6516,13 @@ var ObjScoreRow = class extends MusicObject {
6266
6516
  m.layoutBeams(renderer);
6267
6517
  });
6268
6518
  }
6519
+ updateRect() {
6520
+ let left = this.measures.length > 0 ? this.measures[0].getRect().left : 0;
6521
+ let right = this.measures.length > 0 ? this.measures[this.measures.length - 1].getRect().right : 0;
6522
+ let top = Math.min(0, ...this.measures.map((m) => m.getRect().top));
6523
+ let bottom = Math.max(0, ...this.measures.map((m) => m.getRect().bottom));
6524
+ this.rect = new DivRect(left, right, top, bottom);
6525
+ }
6269
6526
  alignStemsToBeams() {
6270
6527
  this.measures.forEach((m) => m.alignStemsToBeams());
6271
6528
  }
@@ -6282,7 +6539,6 @@ var ObjScoreRow = class extends MusicObject {
6282
6539
  cur.offset(0, prev.calcBottom() - cur.calcTop() + sep);
6283
6540
  }
6284
6541
  }
6285
- this.requestRectUpdate();
6286
6542
  this.measures.forEach((m) => {
6287
6543
  m.requestRectUpdate();
6288
6544
  m.getBarLineLeft().requestRectUpdate();
@@ -6295,59 +6551,12 @@ var ObjScoreRow = class extends MusicObject {
6295
6551
  });
6296
6552
  });
6297
6553
  });
6298
- let lines = this.getNotationLines();
6299
- this.rect.top = lines[0].calcTop();
6300
- this.rect.bottom = lines[lines.length - 1].calcBottom();
6301
6554
  this.alignStemsToBeams();
6302
- }
6303
- updateRect() {
6304
- }
6305
- setObjectY(layoutObj, y) {
6306
- if (y === void 0) {
6307
- return;
6308
- }
6309
- let { measure, musicObj } = layoutObj;
6310
- musicObj.offset(0, y - musicObj.getRect().centerY);
6311
- layoutObj.setPositionResolved();
6312
- measure.getRect().expandInPlace(musicObj.getRect());
6313
- this.rect.expandInPlace(measure.getRect());
6314
- }
6315
- alignObjectsY(renderer, layoutObjArr) {
6316
- layoutObjArr = layoutObjArr.filter((layoutObj) => !layoutObj.isPositionResolved());
6317
- let rowY;
6318
- layoutObjArr.forEach((layoutObj) => {
6319
- let y = layoutObj.resolveClosestToStaffY(renderer);
6320
- rowY = layoutObj.verticalPos === 1 /* BelowStaff */ ? Math.max(y, rowY != null ? rowY : y) : Math.min(y, rowY != null ? rowY : y);
6321
- });
6322
- layoutObjArr.forEach((layoutObj) => this.setObjectY(layoutObj, rowY));
6323
- }
6324
- layoutLayoutGroup(renderer, layoutGroup, verticalPos) {
6325
- let rowLayoutObjs = layoutGroup.getLayoutObjects(verticalPos).filter((layoutObj) => layoutObj.row === this && !layoutObj.isPositionResolved());
6326
- rowLayoutObjs.forEach((layoutObj) => {
6327
- let { musicObj, anchor } = layoutObj;
6328
- if (musicObj instanceof ObjEnding || musicObj instanceof ObjExtensionLine) {
6329
- musicObj.layoutFitToMeasure(renderer);
6330
- } else {
6331
- musicObj.offset(anchor.getRect().centerX - musicObj.getRect().centerX, 0);
6332
- }
6333
- });
6334
- if (layoutGroup.rowAlign) {
6335
- this.alignObjectsY(renderer, rowLayoutObjs);
6336
- } else {
6337
- rowLayoutObjs.forEach((layoutObj) => {
6338
- let link = layoutObj.musicObj.getLink();
6339
- if (link && link.getHead() === layoutObj.musicObj) {
6340
- let objectParts = [link.getHead(), ...link.getTails()];
6341
- let layoutObjs = rowLayoutObjs.filter((layoutObj2) => objectParts.some((o) => o === layoutObj2.musicObj));
6342
- this.alignObjectsY(renderer, layoutObjs);
6343
- } else {
6344
- this.alignObjectsY(renderer, [layoutObj]);
6345
- }
6346
- });
6347
- }
6555
+ this.requestRectUpdate();
6348
6556
  }
6349
6557
  layoutPadding(renderer) {
6350
6558
  let p = renderer.unitSize / 2;
6559
+ this.getRect();
6351
6560
  this.rect.left -= p;
6352
6561
  this.rect.right += p;
6353
6562
  this.rect.top -= p;
@@ -6371,21 +6580,10 @@ var ObjScoreRow = class extends MusicObject {
6371
6580
  ctx.save();
6372
6581
  ctx.rect(this.getRect().left, this.getRect().top, this.getRect().width, this.getRect().height);
6373
6582
  ctx.clip();
6374
- if (this.getFirstMeasure() && this.notationLines.length > 1 || this.notationLines.length === 1 && this.notationLines[0] instanceof ObjTab) {
6583
+ if (this.getFirstMeasure() && (this.notationLines.length > 1 || this.notationLines[0] instanceof ObjTab)) {
6375
6584
  let left = this.getFirstMeasure().getStaffLineLeft();
6376
- let tops = [];
6377
- let bottoms = [];
6378
- this.notationLines.forEach((line) => {
6379
- if (line instanceof ObjStaff) {
6380
- tops.push(line.getTopLineY());
6381
- bottoms.push(line.getBottomLineY());
6382
- } else {
6383
- tops.push(line.getTopStringY());
6384
- bottoms.push(line.getBottomStringY());
6385
- }
6386
- });
6387
- let top = Math.min(...tops);
6388
- let bottom = Math.max(...bottoms);
6585
+ let top = Math.min(...this.notationLines.map((line) => line.getTopLineY()));
6586
+ let bottom = Math.max(...this.notationLines.map((line) => line.getBottomLineY()));
6389
6587
  renderer.drawLine(left, top, left, bottom);
6390
6588
  }
6391
6589
  this.measures.forEach((m) => m.draw(renderer));
@@ -6496,9 +6694,9 @@ var ObjDocument = class extends MusicObject {
6496
6694
  __publicField(this, "measuresPerRow", Infinity);
6497
6695
  __publicField(this, "curScoreConfig", [{ type: "staff", clef: "G" /* G */ }]);
6498
6696
  __publicField(this, "header");
6499
- __publicField(this, "layoutGroups", []);
6500
6697
  __publicField(this, "newRowRequested", false);
6501
6698
  __publicField(this, "allConnectiveProps", []);
6699
+ __publicField(this, "staffGroups", /* @__PURE__ */ new Map());
6502
6700
  __publicField(this, "mi");
6503
6701
  this.mi = new MDocument2(this);
6504
6702
  }
@@ -6564,13 +6762,6 @@ var ObjDocument = class extends MusicObject {
6564
6762
  addConnectiveProps(connectiveProps) {
6565
6763
  this.allConnectiveProps.push(connectiveProps);
6566
6764
  }
6567
- getLayoutGroup(lauoutGroupId) {
6568
- let layoutGroup = this.layoutGroups[lauoutGroupId];
6569
- if (!layoutGroup) {
6570
- layoutGroup = this.layoutGroups[lauoutGroupId] = new LayoutGroup(lauoutGroupId);
6571
- }
6572
- return layoutGroup;
6573
- }
6574
6765
  setRenderer(renderer) {
6575
6766
  if (this.renderer === renderer) {
6576
6767
  return;
@@ -6636,6 +6827,12 @@ var ObjDocument = class extends MusicObject {
6636
6827
  this.requestLayout();
6637
6828
  return measure;
6638
6829
  }
6830
+ addStaffGroup(groupName, layoutElements, verticalPosition) {
6831
+ this.staffGroups.set(groupName, new StaffGroup(groupName, layoutElements, verticalPosition));
6832
+ }
6833
+ getStaffGroup(groupName) {
6834
+ return this.staffGroups.get(groupName);
6835
+ }
6639
6836
  getVoiceSymbols(voiceId) {
6640
6837
  let voiceSymbols = [];
6641
6838
  this.forEachMeasure((m) => voiceSymbols = voiceSymbols.concat(m.getVoiceSymbols(voiceId)));
@@ -6683,21 +6880,15 @@ var ObjDocument = class extends MusicObject {
6683
6880
  this.forEachMeasure((m) => m.createExtensions());
6684
6881
  this.allConnectiveProps.forEach((props) => props.removeConnectives());
6685
6882
  this.allConnectiveProps.forEach((props) => props.createConnectives());
6686
- let layoutGroups = this.layoutGroups.filter((layoutGroup) => !!layoutGroup);
6687
- layoutGroups.forEach((layoutGroup) => layoutGroup.clearPositionAndLayout(renderer));
6883
+ this.rows.forEach((row) => row.resetLayoutGroups(renderer));
6688
6884
  this.rows.forEach((row) => row.layout(renderer));
6689
6885
  let rowWidth = Math.max(
6690
6886
  DocumentSettings.DocumentMinWidth * unitSize,
6691
6887
  ...this.rows.map((row) => 1.4 * row.getMinWidth())
6692
6888
  );
6693
6889
  this.rows.forEach((row) => row.layoutWidth(renderer, rowWidth));
6890
+ this.rows.forEach((row) => row.layoutLayoutGroups(renderer));
6694
6891
  this.rows.forEach((row) => row.layoutPositionLines(renderer));
6695
- layoutGroups.forEach((layoutGroup) => {
6696
- this.rows.forEach((row) => {
6697
- row.layoutLayoutGroup(renderer, layoutGroup, 0 /* AboveStaff */);
6698
- row.layoutLayoutGroup(renderer, layoutGroup, 1 /* BelowStaff */);
6699
- });
6700
- });
6701
6892
  this.rows.forEach((row) => row.layoutPadding(renderer));
6702
6893
  this.rect = new DivRect();
6703
6894
  if (this.header) {
@@ -6922,21 +7113,64 @@ var DocumentBuilder = class {
6922
7113
  this.getMeasure().addRest(voiceId, restLength, options);
6923
7114
  return this;
6924
7115
  }
6925
- addFermata(fermata) {
6926
- assertArg(import_ts_utils_lib11.Utils.Is.isEnumValueOrUndefined(fermata, Fermata), "fermata", fermata);
6927
- this.getMeasure().addFermata(fermata != null ? fermata : 0 /* AtNote */);
7116
+ addFermataInternal(staffTabOrGroup, fermata) {
7117
+ assertArg(import_ts_utils_lib11.Utils.Is.isStringOrUndefined(staffTabOrGroup) || import_ts_utils_lib11.Utils.Is.isIntegerGte(staffTabOrGroup, 0), "staffTabOrGroup", staffTabOrGroup);
7118
+ assertArg(import_ts_utils_lib11.Utils.Is.isEnumValue(fermata, Fermata), "fermata", fermata);
7119
+ this.getMeasure().addFermata(staffTabOrGroup, fermata);
6928
7120
  return this;
6929
7121
  }
6930
- addNavigation(navigation, ...args) {
7122
+ addFermata(fermata = 0 /* AtNote */) {
7123
+ return this.addFermataInternal(void 0, fermata);
7124
+ }
7125
+ /** @param staffTabOrGroup - staff/tab index (0=top), staff/tab name, or staff group name. */
7126
+ addFermataTo(staffTabOrGroup, fermata = 0 /* AtNote */) {
7127
+ return this.addFermataInternal(staffTabOrGroup, fermata);
7128
+ }
7129
+ addNavigationInternal(staffTabOrGroup, navigation, ...args) {
7130
+ assertArg(import_ts_utils_lib11.Utils.Is.isStringOrUndefined(staffTabOrGroup) || import_ts_utils_lib11.Utils.Is.isIntegerGte(staffTabOrGroup, 0), "staffTabOrGroup", staffTabOrGroup);
6931
7131
  assertArg(import_ts_utils_lib11.Utils.Is.isEnumValue(navigation, Navigation), "navigation", navigation);
6932
7132
  if (navigation === 9 /* EndRepeat */ && args.length > 0) {
6933
7133
  assertArg(import_ts_utils_lib11.Utils.Is.isIntegerGte(args[0], 1), "playCount", args[0]);
6934
7134
  } else if (navigation === 10 /* Ending */ && args.length > 0) {
6935
7135
  assertArg(args.every((passage) => import_ts_utils_lib11.Utils.Is.isIntegerGte(passage, 1)), "passages", args);
6936
7136
  }
6937
- this.getMeasure().addNavigation(navigation, ...args);
7137
+ this.getMeasure().addNavigation(staffTabOrGroup, navigation, ...args);
6938
7138
  return this;
6939
7139
  }
7140
+ addNavigation(navigation, ...args) {
7141
+ return this.addNavigationInternal(void 0, navigation, ...args);
7142
+ }
7143
+ addNavigationTo(staffTabOrGroup, navigation, ...args) {
7144
+ return this.addNavigationInternal(staffTabOrGroup, navigation, ...args);
7145
+ }
7146
+ addLabelInternal(staffTabOrGroup, label, text) {
7147
+ assertArg(import_ts_utils_lib11.Utils.Is.isStringOrUndefined(staffTabOrGroup) || import_ts_utils_lib11.Utils.Is.isIntegerGte(staffTabOrGroup, 0), "staffTabOrGroup", staffTabOrGroup);
7148
+ assertArg(import_ts_utils_lib11.Utils.Is.isEnumValue(label, Label), "label", label);
7149
+ assertArg(import_ts_utils_lib11.Utils.Is.isString(text), "text", text);
7150
+ this.getMeasure().addLabel(staffTabOrGroup, label, text);
7151
+ return this;
7152
+ }
7153
+ addLabel(label, text) {
7154
+ return this.addLabelInternal(void 0, label, text);
7155
+ }
7156
+ /** @param staffTabOrGroup - staff/tab index (0=top), staff/tab name, or staff group name. */
7157
+ addLabelTo(staffTabOrGroup, label, text) {
7158
+ return this.addLabelInternal(staffTabOrGroup, label, text);
7159
+ }
7160
+ addAnnotationInternal(staffTabOrGroup, annotation, text) {
7161
+ assertArg(import_ts_utils_lib11.Utils.Is.isStringOrUndefined(staffTabOrGroup) || import_ts_utils_lib11.Utils.Is.isIntegerGte(staffTabOrGroup, 0), "staffTabOrGroup", staffTabOrGroup);
7162
+ assertArg(import_ts_utils_lib11.Utils.Is.isEnumValue(annotation, Annotation), "annotation", annotation);
7163
+ assertArg(import_ts_utils_lib11.Utils.Is.isString(text), "text", text);
7164
+ this.getMeasure().addAnnotation(staffTabOrGroup, annotation, text);
7165
+ return this;
7166
+ }
7167
+ addAnnotation(annotation, text) {
7168
+ return this.addAnnotationInternal(void 0, annotation, text);
7169
+ }
7170
+ /** @param staffTabOrGroup - staff/tab index (0=top), staff/tab name, or staff group name. */
7171
+ addAnnotationTo(staffTabOrGroup, annotation, text) {
7172
+ return this.addAnnotationInternal(staffTabOrGroup, annotation, text);
7173
+ }
6940
7174
  addConnective(connective, ...args) {
6941
7175
  assertArg(import_ts_utils_lib11.Utils.Is.isEnumValue(connective, Connective), "connective", connective);
6942
7176
  if (connective === 0 /* Tie */) {
@@ -6958,24 +7192,30 @@ var DocumentBuilder = class {
6958
7192
  }
6959
7193
  return this;
6960
7194
  }
6961
- addLabel(label, text) {
6962
- assertArg(import_ts_utils_lib11.Utils.Is.isEnumValue(label, Label), "label", label);
6963
- assertArg(import_ts_utils_lib11.Utils.Is.isString(text), "text", text);
6964
- this.getMeasure().addLabel(label, text);
6965
- return this;
6966
- }
6967
- addAnnotation(annotation, text) {
6968
- assertArg(import_ts_utils_lib11.Utils.Is.isEnumValue(annotation, Annotation), "annotation", annotation);
6969
- assertArg(import_ts_utils_lib11.Utils.Is.isString(text), "text", text);
6970
- this.getMeasure().addAnnotation(annotation, text);
6971
- return this;
6972
- }
6973
7195
  addExtension(extensionLength, extensionVisible) {
6974
7196
  assertArg(import_ts_utils_lib11.Utils.Is.isIntegerGte(extensionLength, 0) || extensionLength === Infinity || import_ts_utils_lib11.Utils.Is.isEnumValue(extensionLength, import_theory13.NoteLength), "extendionLength", extensionLength);
6975
7197
  assertArg(import_ts_utils_lib11.Utils.Is.isBooleanOrUndefined(extensionVisible), "extensionVisible", extensionVisible);
6976
7198
  this.getMeasure().addExtension(extensionLength, extensionVisible != null ? extensionVisible : true);
6977
7199
  return this;
6978
7200
  }
7201
+ /**
7202
+ *
7203
+ * @param groupName - Name of staff group.
7204
+ * @param staffsTabsAndGroups - staff/tab index (0=top), staff/tab name, or staff group name. Single value or array.
7205
+ * @param verticalPosition - Vertical position, are elements added above, below or both.
7206
+ * @returns
7207
+ */
7208
+ addStaffGroup(groupName, staffsTabsAndGroups, verticalPosition = 3 /* Auto */) {
7209
+ assertArg(import_ts_utils_lib11.Utils.Is.isString(groupName) && groupName.length > 0, "groupName", groupName);
7210
+ assertArg(
7211
+ import_ts_utils_lib11.Utils.Is.isString(staffsTabsAndGroups) && staffsTabsAndGroups.length > 0 || import_ts_utils_lib11.Utils.Is.isIntegerGte(staffsTabsAndGroups, 0) || import_ts_utils_lib11.Utils.Is.isArray(staffsTabsAndGroups) && staffsTabsAndGroups.every((line) => import_ts_utils_lib11.Utils.Is.isString(line) && line.length > 0 || import_ts_utils_lib11.Utils.Is.isIntegerGte(line, 0)),
7212
+ "staffsTabsAndGroups",
7213
+ staffsTabsAndGroups
7214
+ );
7215
+ assertArg(import_ts_utils_lib11.Utils.Is.isEnumValue(verticalPosition, VerticalPosition), "verticalPosition", verticalPosition);
7216
+ this.doc.addStaffGroup(groupName, staffsTabsAndGroups, verticalPosition);
7217
+ return this;
7218
+ }
6979
7219
  endSong() {
6980
7220
  this.getMeasure().endSong();
6981
7221
  return this;
@@ -7747,6 +7987,7 @@ var import_core20 = require("@tspro/web-music-score/core");
7747
7987
  StaffPreset,
7748
7988
  Stem,
7749
7989
  TieType,
7990
+ VerticalPosition,
7750
7991
  getStringNumbers,
7751
7992
  getVoiceIds
7752
7993
  });