@tspro/web-music-score 5.4.0 → 5.4.2

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.
Files changed (46) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/LICENSE +1 -1
  3. package/README.md +4 -4
  4. package/dist/audio/index.d.mts +1 -1
  5. package/dist/audio/index.d.ts +1 -1
  6. package/dist/audio/index.js +1 -1
  7. package/dist/audio/index.mjs +3 -3
  8. package/dist/audio-cg/index.js +1 -1
  9. package/dist/audio-cg/index.mjs +3 -3
  10. package/dist/audio-synth/index.js +1 -1
  11. package/dist/audio-synth/index.mjs +3 -3
  12. package/dist/{chunk-MHDBTCVG.mjs → chunk-42IBAVOC.mjs} +3 -3
  13. package/dist/{chunk-QGMOI7AP.mjs → chunk-CVYTUTL6.mjs} +2 -2
  14. package/dist/{chunk-ZWUBO5EW.mjs → chunk-MMWSQGVR.mjs} +3 -3
  15. package/dist/{chunk-AUT4C6TY.mjs → chunk-ROBXPR34.mjs} +2 -2
  16. package/dist/core/index.js +2 -2
  17. package/dist/core/index.mjs +4 -4
  18. package/dist/{guitar-CarHGDAt.d.ts → guitar-CNOxM4ZK.d.ts} +1 -1
  19. package/dist/{guitar-DXlB-9vK.d.mts → guitar-DK18GZ6h.d.mts} +1 -1
  20. package/dist/iife/audio-cg.global.js +1 -1
  21. package/dist/iife/index.global.js +11 -11
  22. package/dist/{music-objects-ONIuVUgs.d.mts → music-objects-DqoO-Sfv.d.mts} +100 -45
  23. package/dist/{music-objects-3Esbz7ij.d.ts → music-objects-T8u8bnNP.d.ts} +100 -45
  24. package/dist/pieces/index.d.mts +3 -3
  25. package/dist/pieces/index.d.ts +3 -3
  26. package/dist/pieces/index.js +1 -1
  27. package/dist/pieces/index.mjs +2 -2
  28. package/dist/react-ui/index.d.mts +5 -5
  29. package/dist/react-ui/index.d.ts +5 -5
  30. package/dist/react-ui/index.js +1 -1
  31. package/dist/react-ui/index.mjs +2 -2
  32. package/dist/{scale-DulPFco_.d.ts → scale-CUYFBo-8.d.ts} +2 -2
  33. package/dist/{scale-C8gHC448.d.mts → scale-DWM4RQco.d.mts} +2 -2
  34. package/dist/score/index.d.mts +5 -5
  35. package/dist/score/index.d.ts +5 -5
  36. package/dist/score/index.js +743 -512
  37. package/dist/score/index.mjs +639 -409
  38. package/dist/{tempo-BlCGZuYg.d.mts → tempo-Cxu8vusu.d.mts} +1 -1
  39. package/dist/{tempo-BnUjm25M.d.ts → tempo-DwuZsv2T.d.ts} +1 -1
  40. package/dist/theory/index.d.mts +6 -6
  41. package/dist/theory/index.d.ts +6 -6
  42. package/dist/theory/index.js +1 -1
  43. package/dist/theory/index.mjs +3 -3
  44. package/package.json +2 -1
  45. /package/dist/{note-CJuq5aBy.d.ts → note-CJuq5aBy.d.mts} +0 -0
  46. /package/dist/{note-RVXvpfyV.d.mts → note-RVXvpfyV.d.ts} +0 -0
@@ -1,15 +1,15 @@
1
- /* WebMusicScore v5.4.0 | (c) 2023 PahkaSoft | MIT License | Includes: Tone.js (MIT License) */
1
+ /* WebMusicScore v5.4.2 | (c) 2023-2025 PahkaSoft | MIT License | Includes: Tone.js (MIT License) */
2
2
  import {
3
3
  MusicError
4
- } from "../chunk-ZWUBO5EW.mjs";
4
+ } from "../chunk-MMWSQGVR.mjs";
5
5
  import {
6
6
  NoteLengthProps,
7
7
  RhythmProps,
8
8
  validateNoteLength
9
- } from "../chunk-MHDBTCVG.mjs";
9
+ } from "../chunk-42IBAVOC.mjs";
10
10
  import {
11
11
  __publicField
12
- } from "../chunk-AUT4C6TY.mjs";
12
+ } from "../chunk-ROBXPR34.mjs";
13
13
 
14
14
  // src/score/pub/div-rect.ts
15
15
  import { Utils } from "@tspro/ts-utils-lib";
@@ -537,13 +537,52 @@ var MusicObject = class {
537
537
  }
538
538
  updateRect() {
539
539
  }
540
+ forceRectUpdate() {
541
+ this.needRectUpdate = true;
542
+ this.updateRect();
543
+ this.needRectUpdate = false;
544
+ }
540
545
  getRect() {
541
- if (this.needRectUpdate) {
542
- this.updateRect();
543
- this.needRectUpdate = false;
544
- }
546
+ if (this.needRectUpdate)
547
+ this.forceRectUpdate();
545
548
  return this.rect;
546
549
  }
550
+ offsetX(dx) {
551
+ this.offset(dx, 0);
552
+ }
553
+ offsetY(dy) {
554
+ this.offset(0, dy);
555
+ }
556
+ setLeft(x) {
557
+ this.offset(x - this.getRect().left, 0);
558
+ }
559
+ setRight(x) {
560
+ this.offset(x - this.getRect().right, 0);
561
+ }
562
+ setTop(y) {
563
+ this.offset(0, y - this.getRect().top);
564
+ }
565
+ setBottom(y) {
566
+ this.offset(0, y - this.getRect().bottom);
567
+ }
568
+ setAnchor(x, y) {
569
+ this.offset(x - this.getRect().anchorX, y - this.getRect().anchorY);
570
+ }
571
+ setAnchorX(x) {
572
+ this.offset(x - this.getRect().anchorX, 0);
573
+ }
574
+ setAnchorY(y) {
575
+ this.offset(0, y - this.getRect().anchorY);
576
+ }
577
+ setCenter(x, y) {
578
+ this.offset(x - this.getRect().centerX, y - this.getRect().centerY);
579
+ }
580
+ setCenterX(x) {
581
+ this.offset(x - this.getRect().centerX, 0);
582
+ }
583
+ setCenterY(y) {
584
+ this.offset(0, y - this.getRect().centerY);
585
+ }
547
586
  /**
548
587
  * Most objects are simple rects in shape.
549
588
  * Some objects might be more complex consisting of multiple rects.
@@ -587,7 +626,9 @@ var DebugSettings = {
587
626
  };
588
627
  var DocumentSettings = {
589
628
  DocumentScale: 1,
590
- DocumentMinWidth: 75,
629
+ MinStaffWidth: 75,
630
+ MinColumnsWidth: 10,
631
+ ColumnWidthScale: 1.7,
591
632
  PostMeasureBreakWidth: 10,
592
633
  NoteDotSpace: 0.5,
593
634
  NoteAccSpace: 0.5,
@@ -1147,72 +1188,112 @@ var RenderContext = class {
1147
1188
  }
1148
1189
  }
1149
1190
  arc(x, y, radius, startRadians, endRadians) {
1150
- var _a;
1151
- (_a = this.ctx) == null ? void 0 : _a.arc(x, y, radius, startRadians, endRadians);
1191
+ if (this.ctx) this.ctx.arc(x, y, radius, startRadians, endRadians);
1192
+ return this;
1152
1193
  }
1153
1194
  fillCircle(x, y, radius) {
1154
- if (this.ctx) {
1155
- this.ctx.beginPath();
1156
- this.ctx.arc(x, y, radius, 0, 2 * Math.PI);
1157
- this.ctx.fill();
1158
- }
1195
+ if (!this.ctx) return this;
1196
+ this.ctx.beginPath();
1197
+ this.ctx.arc(x, y, radius, 0, 2 * Math.PI);
1198
+ this.ctx.fill();
1199
+ return this;
1159
1200
  }
1160
1201
  strokeLine(startX, startY, endX, endY) {
1161
- if (this.ctx) {
1162
- this.ctx.beginPath();
1163
- this.ctx.moveTo(startX, startY);
1164
- this.ctx.lineTo(endX, endY);
1165
- this.ctx.stroke();
1166
- }
1202
+ if (!this.ctx) return this;
1203
+ this.ctx.beginPath();
1204
+ this.ctx.moveTo(startX, startY);
1205
+ this.ctx.lineTo(endX, endY);
1206
+ this.ctx.stroke();
1207
+ return this;
1167
1208
  }
1168
1209
  strokePartialLine(startX, startY, endX, endY, startT, endT) {
1210
+ if (!this.ctx) return this;
1169
1211
  let x1 = startX + (endX - startX) * startT;
1170
1212
  let y1 = startY + (endY - startY) * startT;
1171
1213
  let x2 = startX + (endX - startX) * endT;
1172
1214
  let y2 = startY + (endY - startY) * endT;
1173
- if (this.ctx) {
1174
- this.ctx.beginPath();
1175
- this.ctx.moveTo(x1, y1);
1176
- this.ctx.lineTo(x2, y2);
1177
- this.ctx.stroke();
1178
- }
1215
+ this.ctx.beginPath();
1216
+ this.ctx.moveTo(x1, y1);
1217
+ this.ctx.lineTo(x2, y2);
1218
+ this.ctx.stroke();
1219
+ return this;
1179
1220
  }
1221
+ /** @deprecated - Use {@link drawBracket} instead. */
1180
1222
  drawBrace(rect, side) {
1181
- if (this.ctx) {
1182
- let { left, right, width, top, bottom, anchorY } = rect;
1183
- if (side === "right") {
1184
- [left, right, width] = [right, left, -width];
1185
- }
1186
- this.ctx.beginPath();
1187
- this.ctx.moveTo(right, top);
1188
- this.ctx.bezierCurveTo(
1189
- left + width * 0.1,
1190
- top,
1191
- left + width * 0.8,
1192
- anchorY,
1193
- left,
1194
- anchorY
1195
- );
1196
- this.ctx.moveTo(right, bottom);
1197
- this.ctx.bezierCurveTo(
1198
- left + width * 0.1,
1199
- bottom,
1200
- left + width * 0.8,
1201
- anchorY,
1202
- left,
1203
- anchorY
1204
- );
1205
- this.ctx.stroke();
1223
+ return this.drawBracket(rect, side === "left" ? "{" : "}");
1224
+ }
1225
+ drawBracket(rect, bracket) {
1226
+ if (!this.ctx) return this;
1227
+ let { left, right, width, top, bottom, height, anchorY } = rect;
1228
+ if ([")", "]", "}", ">"].includes(bracket)) {
1229
+ [left, right, width] = [right, left, -width];
1230
+ }
1231
+ switch (bracket) {
1232
+ case "(":
1233
+ case ")":
1234
+ this.ctx.beginPath();
1235
+ this.ctx.moveTo(right, top);
1236
+ this.ctx.bezierCurveTo(
1237
+ left - width * 0.2,
1238
+ top + height * 0.3,
1239
+ left - width * 0.2,
1240
+ top + height * 0.7,
1241
+ right,
1242
+ bottom
1243
+ );
1244
+ this.ctx.stroke();
1245
+ break;
1246
+ case "{":
1247
+ case "}":
1248
+ this.ctx.beginPath();
1249
+ this.ctx.moveTo(right, top);
1250
+ this.ctx.bezierCurveTo(
1251
+ left + width * 0.1,
1252
+ top,
1253
+ left + width * 0.8,
1254
+ anchorY,
1255
+ left,
1256
+ anchorY
1257
+ );
1258
+ this.ctx.moveTo(right, bottom);
1259
+ this.ctx.bezierCurveTo(
1260
+ left + width * 0.1,
1261
+ bottom,
1262
+ left + width * 0.8,
1263
+ anchorY,
1264
+ left,
1265
+ anchorY
1266
+ );
1267
+ this.ctx.stroke();
1268
+ break;
1269
+ case "[":
1270
+ case "]":
1271
+ this.ctx.beginPath();
1272
+ this.ctx.moveTo(right, top);
1273
+ this.ctx.lineTo(left, top);
1274
+ this.ctx.lineTo(left, bottom);
1275
+ this.ctx.lineTo(right, bottom);
1276
+ this.ctx.stroke();
1277
+ break;
1278
+ case "<":
1279
+ case ">":
1280
+ this.ctx.beginPath();
1281
+ this.ctx.moveTo(right, top);
1282
+ this.ctx.lineTo(left, anchorY);
1283
+ this.ctx.lineTo(right, bottom);
1284
+ this.ctx.stroke();
1285
+ break;
1206
1286
  }
1287
+ return this;
1207
1288
  }
1208
1289
  };
1209
1290
 
1210
1291
  // src/score/engine/obj-staff-and-tab.ts
1211
1292
  import { MusicError as MusicError15, MusicErrorType as MusicErrorType15 } from "@tspro/web-music-score/core";
1212
- import { AnchoredRect as AnchoredRect23, Guard as Guard9, UniMap as UniMap7, Utils as Utils10 } from "@tspro/ts-utils-lib";
1293
+ import { AnchoredRect as AnchoredRect22, Guard as Guard9, UniMap as UniMap8, Utils as Utils10 } from "@tspro/ts-utils-lib";
1213
1294
 
1214
1295
  // src/score/engine/obj-measure.ts
1215
- import { Guard as Guard8, IndexArray as IndexArray2, UniMap as UniMap5, TriMap as TriMap2, ValueSet, Utils as Utils9, asMulti, AnchoredRect as AnchoredRect21 } from "@tspro/ts-utils-lib";
1296
+ import { Guard as Guard8, IndexArray as IndexArray2, UniMap as UniMap6, TriMap as TriMap2, ValueSet, Utils as Utils9, asMulti, AnchoredRect as AnchoredRect20 } from "@tspro/ts-utils-lib";
1216
1297
  import { getScale, Scale, validateScaleType, Note as Note7, RhythmProps as RhythmProps5, KeySignature as KeySignature2, getDefaultKeySignature, PitchNotation, SymbolSet, validateNoteLength as validateNoteLength2, NoteLengthProps as NoteLengthProps5 } from "@tspro/web-music-score/theory";
1217
1298
  import { getDefaultTempo, getDefaultTimeSignature } from "@tspro/web-music-score/theory";
1218
1299
 
@@ -1640,20 +1721,21 @@ var ObjStaffSignature = class extends MusicObject {
1640
1721
  if (this.clefImage) {
1641
1722
  x += paddingX;
1642
1723
  this.clefImage.layout(ctx);
1643
- this.clefImage.offset(x, staff.getDiatonicIdY(staff.clefLineDiatonicId));
1724
+ this.clefImage.setAnchor(x, staff.getDiatonicIdY(staff.clefLineDiatonicId));
1644
1725
  this.rect.expandInPlace(this.clefImage.getRect());
1645
1726
  x = this.rect.right;
1646
1727
  if (this.eightBelowClef) {
1647
1728
  let r = this.clefImage.getRect();
1648
1729
  this.eightBelowClef.layout(ctx);
1649
- this.eightBelowClef.offset(r.centerX, Math.max(r.anchorY + r.height * 0.3, staff.getBottomLineY()));
1730
+ this.eightBelowClef.setCenterX(r.centerX);
1731
+ this.eightBelowClef.setTop(Math.max(r.anchorY + r.height * 0.3, staff.getBottomLineY()));
1650
1732
  this.rect.expandInPlace(this.eightBelowClef.getRect());
1651
1733
  }
1652
1734
  }
1653
1735
  if (this.measureNumber) {
1654
1736
  this.measureNumber.layout(ctx);
1655
- let y = Math.min(staff.getTopLineY(), this.clefImage ? this.clefImage.getRect().top : staff.getTopLineY());
1656
- this.measureNumber.offset(0, y);
1737
+ this.measureNumber.setLeft(0);
1738
+ this.measureNumber.setBottom(Math.min(staff.getTopLineY(), this.clefImage ? this.clefImage.getRect().top : staff.getTopLineY()));
1657
1739
  this.rect.expandInPlace(this.measureNumber.getRect());
1658
1740
  x = Math.max(x, this.rect.right);
1659
1741
  }
@@ -1661,7 +1743,8 @@ var ObjStaffSignature = class extends MusicObject {
1661
1743
  x += paddingX;
1662
1744
  this.ksNeutralizeAccidentals.forEach((objAcc) => {
1663
1745
  objAcc.layout(ctx);
1664
- objAcc.offset(x + objAcc.getRect().leftw, staff.getDiatonicIdY(objAcc.diatonicId));
1746
+ objAcc.setLeft(x);
1747
+ objAcc.setAnchorY(staff.getDiatonicIdY(objAcc.diatonicId));
1665
1748
  this.rect.expandInPlace(objAcc.getRect());
1666
1749
  x = this.rect.right;
1667
1750
  });
@@ -1670,7 +1753,8 @@ var ObjStaffSignature = class extends MusicObject {
1670
1753
  x += paddingX;
1671
1754
  this.ksNewAccidentals.forEach((objAcc) => {
1672
1755
  objAcc.layout(ctx);
1673
- objAcc.offset(x + objAcc.getRect().leftw, staff.getDiatonicIdY(objAcc.diatonicId));
1756
+ objAcc.setLeft(x);
1757
+ objAcc.setAnchorY(staff.getDiatonicIdY(objAcc.diatonicId));
1674
1758
  this.rect.expandInPlace(objAcc.getRect());
1675
1759
  x = this.rect.right;
1676
1760
  });
@@ -1680,24 +1764,34 @@ var ObjStaffSignature = class extends MusicObject {
1680
1764
  (_b = this.beatSizeText) == null ? void 0 : _b.layout(ctx);
1681
1765
  let tsWidth = Math.max((_d = (_c = this.beatCountText) == null ? void 0 : _c.getRect().width) != null ? _d : 0, (_f = (_e = this.beatSizeText) == null ? void 0 : _e.getRect().width) != null ? _f : 0);
1682
1766
  if (this.beatCountText) {
1683
- this.beatCountText.offset(x + tsWidth / 2 + paddingX, staff.getDiatonicIdY(staff.middleLineDiatonicId + 2));
1767
+ this.beatCountText.setCenter(
1768
+ x + tsWidth / 2 + paddingX,
1769
+ staff.getDiatonicIdY(staff.middleLineDiatonicId + 2)
1770
+ );
1684
1771
  this.rect.expandInPlace(this.beatCountText.getRect());
1685
1772
  right = Math.max(right, this.rect.right);
1686
1773
  }
1687
1774
  if (this.beatSizeText) {
1688
- this.beatSizeText.offset(x + tsWidth / 2 + paddingX, staff.getDiatonicIdY(staff.bottomLineDiatonicId + 2));
1775
+ this.beatSizeText.setCenter(
1776
+ x + tsWidth / 2 + paddingX,
1777
+ staff.getDiatonicIdY(staff.bottomLineDiatonicId + 2)
1778
+ );
1689
1779
  this.rect.expandInPlace(this.beatSizeText.getRect());
1690
1780
  right = Math.max(right, this.rect.right);
1691
1781
  }
1692
1782
  x = right;
1693
1783
  if (this.tempoText) {
1694
- let tempoBottom = Math.min(
1695
- this.clefImage ? this.clefImage.getRect().top : staff.getTopLineY(),
1696
- ...this.ksNeutralizeAccidentals.map((o) => o.getRect().top),
1697
- ...this.ksNewAccidentals.map((o) => o.getRect().top)
1698
- );
1699
1784
  this.tempoText.layout(ctx);
1700
- this.tempoText.offset(x, tempoBottom);
1785
+ this.tempoText.setCenterX(x);
1786
+ this.tempoText.setBottom(staff.getTopLineY());
1787
+ if (this.clefImage && AnchoredRect6.overlap(this.clefImage.getRect(), this.tempoText.getRect())) {
1788
+ this.tempoText.setBottom(this.clefImage.getRect().top);
1789
+ }
1790
+ [...this.ksNeutralizeAccidentals, ...this.ksNewAccidentals].forEach((acc) => {
1791
+ if (this.tempoText && AnchoredRect6.overlap(acc.getRect(), this.tempoText.getRect())) {
1792
+ this.tempoText.setBottom(acc.getRect().top);
1793
+ }
1794
+ });
1701
1795
  this.rect.expandInPlace(this.tempoText.getRect());
1702
1796
  }
1703
1797
  this.rect.right += paddingX;
@@ -1808,7 +1902,8 @@ var ObjTabSignature = class extends MusicObject {
1808
1902
  this.rect = new AnchoredRect6();
1809
1903
  if (this.measureNumber) {
1810
1904
  this.measureNumber.layout(ctx);
1811
- this.measureNumber.offset(0, topLineY);
1905
+ this.measureNumber.setLeft(0);
1906
+ this.measureNumber.setBottom(topLineY);
1812
1907
  this.rect.expandInPlace(this.measureNumber.getRect());
1813
1908
  x = Math.max(x, this.rect.right);
1814
1909
  }
@@ -1816,16 +1911,23 @@ var ObjTabSignature = class extends MusicObject {
1816
1911
  (_b = this.beatSizeText) == null ? void 0 : _b.layout(ctx);
1817
1912
  let tsWidth = Math.max((_d = (_c = this.beatCountText) == null ? void 0 : _c.getRect().width) != null ? _d : 0, (_f = (_e = this.beatSizeText) == null ? void 0 : _e.getRect().width) != null ? _f : 0);
1818
1913
  if (this.beatCountText) {
1819
- this.beatCountText.offset(0 + tsWidth / 2 + paddingX, tab.getRect().anchorY - this.beatCountText.getRect().bottomh);
1914
+ this.beatCountText.setCenter(
1915
+ 0 + tsWidth / 2 + paddingX,
1916
+ tab.getRect().anchorY - this.beatCountText.getRect().bottomh
1917
+ );
1820
1918
  this.rect.expandInPlace(this.beatCountText.getRect());
1821
1919
  }
1822
1920
  if (this.beatSizeText) {
1823
- this.beatSizeText.offset(0 + tsWidth / 2 + paddingX, tab.getRect().anchorY + this.beatSizeText.getRect().toph);
1921
+ this.beatSizeText.setCenter(
1922
+ 0 + tsWidth / 2 + paddingX,
1923
+ tab.getRect().anchorY + this.beatSizeText.getRect().toph
1924
+ );
1824
1925
  this.rect.expandInPlace(this.beatSizeText.getRect());
1825
1926
  }
1826
1927
  if (this.tempoText) {
1827
1928
  this.tempoText.layout(ctx);
1828
- this.tempoText.offset(x + unitSize * 2, topLineY);
1929
+ this.tempoText.setLeft(x + unitSize * 2);
1930
+ this.tempoText.setBottom(topLineY);
1829
1931
  this.rect.expandInPlace(this.tempoText.getRect());
1830
1932
  }
1831
1933
  this.rect.right += paddingX;
@@ -2124,7 +2226,7 @@ var _ObjRest = class _ObjRest extends MusicObject {
2124
2226
  let dotY = this.getRestDotVerticalDisplacement(noteSize) * unitSize;
2125
2227
  obj.dotRects.push(AnchoredRect8.createCentered(dotX, dotY, dotWidth, dotWidth));
2126
2228
  }
2127
- obj.offset(0, staff.getDiatonicIdY(diatonicId));
2229
+ obj.setAnchor(0, staff.getDiatonicIdY(diatonicId));
2128
2230
  this.staffObjects.push(obj);
2129
2231
  this.measure.addStaticObject(staff, obj);
2130
2232
  });
@@ -2632,7 +2734,10 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2632
2734
  let acc = obj.accidentals[noteIndex] = new ObjAccidental(this, note.diatonicId, note.accidental, this.color);
2633
2735
  if (acc) {
2634
2736
  acc.layout(ctx);
2635
- acc.offset(-noteHeadRect.leftw - unitSize * DocumentSettings.NoteAccSpace - acc.getRect().rightw, noteY);
2737
+ acc.setAnchor(
2738
+ -noteHeadRect.leftw - unitSize * DocumentSettings.NoteAccSpace - acc.getRect().rightw,
2739
+ noteY
2740
+ );
2636
2741
  }
2637
2742
  noteStaff.addObject(acc);
2638
2743
  }
@@ -2696,9 +2801,7 @@ var ObjNoteGroup = class _ObjNoteGroup extends MusicObject {
2696
2801
  let color = fretId < 0 ? "red" : "black";
2697
2802
  let fretNumber = new ObjText(this, { text: String(fretId), color, bgcolor: "white" }, 0.5, 0.5);
2698
2803
  fretNumber.layout(ctx);
2699
- let x = this.col.getRect().anchorX;
2700
- let y = tab.getStringY(stringNumber - 1);
2701
- fretNumber.offset(x, y);
2804
+ fretNumber.setAnchor(this.col.getRect().anchorX, tab.getStringY(stringNumber - 1));
2702
2805
  obj.fretNumbers.push(fretNumber);
2703
2806
  }
2704
2807
  });
@@ -2873,7 +2976,7 @@ var ObjRhythmColumn = class extends MusicObject {
2873
2976
  return Math.max(0, nextPositionTicks - curPositionTicks);
2874
2977
  }
2875
2978
  getShapeRects() {
2876
- this.getRect();
2979
+ this.forceRectUpdate();
2877
2980
  return this.shapeRects;
2878
2981
  }
2879
2982
  get doc() {
@@ -2948,23 +3051,6 @@ var ObjRhythmColumn = class extends MusicObject {
2948
3051
  addLyricsObject(lyricsObj) {
2949
3052
  this.lyricsObject.set(lyricsObj.verse, lyricsObj.line, lyricsObj.vpos, lyricsObj);
2950
3053
  }
2951
- getMinWidth() {
2952
- let maxNoteSize = Math.max(...this.voiceSymbol.mapToArray((s) => s.rhythmProps.noteSize));
2953
- let w = DocumentSettings.NoteHeadWidth;
2954
- switch (maxNoteSize) {
2955
- case 1:
2956
- return w * 5;
2957
- // whole note
2958
- case 2:
2959
- return w * 3;
2960
- // half note
2961
- case 4:
2962
- return w * 2;
2963
- // quarter note
2964
- default:
2965
- return w;
2966
- }
2967
- }
2968
3054
  updateNoteDisplacements() {
2969
3055
  let data = [];
2970
3056
  this.voiceSymbol.forEach((symbol) => {
@@ -3055,13 +3141,11 @@ var ObjRhythmColumn = class extends MusicObject {
3055
3141
  if (!this.needLayout) {
3056
3142
  return;
3057
3143
  }
3058
- this.requestRectUpdate();
3059
- this.rect = new AnchoredRect10();
3060
3144
  let { row } = this;
3061
- let { unitSize } = ctx;
3062
- let halfMinWidth = this.getMinWidth() * unitSize / 2;
3063
- let leftw = halfMinWidth;
3064
- let rightw = halfMinWidth;
3145
+ this.rect = new AnchoredRect10();
3146
+ this.requestRectUpdate();
3147
+ let leftw = 0;
3148
+ let rightw = 0;
3065
3149
  this.voiceSymbol.forEach((symbol) => {
3066
3150
  symbol.layout(ctx, accState);
3067
3151
  let r = symbol.getRect();
@@ -3069,31 +3153,30 @@ var ObjRhythmColumn = class extends MusicObject {
3069
3153
  rightw = Math.max(rightw, r.rightw);
3070
3154
  });
3071
3155
  if (this.arpeggioDir !== void 0) {
3072
- let arpeggioWidth = 0;
3073
- this.arpeggios = row.getNotationLines().map((line) => {
3074
- let arpeggio = new ObjArpeggio(this, line, this.getArpeggioDir());
3075
- arpeggio.layout(ctx);
3076
- arpeggio.offset(-leftw - arpeggio.getRect().right, line.getRect().anchorY - arpeggio.getRect().anchorY);
3077
- arpeggioWidth = Math.max(arpeggioWidth, arpeggio.getRect().width);
3078
- line.addObject(arpeggio);
3079
- this.measure.addStaticObject(line, arpeggio);
3080
- return arpeggio;
3156
+ this.arpeggios = row.getNotationLines().map((line) => new ObjArpeggio(this, line, this.getArpeggioDir()));
3157
+ this.arpeggios.forEach((a) => a.layout(ctx));
3158
+ const arpeggioWidth = this.arpeggios.map((a) => a.getRect().width).reduce((accState2, cur) => Math.max(accState2, cur)) + ctx.unitSize;
3159
+ this.arpeggios.forEach((a) => {
3160
+ a.setAnchor(-leftw - arpeggioWidth / 2, a.line.getRect().anchorY);
3161
+ a.line.addObject(a);
3162
+ this.measure.addStaticObject(a.line, a);
3081
3163
  });
3082
3164
  leftw += arpeggioWidth;
3083
3165
  } else {
3084
3166
  this.arpeggios = [];
3085
3167
  }
3086
- let widenColumnObjs = this.getAnchoredLayoutObjects().filter((layoutObj) => layoutObj.layoutGroup.widensColumn);
3087
- if (widenColumnObjs.length > 0) {
3088
- widenColumnObjs.forEach((layoutObj) => {
3089
- leftw = Math.max(leftw, layoutObj.musicObj.getRect().leftw);
3090
- rightw = Math.max(rightw, layoutObj.musicObj.getRect().rightw);
3091
- });
3092
- }
3093
- this.voiceSymbol.forEach((symbol) => symbol.updateAccidentalState(accState));
3168
+ const noteSizes = this.voiceSymbol.mapToArray((s) => s.rhythmProps.noteSize);
3169
+ const maxNoteSize = Math.min(8, Math.max(1, ...noteSizes));
3170
+ const MinColumnWidth = Math.ceil(8 / maxNoteSize) * DocumentSettings.NoteHeadWidth * ctx.unitSize * 0.75;
3171
+ leftw = Math.max(leftw, MinColumnWidth / 2);
3172
+ rightw = Math.max(rightw, MinColumnWidth / 2);
3173
+ leftw *= DocumentSettings.ColumnWidthScale;
3174
+ rightw *= DocumentSettings.ColumnWidthScale;
3094
3175
  this.rect.left = -leftw;
3095
3176
  this.rect.anchorX = 0;
3096
3177
  this.rect.right = rightw;
3178
+ this.requestRectUpdate();
3179
+ this.voiceSymbol.forEach((symbol) => symbol.updateAccidentalState(accState));
3097
3180
  this.row.getStaves().forEach((staff) => {
3098
3181
  let minDiatonicId = void 0;
3099
3182
  let maxDiatonicId = void 0;
@@ -3121,12 +3204,48 @@ var ObjRhythmColumn = class extends MusicObject {
3121
3204
  }
3122
3205
  });
3123
3206
  }
3207
+ layoutReserveSpace(ctx) {
3208
+ const columns = this.measure.getColumns();
3209
+ const extraSpace = ctx.unitSize;
3210
+ this.getAnchoredLayoutObjects().forEach((obj) => {
3211
+ if (obj.layoutGroup.reserveSpace) {
3212
+ const i = columns.indexOf(this);
3213
+ if (i < 0) return;
3214
+ const leftOverflow = obj.getRect().leftw - this.getRect().leftw;
3215
+ if (leftOverflow > 0) {
3216
+ const prevCol = columns[i - 1];
3217
+ if (prevCol) {
3218
+ prevCol.getAnchoredLayoutObjects().forEach((prevObj) => {
3219
+ if (prevObj.layoutGroupId === obj.layoutGroupId) {
3220
+ const rightOverflow2 = prevObj.getRect().rightw - prevCol.getRect().rightw;
3221
+ this.rect.left -= Math.max(rightOverflow2 + leftOverflow, 0) + extraSpace;
3222
+ this.requestRectUpdate();
3223
+ }
3224
+ });
3225
+ }
3226
+ }
3227
+ const rightOverflow = obj.getRect().rightw - this.getRect().rightw;
3228
+ if (rightOverflow > 0) {
3229
+ const nextCol = columns[i + 1];
3230
+ if (nextCol) {
3231
+ nextCol.getAnchoredLayoutObjects().forEach((nextObj) => {
3232
+ if (nextObj.layoutGroupId === obj.layoutGroupId) {
3233
+ const leftOverflow2 = nextObj.getRect().leftw - nextCol.getRect().leftw;
3234
+ this.rect.right += Math.max(rightOverflow + leftOverflow2, 0) + extraSpace;
3235
+ this.requestRectUpdate();
3236
+ }
3237
+ });
3238
+ }
3239
+ }
3240
+ }
3241
+ });
3242
+ }
3124
3243
  layoutDone() {
3125
3244
  this.needLayout = false;
3126
3245
  }
3127
3246
  updateRect() {
3128
3247
  this.shapeRects = [
3129
- ...this.voiceSymbol.filter((s) => !!s).mapToArray((s) => s.getRect().clone()),
3248
+ ...this.voiceSymbol.filter((s) => s !== void 0).mapToArray((s) => s.getRect().clone()),
3130
3249
  ...this.arpeggios.map((a) => a.getRect().clone())
3131
3250
  ];
3132
3251
  this.rect.top = Math.min(...this.shapeRects.map((r) => r.top));
@@ -3207,8 +3326,8 @@ var _ObjSpecialText = class _ObjSpecialText extends MusicObject {
3207
3326
  let codaText = this.components[1];
3208
3327
  codaSym.layout(ctx);
3209
3328
  codaText.layout(ctx);
3210
- codaSym.offset(0, codaText.getRect().centerY);
3211
- codaText.offset(codaSym.getRect().right, 0);
3329
+ codaSym.setAnchorY(codaText.getRect().centerY);
3330
+ codaText.setLeft(codaSym.getRect().right);
3212
3331
  this.rect = new AnchoredRect11(
3213
3332
  codaSym.getRect().left,
3214
3333
  codaSym.getRect().anchorX,
@@ -3224,8 +3343,8 @@ var _ObjSpecialText = class _ObjSpecialText extends MusicObject {
3224
3343
  let codaSym = this.components[1];
3225
3344
  toCodaText.layout(ctx);
3226
3345
  codaSym.layout(ctx);
3227
- codaSym.offset(0, toCodaText.getRect().centerY);
3228
- toCodaText.offset(codaSym.getRect().left, 0);
3346
+ codaSym.setAnchorY(toCodaText.getRect().centerY);
3347
+ toCodaText.setRight(codaSym.getRect().left);
3229
3348
  this.rect = new AnchoredRect11(
3230
3349
  toCodaText.getRect().left,
3231
3350
  codaSym.getRect().anchorX,
@@ -3804,17 +3923,17 @@ var Player = class _Player {
3804
3923
  };
3805
3924
 
3806
3925
  // src/score/engine/obj-bar-line.ts
3807
- import { AnchoredRect as AnchoredRect13 } from "@tspro/ts-utils-lib";
3808
- var ObjStaffTabBarLine = class extends MusicObject {
3926
+ import { AnchoredRect as AnchoredRect13, UniMap as UniMap4 } from "@tspro/ts-utils-lib";
3927
+ var ObjStaffBarLine = class extends MusicObject {
3809
3928
  constructor(barLine, line) {
3810
3929
  super(line);
3811
3930
  this.barLine = barLine;
3812
3931
  this.line = line;
3813
- __publicField(this, "verticalLines", []);
3932
+ __publicField(this, "vlines", []);
3814
3933
  __publicField(this, "dots", []);
3815
3934
  __publicField(this, "mi");
3816
3935
  line.addObject(this);
3817
- this.mi = new MStaffTabBarLine(this);
3936
+ this.mi = new MStaffBarLine(this);
3818
3937
  }
3819
3938
  getMusicInterface() {
3820
3939
  return this.mi;
@@ -3822,11 +3941,17 @@ var ObjStaffTabBarLine = class extends MusicObject {
3822
3941
  pick(x, y) {
3823
3942
  return this.getRect().contains(x, y) ? [this] : [];
3824
3943
  }
3825
- setRect(r) {
3826
- this.rect = r;
3944
+ updateRect() {
3945
+ this.rect = new AnchoredRect13(0, 0, this.line.getTopLineY(), this.line.getBottomLineY());
3946
+ this.vlines.forEach(
3947
+ (l) => this.rect.expandInPlace(new AnchoredRect13(l.left, l.left + l.width, this.rect.top, this.rect.bottom))
3948
+ );
3949
+ this.dots.forEach(
3950
+ (d) => this.rect.expandInPlace(new AnchoredRect13(d.x - d.r, d.x + d.r, d.y - d.r, d.y + d.r))
3951
+ );
3827
3952
  }
3828
3953
  offset(dx, dy) {
3829
- this.verticalLines.forEach((l) => l.left += dx);
3954
+ this.vlines.forEach((l) => l.left += dx);
3830
3955
  this.dots.forEach((d) => {
3831
3956
  d.x += dx;
3832
3957
  d.y += dy;
@@ -3838,16 +3963,16 @@ var ObjBarLine = class extends MusicObject {
3838
3963
  constructor(measure) {
3839
3964
  super(measure);
3840
3965
  this.measure = measure;
3841
- __publicField(this, "staffTabObjects", []);
3842
- __publicField(this, "staffTabObjectGroups", []);
3966
+ __publicField(this, "notationLineObjects", []);
3967
+ __publicField(this, "notationLineObjectsByGrp", new UniMap4());
3843
3968
  __publicField(this, "barLineType", 0 /* None */);
3844
3969
  }
3845
3970
  pick(x, y) {
3846
3971
  if (!this.getRect().contains(x, y)) {
3847
3972
  return [];
3848
3973
  }
3849
- for (let i = 0; i < this.staffTabObjects.length; i++) {
3850
- let arr = this.staffTabObjects[i].pick(x, y);
3974
+ for (let i = 0; i < this.notationLineObjects.length; i++) {
3975
+ let arr = this.notationLineObjects[i].pick(x, y);
3851
3976
  if (arr.length > 0) {
3852
3977
  return [this, ...arr];
3853
3978
  }
@@ -3856,7 +3981,6 @@ var ObjBarLine = class extends MusicObject {
3856
3981
  }
3857
3982
  layout(ctx) {
3858
3983
  this.requestRectUpdate();
3859
- this.staffTabObjects.length = 0;
3860
3984
  this.barLineType = this.solveBarLineType();
3861
3985
  let { unitSize, _lineWidth } = ctx;
3862
3986
  let { measure, barLineType } = this;
@@ -3866,102 +3990,95 @@ var ObjBarLine = class extends MusicObject {
3866
3990
  let spaceW = 0.7 * unitSize;
3867
3991
  let dotW = DocumentSettings.DotSize * unitSize;
3868
3992
  let dotRadius = dotW / 2;
3869
- row.getNotationLines().forEach((line) => {
3870
- let obj = new ObjStaffTabBarLine(this, line);
3871
- let lineCenterY;
3872
- let lineDotOff;
3873
- let top, bottom;
3874
- const addVerticalLine = (left, width) => {
3875
- obj.verticalLines.push({ left, width });
3876
- };
3877
- const addDotPair = (cx) => {
3878
- for (let i = -1; i <= 1; i += 2) {
3879
- let y = lineCenterY + i * lineDotOff;
3880
- obj.dots.push({ x: cx, y, r: dotRadius });
3993
+ this.notationLineObjects = [];
3994
+ this.notationLineObjectsByGrp.clear();
3995
+ row.getRowGroups().forEach((grp) => {
3996
+ grp.lines.forEach((line) => {
3997
+ let obj = new ObjStaffBarLine(this, line);
3998
+ this.notationLineObjects.push(obj);
3999
+ this.notationLineObjectsByGrp.getOrCreate(grp, []).push(obj);
4000
+ let lineCenterY;
4001
+ let lineDotOff;
4002
+ const addVerticalLine = (left, width) => {
4003
+ obj.vlines.push({ left, width });
4004
+ };
4005
+ const addDotPair = (cx) => {
4006
+ for (let i = -1; i <= 1; i += 2) {
4007
+ let y = lineCenterY + i * lineDotOff;
4008
+ obj.dots.push({ x: cx, y, r: dotRadius });
4009
+ }
4010
+ };
4011
+ if (line instanceof ObjStaff) {
4012
+ lineCenterY = line.getMiddleLineY();
4013
+ lineDotOff = line.getDiatonicSpacing();
4014
+ } else {
4015
+ lineCenterY = (line.getBottomLineY() + line.getTopLineY()) / 2;
4016
+ lineDotOff = (line.getBottomLineY() - line.getTopLineY()) / 6;
3881
4017
  }
3882
- };
3883
- if (line instanceof ObjStaff) {
3884
- lineCenterY = line.getMiddleLineY();
3885
- lineDotOff = line.getDiatonicSpacing();
3886
- } else {
3887
- lineCenterY = (line.getBottomLineY() + line.getTopLineY()) / 2;
3888
- lineDotOff = (line.getBottomLineY() - line.getTopLineY()) / 6;
3889
- }
3890
- top = line.getTopLineY();
3891
- bottom = line.getBottomLineY();
3892
- switch (barLineType) {
3893
- case 0 /* None */:
3894
- obj.setRect(new AnchoredRect13(0, 0, 0, top, 0, bottom));
3895
- break;
3896
- case 1 /* Single */:
3897
- obj.setRect(new AnchoredRect13(-thinW, 0, 0, top, 0, bottom));
3898
- addVerticalLine(-thinW, thinW);
3899
- break;
3900
- case 2 /* Double */:
3901
- obj.setRect(new AnchoredRect13(-thinW - spaceW - thinW, 0, 0, top, 0, bottom));
3902
- addVerticalLine(-thinW - spaceW - thinW, thinW);
3903
- addVerticalLine(-thinW, thinW);
3904
- break;
3905
- case 3 /* EndSong */:
3906
- obj.setRect(new AnchoredRect13(-thicW - spaceW - thinW, 0, 0, top, 0, bottom));
3907
- addVerticalLine(-thinW - spaceW - thicW, thinW);
3908
- addVerticalLine(-thicW, thicW);
3909
- break;
3910
- case 4 /* StartRepeat */:
3911
- obj.setRect(new AnchoredRect13(0, 0, thicW + spaceW + thinW + spaceW + dotW, top, 0, bottom));
3912
- addVerticalLine(0, thicW);
3913
- addVerticalLine(thicW + spaceW, thinW);
3914
- addDotPair(thicW + spaceW + thinW + spaceW + dotRadius);
3915
- break;
3916
- case 5 /* EndRepeat */:
3917
- obj.setRect(new AnchoredRect13(-thicW - spaceW - thinW - spaceW - dotW, 0, 0, top, 0, bottom));
3918
- addVerticalLine(-thinW - spaceW - thicW, thinW);
3919
- addVerticalLine(-thicW, thicW);
3920
- addDotPair(-thinW - spaceW - thicW - spaceW - dotRadius);
3921
- break;
3922
- case 6 /* EndStartRepeat */:
3923
- obj.setRect(new AnchoredRect13(-dotW - spaceW - thinW - spaceW - thicW / 2, 0, thicW / 2 + spaceW + thinW + spaceW + dotW, top, 0, bottom));
3924
- addVerticalLine(-thicW / 2, thicW);
3925
- addVerticalLine(-thicW / 2 - spaceW - thinW, thinW);
3926
- addVerticalLine(thicW / 2 + spaceW, thinW);
3927
- addDotPair(-thicW / 2 - spaceW - thinW - spaceW - dotRadius);
3928
- addDotPair(thicW / 2 + spaceW + thinW + spaceW + dotRadius);
3929
- break;
3930
- }
3931
- this.staffTabObjects.push(obj);
4018
+ switch (barLineType) {
4019
+ case 0 /* None */:
4020
+ break;
4021
+ case 1 /* Single */:
4022
+ addVerticalLine(-thinW, thinW);
4023
+ break;
4024
+ case 2 /* Double */:
4025
+ addVerticalLine(-thinW - spaceW - thinW, thinW);
4026
+ addVerticalLine(-thinW, thinW);
4027
+ break;
4028
+ case 3 /* EndSong */:
4029
+ addVerticalLine(-thinW - spaceW - thicW, thinW);
4030
+ addVerticalLine(-thicW, thicW);
4031
+ break;
4032
+ case 4 /* StartRepeat */:
4033
+ addVerticalLine(0, thicW);
4034
+ addVerticalLine(thicW + spaceW, thinW);
4035
+ addDotPair(thicW + spaceW + thinW + spaceW + dotRadius);
4036
+ break;
4037
+ case 5 /* EndRepeat */:
4038
+ addVerticalLine(-thinW - spaceW - thicW, thinW);
4039
+ addVerticalLine(-thicW, thicW);
4040
+ addDotPair(-thinW - spaceW - thicW - spaceW - dotRadius);
4041
+ break;
4042
+ case 6 /* EndStartRepeat */:
4043
+ addVerticalLine(-thicW / 2, thicW);
4044
+ addVerticalLine(-thicW / 2 - spaceW - thinW, thinW);
4045
+ addVerticalLine(thicW / 2 + spaceW, thinW);
4046
+ addDotPair(-thicW / 2 - spaceW - thinW - spaceW - dotRadius);
4047
+ addDotPair(thicW / 2 + spaceW + thinW + spaceW + dotRadius);
4048
+ break;
4049
+ }
4050
+ obj.forceRectUpdate();
4051
+ });
3932
4052
  });
3933
- this.staffTabObjectGroups = row.getInstrumentLineGroups().map(
3934
- (lines) => lines.map((line) => this.staffTabObjects.find((obj) => obj.line === line)).filter((obj) => obj !== void 0)
3935
- );
3936
4053
  }
3937
4054
  updateRect() {
3938
- if (this.staffTabObjects.length > 0) {
3939
- this.rect = this.staffTabObjects[0].getRect().clone();
3940
- for (let i = 1; i < this.staffTabObjects.length; i++) {
3941
- this.rect.expandInPlace(this.staffTabObjects[i].getRect());
4055
+ if (this.notationLineObjects.length > 0) {
4056
+ this.rect = this.notationLineObjects[0].getRect().clone();
4057
+ for (let i = 1; i < this.notationLineObjects.length; i++) {
4058
+ this.rect.expandInPlace(this.notationLineObjects[i].getRect());
3942
4059
  }
3943
4060
  } else {
3944
4061
  this.rect = new AnchoredRect13();
3945
4062
  }
3946
4063
  }
3947
4064
  offset(dx, dy) {
3948
- this.staffTabObjects.forEach((obj) => obj.offset(dx, 0));
4065
+ this.notationLineObjects.forEach((obj) => obj.offset(dx, 0));
3949
4066
  this.requestRectUpdate();
3950
4067
  }
3951
4068
  draw(ctx) {
3952
- if (this.barLineType === 0 /* None */) {
4069
+ if (this.barLineType === 0 /* None */)
3953
4070
  return;
3954
- }
3955
4071
  ctx.drawDebugRect(this.getRect());
3956
4072
  ctx.color("black");
3957
- this.staffTabObjectGroups.forEach((objs) => {
3958
- if (objs.length > 0) {
3959
- objs.forEach((obj) => obj.dots.forEach((d) => ctx.fillCircle(d.x, d.y, d.r)));
3960
- let top = objs[0].getRect().top;
3961
- let height = objs[objs.length - 1].getRect().bottom - top;
3962
- objs[0].verticalLines.forEach((vline) => ctx.fillRect(vline.left, top, vline.width, height));
3963
- }
3964
- });
4073
+ for (const [grp, objects] of this.notationLineObjectsByGrp) {
4074
+ objects.forEach((obj, i) => {
4075
+ obj.dots.forEach((d) => ctx.fillCircle(d.x, d.y, d.r));
4076
+ if (i === 0) {
4077
+ let { top, height } = obj.barLine.getRect();
4078
+ obj.vlines.forEach((l) => ctx.fillRect(l.left, top, l.width, height));
4079
+ }
4080
+ });
4081
+ }
3965
4082
  }
3966
4083
  };
3967
4084
  var ObjBarLineLeft = class extends ObjBarLine {
@@ -4078,7 +4195,8 @@ var ObjEnding = class extends MusicObject {
4078
4195
  let measureContent = measure.getColumnsContentRect();
4079
4196
  let endingHeight = textRect.height;
4080
4197
  this.rect = new AnchoredRect14(measureContent.left + unitSize, measureContent.right - unitSize, -endingHeight, 0);
4081
- this.endingText.offset(this.rect.left + unitSize / 2, this.rect.bottom);
4198
+ this.endingText.setLeft(this.rect.left + unitSize / 2);
4199
+ this.endingText.setBottom(this.rect.bottom);
4082
4200
  this.shapeRects = [
4083
4201
  new AnchoredRect14(this.rect.left, this.rect.left + 1, this.rect.top, this.rect.bottom),
4084
4202
  new AnchoredRect14(this.rect.left, this.rect.right, this.rect.top, this.rect.top + 1),
@@ -4505,8 +4623,7 @@ var ObjBeamGroup = class _ObjBeamGroup extends MusicObject {
4505
4623
  });
4506
4624
  }
4507
4625
  if (obj.tupletNumber) {
4508
- let y = (left.y + right.y) / 2 + obj.tupletNumberOffsetY;
4509
- obj.tupletNumber.offset(0, -obj.tupletNumber.getRect().anchorY + y);
4626
+ obj.tupletNumber.setAnchorY((left.y + right.y) / 2 + obj.tupletNumberOffsetY);
4510
4627
  }
4511
4628
  });
4512
4629
  }
@@ -5076,7 +5193,7 @@ var ConnectiveProps = class {
5076
5193
  };
5077
5194
 
5078
5195
  // src/score/engine/obj-lyrics.ts
5079
- import { AnchoredRect as AnchoredRect19, Guard as Guard7 } from "@tspro/ts-utils-lib";
5196
+ import { Guard as Guard7 } from "@tspro/ts-utils-lib";
5080
5197
  var ObjLyrics = class extends MusicObject {
5081
5198
  constructor(col, verse, line, vpos, lyricsLength, lyricsText, lyricsOptions) {
5082
5199
  super(col);
@@ -5094,7 +5211,7 @@ var ObjLyrics = class extends MusicObject {
5094
5211
  let halign = (lyricsOptions == null ? void 0 : lyricsOptions.align) === "left" /* Left */ ? 0 : (lyricsOptions == null ? void 0 : lyricsOptions.align) === "right" /* Right */ ? 1 : 0.5;
5095
5212
  this.hyphen = Guard7.isEnumValue(lyricsOptions == null ? void 0 : lyricsOptions.hyphen, LyricsHyphen) ? lyricsOptions == null ? void 0 : lyricsOptions.hyphen : void 0;
5096
5213
  this.text = new ObjText(this, { text: lyricsText, color: this.color, scale: 0.8 }, halign, 0);
5097
- this.rect = new AnchoredRect19();
5214
+ this.rect = this.text.getRect().clone();
5098
5215
  this.mi = new MLyrics(this);
5099
5216
  }
5100
5217
  getMusicInterface() {
@@ -5110,7 +5227,7 @@ var ObjLyrics = class extends MusicObject {
5110
5227
  this.nextLyricsObject = lyricsObj;
5111
5228
  }
5112
5229
  pick(x, y) {
5113
- return this.rect.contains(x, y) ? [this] : [];
5230
+ return this.getRect().contains(x, y) ? [this] : [];
5114
5231
  }
5115
5232
  layout(ctx) {
5116
5233
  this.text.layout(ctx);
@@ -5131,8 +5248,8 @@ var ObjLyrics = class extends MusicObject {
5131
5248
  let maxw = r ? (r.left - l.right) * 0.85 : hyphenw;
5132
5249
  let w = this.hyphen === "-" /* Hyphen */ ? Math.min(hyphenw, maxw) : maxw;
5133
5250
  if (w > 0) {
5134
- let cx = r ? (r.left + l.right) / 2 : l.right + w / 0.85;
5135
- let cy = l.centerY / 2;
5251
+ let cx = r ? (l.right + r.left) / 2 : l.right + w / 0.85;
5252
+ let cy = l.centerY;
5136
5253
  ctx.moveTo(cx - w / 2, cy);
5137
5254
  ctx.lineTo(cx + w / 2, cy);
5138
5255
  ctx.stroke();
@@ -5142,7 +5259,7 @@ var ObjLyrics = class extends MusicObject {
5142
5259
  };
5143
5260
 
5144
5261
  // src/score/engine/obj-tab-rhythm.ts
5145
- import { AnchoredRect as AnchoredRect20, UniMap as UniMap4, Utils as Utils8 } from "@tspro/ts-utils-lib";
5262
+ import { AnchoredRect as AnchoredRect19, UniMap as UniMap5, Utils as Utils8 } from "@tspro/ts-utils-lib";
5146
5263
  var ObjTabRhythm = class extends MusicObject {
5147
5264
  constructor(measure, tab) {
5148
5265
  super(measure);
@@ -5151,9 +5268,9 @@ var ObjTabRhythm = class extends MusicObject {
5151
5268
  __publicField(this, "voiceId");
5152
5269
  __publicField(this, "mi");
5153
5270
  // Keep non-static
5154
- __publicField(this, "tupletPartsTextObjMap", new UniMap4());
5271
+ __publicField(this, "tupletPartsTextObjMap", new UniMap5());
5155
5272
  this.voiceId = getVoiceIds().filter((voiceId) => tab.containsVoiceId(voiceId));
5156
- this.rect = new AnchoredRect20();
5273
+ this.rect = new AnchoredRect19();
5157
5274
  this.mi = new MTabRhythm(this);
5158
5275
  }
5159
5276
  getMusicInterface() {
@@ -5166,7 +5283,7 @@ var ObjTabRhythm = class extends MusicObject {
5166
5283
  let columns = this.measure.getColumns();
5167
5284
  let numColsInVoiceId = getVoiceIds().map((voiceId) => Utils8.Math.sum(columns.map((col) => col.getVoiceSymbol(voiceId) ? 1 : 0)));
5168
5285
  this.voiceId.sort((a, b) => Utils8.Math.cmp(numColsInVoiceId[a], numColsInVoiceId[b]));
5169
- this.rect = new AnchoredRect20();
5286
+ this.rect = new AnchoredRect19();
5170
5287
  }
5171
5288
  hasTuplets() {
5172
5289
  return this.measure.getBeamGroups().some((beamGroup) => beamGroup.isTuplet());
@@ -5217,7 +5334,7 @@ var ObjTabRhythm = class extends MusicObject {
5217
5334
  ctx.lineWidth(1);
5218
5335
  if (symbols.length === 1) {
5219
5336
  for (let i = 0; i < sym.rhythmProps.flagCount; i++) {
5220
- ctx.drawFlag(new AnchoredRect20(colX, colX + flagSize, stemTop + i * flagSize, stemTop + (i + 2) * flagSize), "up");
5337
+ ctx.drawFlag(new AnchoredRect19(colX, colX + flagSize, stemTop + i * flagSize, stemTop + (i + 2) * flagSize), "up");
5221
5338
  }
5222
5339
  }
5223
5340
  for (let i = 0; i < sym.rhythmProps.dotCount; i++) {
@@ -5266,8 +5383,7 @@ var ObjTabRhythm = class extends MusicObject {
5266
5383
  this.tupletPartsTextObjMap.set(text, textObj = new ObjText(this, { text, scale: 0.75 }, 0.5, 0.5));
5267
5384
  textObj.layout(ctx);
5268
5385
  }
5269
- textObj.offset(-textObj.getRect().anchorX, -textObj.getRect().anchorY);
5270
- textObj.offset(cx, stemTop - fontSize / 2);
5386
+ textObj.setCenter(cx, stemTop - fontSize / 2);
5271
5387
  textObj.draw(ctx);
5272
5388
  }
5273
5389
  if (symbols.length > 1) {
@@ -5320,7 +5436,27 @@ function getVerseLayoutGroupId(verse) {
5320
5436
  throw new MusicError13(MusicErrorType13.Unknown, "VerseNumber is not 1, 2 or 3.");
5321
5437
  }
5322
5438
  }
5323
- var _ObjMeasure = class _ObjMeasure extends MusicObject {
5439
+ var MeasureRegions = class {
5440
+ constructor() {
5441
+ __publicField(this, "tabTuning_0", 0);
5442
+ __publicField(this, "signature_1", 0);
5443
+ __publicField(this, "leftBarLine_2", 0);
5444
+ __publicField(this, "padding_3", 0);
5445
+ __publicField(this, "columnsMin_4", 0);
5446
+ __publicField(this, "padding_5", 0);
5447
+ __publicField(this, "rightBarLine_6", 0);
5448
+ }
5449
+ get leftSolid() {
5450
+ return this.tabTuning_0 + this.signature_1 + this.leftBarLine_2 + this.padding_3;
5451
+ }
5452
+ get columnsMin() {
5453
+ return this.columnsMin_4;
5454
+ }
5455
+ get rightSolid() {
5456
+ return this.padding_5 + this.rightBarLine_6;
5457
+ }
5458
+ };
5459
+ var ObjMeasure = class extends MusicObject {
5324
5460
  constructor(row, options) {
5325
5461
  super(row);
5326
5462
  this.row = row;
@@ -5340,12 +5476,9 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5340
5476
  __publicField(this, "barLineRight");
5341
5477
  __publicField(this, "connectives", []);
5342
5478
  __publicField(this, "beamGroups", []);
5343
- __publicField(this, "tabStringNotesWidth", 0);
5344
5479
  __publicField(this, "measureId");
5480
+ __publicField(this, "regions", new MeasureRegions());
5345
5481
  __publicField(this, "needLayout", true);
5346
- __publicField(this, "leftSolidAreaWidth", 0);
5347
- __publicField(this, "minColumnsAreaWidth", 0);
5348
- __publicField(this, "rightSolidAreaWidth", 0);
5349
5482
  __publicField(this, "voiceSymbols", asMulti(new IndexArray2()));
5350
5483
  __publicField(this, "lastAddedRhythmColumn");
5351
5484
  __publicField(this, "lastAddedRhythmSymbol");
@@ -5361,7 +5494,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
5361
5494
  __publicField(this, "endRepeatPlayCount", 2);
5362
5495
  // play twice.
5363
5496
  __publicField(this, "endRepeatPlayCountText");
5364
- __publicField(this, "staticObjectsCache", new UniMap5());
5497
+ __publicField(this, "staticObjectsCache", new UniMap6());
5365
5498
  __publicField(this, "lyricsObjectsCache", new TriMap2());
5366
5499
  __publicField(this, "mi");
5367
5500
  this.mi = new MMeasure(this);
@@ -6014,34 +6147,34 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
6014
6147
  }
6015
6148
  // Get content rect excluding signature
6016
6149
  getColumnsContentRect() {
6017
- return new AnchoredRect21(
6150
+ return new AnchoredRect20(
6018
6151
  this.barLineLeft.getRect().anchorX,
6019
6152
  this.barLineRight.getRect().anchorX,
6020
6153
  this.getRect().top,
6021
6154
  this.getRect().bottom
6022
6155
  );
6023
6156
  }
6024
- getLeftSolidAreaWidth() {
6025
- return this.leftSolidAreaWidth;
6157
+ getLeftSolidWidth() {
6158
+ return this.regions.leftSolid;
6026
6159
  }
6027
- getMinColumnsAreaWidth() {
6028
- return this.minColumnsAreaWidth;
6160
+ getMinColumnsWidth() {
6161
+ return this.regions.columnsMin;
6029
6162
  }
6030
- getRightSolidAreaWidth() {
6031
- return this.rightSolidAreaWidth;
6163
+ getRightSolidWidth() {
6164
+ return this.regions.rightSolid;
6032
6165
  }
6033
- getSolidAreaWidth() {
6034
- return this.leftSolidAreaWidth + this.rightSolidAreaWidth;
6166
+ getTotalSolidWidth() {
6167
+ return this.getLeftSolidWidth() + this.getRightSolidWidth();
6035
6168
  }
6036
6169
  getMinWidth() {
6037
- return this.leftSolidAreaWidth + this.minColumnsAreaWidth + this.rightSolidAreaWidth;
6170
+ return this.getLeftSolidWidth() + this.getMinColumnsWidth() + this.getRightSolidWidth();
6038
6171
  }
6039
6172
  getStaffLineLeft() {
6040
6173
  let prev = this.getPrevMeasure();
6041
6174
  if (prev && prev.row === this.row && !prev.hasPostMeasureBreak()) {
6042
6175
  return prev.getStaffLineRight();
6043
6176
  } else {
6044
- return this.getRect().left + this.tabStringNotesWidth;
6177
+ return this.getRect().left + this.regions.tabTuning_0;
6045
6178
  }
6046
6179
  }
6047
6180
  getStaffLineRight() {
@@ -6255,7 +6388,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
6255
6388
  this.postMeasureBreakWidth = this.hasPostMeasureBreak() ? DocumentSettings.PostMeasureBreakWidth * unitSize : 0;
6256
6389
  let isFirstMeasureInRow = this === this.row.getFirstMeasure();
6257
6390
  let isAfterMeasureBreak = ((_a = this.getPrevMeasure()) == null ? void 0 : _a.hasPostMeasureBreak()) === true;
6258
- this.tabStringNotesWidth = isFirstMeasureInRow && this.row.hasTab ? unitSize * 4 : 0;
6391
+ this.regions.tabTuning_0 = isFirstMeasureInRow && this.row.hasTab ? unitSize * 4 : 0;
6259
6392
  let showClef = isFirstMeasureInRow || isAfterMeasureBreak;
6260
6393
  let showMeasureNumber = this.options.showNumber === false ? false : this.options.showNumber === true || isFirstMeasureInRow && !this.row.isFirstRow();
6261
6394
  let showKeySignature = isFirstMeasureInRow || isAfterMeasureBreak || !!this.alterKeySignature;
@@ -6292,7 +6425,8 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
6292
6425
  let note = tab.getTuningStrings()[stringId].format(PitchNotation.Helmholtz, SymbolSet.Unicode);
6293
6426
  let obj = new ObjText(this, { text: note, scale: 0.8 }, 1, 0.5);
6294
6427
  obj.layout(ctx);
6295
- obj.offset(this.tabStringNotesWidth * 0.8, tab.getStringY(stringId));
6428
+ obj.setRight(this.regions.tabTuning_0 * 0.8);
6429
+ obj.setCenterY(tab.getStringY(stringId));
6296
6430
  this.tabStringNotes.push(obj);
6297
6431
  tab.addObject(obj);
6298
6432
  }
@@ -6301,50 +6435,54 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
6301
6435
  this.barLineLeft.layout(ctx);
6302
6436
  const accState = new AccidentalState(this);
6303
6437
  this.columns.forEach((col) => col.layout(ctx, accState));
6438
+ this.columns.forEach((col) => col.layoutReserveSpace(ctx));
6304
6439
  this.barLineRight.layout(ctx);
6305
- if (this.endRepeatPlayCountText) {
6440
+ if (this.endRepeatPlayCountText)
6306
6441
  this.endRepeatPlayCountText.layout(ctx);
6307
- }
6308
- this.layoutObjects.forEach((layoutObj) => layoutObj.layout(ctx));
6442
+ this.layoutObjects.forEach((obj) => obj.layout(ctx));
6309
6443
  let padding = ctx.unitSize;
6310
- this.leftSolidAreaWidth = this.tabStringNotesWidth + Math.max(0, ...this.signatures.map((signature) => signature.getRect().width)) + this.barLineLeft.getRect().width + padding;
6311
- this.rightSolidAreaWidth = padding + this.barLineRight.getRect().width;
6312
- this.minColumnsAreaWidth = 0;
6313
- this.columns.forEach((col) => this.minColumnsAreaWidth += col.getRect().width);
6314
- this.minColumnsAreaWidth = Math.max(this.minColumnsAreaWidth, _ObjMeasure.MinFlexContentWidth * unitSize);
6444
+ this.regions.signature_1 = Math.max(0, ...this.signatures.map((signature) => signature.getRect().width));
6445
+ this.regions.leftBarLine_2 = this.barLineLeft.getRect().width;
6446
+ this.regions.padding_3 = padding;
6447
+ this.regions.columnsMin_4 = Math.max(
6448
+ DocumentSettings.MinColumnsWidth * unitSize,
6449
+ this.columns.map((col) => col.getRect().width).reduce((acc, cur) => acc + cur)
6450
+ );
6451
+ this.regions.padding_5 = padding;
6452
+ this.regions.rightBarLine_6 = this.barLineRight.getRect().width;
6315
6453
  }
6316
6454
  layoutWidth(ctx, width) {
6317
6455
  if (!this.needLayout) {
6318
6456
  return;
6319
6457
  }
6320
6458
  width = Math.max(width, this.getMinWidth());
6321
- this.rect = new AnchoredRect21();
6459
+ this.rect = new AnchoredRect20();
6322
6460
  this.rect.anchorX = this.rect.left + width / 2;
6323
6461
  this.rect.right = this.rect.left + width;
6324
- let rect;
6325
6462
  this.signatures.forEach((signature) => {
6326
- rect = signature.getRect();
6327
- signature.offset(this.rect.left + this.tabStringNotesWidth - rect.left, -rect.anchorY);
6463
+ signature.setLeft(this.rect.left + this.regions.tabTuning_0);
6464
+ signature.setAnchorY(this.rect.anchorY);
6328
6465
  });
6329
6466
  let signaturesWidth = Math.max(0, ...this.signatures.map((signature) => signature.getRect().width));
6330
- rect = this.barLineLeft.getRect();
6331
- this.barLineLeft.offset(this.rect.left + this.tabStringNotesWidth + signaturesWidth - rect.left, -rect.anchorY);
6332
- rect = this.barLineRight.getRect();
6333
- this.barLineRight.offset(this.rect.right - rect.right, -rect.anchorY);
6467
+ this.barLineLeft.setLeft(this.rect.left + this.regions.tabTuning_0 + signaturesWidth);
6468
+ this.barLineLeft.setAnchorY(this.rect.anchorY);
6469
+ this.barLineRight.setRight(this.rect.right);
6470
+ this.barLineRight.setAnchorY(this.rect.anchorY);
6334
6471
  if (this.endRepeatPlayCountText) {
6335
- this.endRepeatPlayCountText.offset(this.barLineRight.getRect().left, this.barLineRight.getRect().top);
6336
- }
6337
- let columnsAreaLeft = this.rect.left + this.leftSolidAreaWidth;
6338
- let columnsAreaRight = this.rect.right - this.rightSolidAreaWidth;
6339
- let columnsAreaWidth = columnsAreaRight - columnsAreaLeft;
6340
- let columnsWidth = Utils9.Math.sum(this.columns.map((col) => col.getRect().width));
6341
- let columnScale = columnsAreaWidth / columnsWidth;
6342
- let columnLeft = columnsAreaLeft;
6472
+ this.endRepeatPlayCountText.setCenterX(this.barLineRight.getRect().left);
6473
+ this.endRepeatPlayCountText.setBottom(this.barLineRight.getRect().top);
6474
+ }
6475
+ let columnsLeft = this.rect.left + this.regions.leftSolid;
6476
+ let columnsRight = this.rect.right - this.regions.rightSolid;
6477
+ let columnsWidth = columnsRight - columnsLeft;
6478
+ let columnsMinWidth = this.regions.columnsMin;
6479
+ let columnScale = columnsWidth / columnsMinWidth;
6480
+ let curColumnLeft = columnsLeft;
6343
6481
  this.columns.forEach((col) => {
6344
- rect = col.getRect();
6345
- let columnAnchorX = columnLeft + rect.leftw * columnScale;
6346
- col.offset(columnAnchorX - rect.anchorX, -rect.anchorY);
6347
- columnLeft += rect.width * columnScale;
6482
+ let rect = col.getRect();
6483
+ let columnAnchorX = curColumnLeft + rect.leftw * columnScale;
6484
+ col.setAnchor(columnAnchorX, this.rect.anchorY);
6485
+ curColumnLeft += rect.width * columnScale;
6348
6486
  });
6349
6487
  getVoiceIds().forEach((voiceId) => {
6350
6488
  const symbols = this.getVoiceSymbols(voiceId);
@@ -6352,8 +6490,7 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
6352
6490
  if (!onlyRest) return;
6353
6491
  const isOnlySymbolInCol = getVoiceIds().map((voiceId2) => onlyRest.col.getVoiceSymbol(voiceId2)).filter((sym) => sym !== void 0 && sym !== onlyRest).length === 0;
6354
6492
  if (isOnlySymbolInCol) return;
6355
- const r = this.getColumnsContentRect();
6356
- onlyRest.offset(r.centerX - onlyRest.getRect().anchorX, 0);
6493
+ onlyRest.setAnchorX(this.getColumnsContentRect().centerX);
6357
6494
  });
6358
6495
  }
6359
6496
  layoutConnectives(ctx) {
@@ -6422,9 +6559,8 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
6422
6559
  this.barLineLeft.offset(dx, dy);
6423
6560
  this.columns.forEach((col) => col.offset(dx, dy));
6424
6561
  this.barLineRight.offset(dx, dy);
6425
- if (this.endRepeatPlayCountText) {
6562
+ if (this.endRepeatPlayCountText)
6426
6563
  this.endRepeatPlayCountText.offset(dx, dy);
6427
- }
6428
6564
  this.connectives.forEach((connective) => connective.offset(dx, 0));
6429
6565
  this.beamGroups.forEach((beam) => beam.offset(dx, dy));
6430
6566
  this.layoutObjects.forEach((layoutObj) => layoutObj.offset(dx, 0));
@@ -6461,12 +6597,10 @@ var _ObjMeasure = class _ObjMeasure extends MusicObject {
6461
6597
  this.beamGroups.forEach((beam) => beam.draw(ctx));
6462
6598
  }
6463
6599
  };
6464
- __publicField(_ObjMeasure, "MinFlexContentWidth", 10);
6465
- var ObjMeasure = _ObjMeasure;
6466
6600
 
6467
6601
  // src/score/engine/layout-object.ts
6468
6602
  import { MusicError as MusicError14, MusicErrorType as MusicErrorType14 } from "@tspro/web-music-score/core";
6469
- import { AnchoredRect as AnchoredRect22, asMulti as asMulti2, IndexArray as IndexArray3, UniMap as UniMap6 } from "@tspro/ts-utils-lib";
6603
+ import { AnchoredRect as AnchoredRect21, asMulti as asMulti2, IndexArray as IndexArray3, UniMap as UniMap7 } from "@tspro/ts-utils-lib";
6470
6604
  var LayoutGroupId = /* @__PURE__ */ ((LayoutGroupId2) => {
6471
6605
  LayoutGroupId2[LayoutGroupId2["TabRhythm"] = 0] = "TabRhythm";
6472
6606
  LayoutGroupId2[LayoutGroupId2["Fermata"] = 1] = "Fermata";
@@ -6481,18 +6615,18 @@ var LayoutGroupId = /* @__PURE__ */ ((LayoutGroupId2) => {
6481
6615
  LayoutGroupId2[LayoutGroupId2["LyricsVerse3"] = 10] = "LyricsVerse3";
6482
6616
  return LayoutGroupId2;
6483
6617
  })(LayoutGroupId || {});
6484
- var LayoutGroupIdAttrs = new UniMap6([
6618
+ var LayoutGroupIdAttrs = new UniMap7([
6485
6619
  [0 /* TabRhythm */, { rowAlign: true }],
6486
- [1 /* Fermata */, {}],
6487
- [2 /* NoteLabel */, { widen: true }],
6620
+ [1 /* Fermata */, { reserveSpace: true }],
6621
+ [2 /* NoteLabel */, { reserveSpace: true }],
6488
6622
  [3 /* Navigation */, { rowAlign: true }],
6489
6623
  [4 /* Ending */, { rowAlign: true, padding: 2 }],
6490
6624
  [5 /* TempoAnnotation */, { rowAlign: true, padding: 2 }],
6491
6625
  [6 /* DynamicsAnnotation */, { rowAlign: true, padding: 2 }],
6492
- [7 /* ChordLabel */, { widen: true, rowAlign: true }],
6493
- [8 /* LyricsVerse1 */, { rowAlign: true }],
6494
- [9 /* LyricsVerse2 */, { rowAlign: true }],
6495
- [10 /* LyricsVerse3 */, { rowAlign: true }]
6626
+ [7 /* ChordLabel */, { reserveSpace: true, rowAlign: true }],
6627
+ [8 /* LyricsVerse1 */, { reserveSpace: true, rowAlign: true }],
6628
+ [9 /* LyricsVerse2 */, { reserveSpace: true, rowAlign: true }],
6629
+ [10 /* LyricsVerse3 */, { reserveSpace: true, rowAlign: true }]
6496
6630
  ]);
6497
6631
  function requireParentMeasure(p) {
6498
6632
  while (p) {
@@ -6553,7 +6687,7 @@ var LayoutObjectWrapper = class {
6553
6687
  let staticShapeRects = staticObj.getShapeRects();
6554
6688
  objShapeRects.forEach((objR) => {
6555
6689
  staticShapeRects.forEach((staticR) => {
6556
- if (AnchoredRect22.overlapX(objR, staticR)) {
6690
+ if (AnchoredRect21.overlapX(objR, staticR)) {
6557
6691
  y = verticalPos === 1 /* Below */ ? Math.max(y, staticR.bottom + objR.toph + objR.anchorY) : Math.min(y, staticR.top - objR.bottomh - objR.anchorY);
6558
6692
  }
6559
6693
  });
@@ -6574,6 +6708,9 @@ var LayoutObjectWrapper = class {
6574
6708
  offset(dx, dy) {
6575
6709
  this.musicObj.offset(dx, dy);
6576
6710
  }
6711
+ setAnchorY(y) {
6712
+ this.musicObj.setAnchorY(y);
6713
+ }
6577
6714
  getRect() {
6578
6715
  return this.musicObj.getRect();
6579
6716
  }
@@ -6584,11 +6721,11 @@ var LayoutGroup = class {
6584
6721
  // key = VerticalPos
6585
6722
  __publicField(this, "layoutObject", asMulti2(new IndexArray3()));
6586
6723
  __publicField(this, "rowAlign");
6587
- __publicField(this, "widensColumn");
6724
+ __publicField(this, "reserveSpace");
6588
6725
  __publicField(this, "padding");
6589
6726
  var _a, _b, _c, _d;
6590
6727
  this.rowAlign = ((_a = LayoutGroupIdAttrs.get(layoutGroupId)) == null ? void 0 : _a.rowAlign) === true;
6591
- this.widensColumn = ((_b = LayoutGroupIdAttrs.get(layoutGroupId)) == null ? void 0 : _b.widen) === true;
6728
+ this.reserveSpace = ((_b = LayoutGroupIdAttrs.get(layoutGroupId)) == null ? void 0 : _b.reserveSpace) === true;
6592
6729
  this.padding = (_d = (_c = LayoutGroupIdAttrs.get(layoutGroupId)) == null ? void 0 : _c.padding) != null ? _d : 0;
6593
6730
  }
6594
6731
  getLayoutObjects(verticalPos) {
@@ -6617,7 +6754,7 @@ var ObjNotationLine5 = class extends MusicObject {
6617
6754
  super(row);
6618
6755
  this.row = row;
6619
6756
  __publicField(this, "objects", []);
6620
- __publicField(this, "layoutGroups", new UniMap7());
6757
+ __publicField(this, "layoutGroups", new UniMap8());
6621
6758
  }
6622
6759
  addObject(o) {
6623
6760
  this.objects.push(o);
@@ -6644,7 +6781,7 @@ var ObjNotationLine5 = class extends MusicObject {
6644
6781
  if (y === void 0) {
6645
6782
  return;
6646
6783
  }
6647
- layoutObj.offset(0, y - layoutObj.getRect().anchorY);
6784
+ layoutObj.setAnchorY(y - layoutObj.getRect().anchorY);
6648
6785
  layoutObj.setPositionResolved();
6649
6786
  }
6650
6787
  alignObjectsY(ctx, layoutObjects, verticalPos) {
@@ -6665,7 +6802,7 @@ var ObjNotationLine5 = class extends MusicObject {
6665
6802
  if (musicObj instanceof ObjEnding || musicObj instanceof ObjExtensionLine || musicObj instanceof ObjTabRhythm) {
6666
6803
  musicObj.layoutFitToMeasure(ctx);
6667
6804
  } else {
6668
- musicObj.offset(anchor.getRect().anchorX - musicObj.getRect().anchorX, 0);
6805
+ musicObj.setAnchorX(anchor.getRect().anchorX);
6669
6806
  }
6670
6807
  });
6671
6808
  if (layoutGroup.rowAlign) {
@@ -6815,7 +6952,7 @@ var ObjStaff = class extends ObjNotationLine5 {
6815
6952
  let h = unitSize * DocumentSettings.StaffHeight;
6816
6953
  this.topLineY = -h / 2;
6817
6954
  this.bottomLineY = h / 2;
6818
- this.rect = new AnchoredRect23(0, 0, this.topLineY, this.bottomLineY);
6955
+ this.rect = new AnchoredRect22(0, 0, this.topLineY, this.bottomLineY);
6819
6956
  }
6820
6957
  layoutWidth(ctx) {
6821
6958
  this.rect.left = this.row.getRect().left;
@@ -6921,7 +7058,7 @@ var ObjTab = class extends ObjNotationLine5 {
6921
7058
  let h = unitSize * DocumentSettings.TabHeight;
6922
7059
  this.top = -h / 2;
6923
7060
  this.bottom = h / 2;
6924
- this.rect = new AnchoredRect23(0, 0, this.top, this.bottom);
7061
+ this.rect = new AnchoredRect22(0, 0, this.top, this.bottom);
6925
7062
  }
6926
7063
  layoutWidth(ctx) {
6927
7064
  this.rect.left = this.row.getRect().left;
@@ -6946,6 +7083,111 @@ var ObjTab = class extends ObjNotationLine5 {
6946
7083
  // src/score/engine/obj-score-row.ts
6947
7084
  import { MusicError as MusicError16, MusicErrorType as MusicErrorType16 } from "@tspro/web-music-score/core";
6948
7085
  import { AnchoredRect as AnchoredRect24, Guard as Guard10, Utils as Utils11 } from "@tspro/ts-utils-lib";
7086
+
7087
+ // src/score/engine/obj-score-row-group.ts
7088
+ import { AnchoredRect as AnchoredRect23 } from "@tspro/ts-utils-lib";
7089
+ var ObjScoreRowGroup = class extends MusicObject {
7090
+ constructor(lines) {
7091
+ var _a;
7092
+ super(lines[0].row);
7093
+ this.lines = lines;
7094
+ __publicField(this, "space", 0);
7095
+ __publicField(this, "instrument");
7096
+ __publicField(this, "instrText");
7097
+ __publicField(this, "braceRect", new AnchoredRect23());
7098
+ __publicField(this, "mi");
7099
+ this.instrument = (_a = lines[0].getConfig().instrument) != null ? _a : "";
7100
+ this.instrText = new ObjText(this, { text: this.instrument, color: "black", scale: 1 }, 1, 0.5);
7101
+ this.mi = new MScoreRowGroup(this);
7102
+ }
7103
+ getMusicInterface() {
7104
+ return this.mi;
7105
+ }
7106
+ get row() {
7107
+ return this.lines[0].row;
7108
+ }
7109
+ get hasBrace() {
7110
+ return this.hasInstrument && this.lines.length > 1;
7111
+ }
7112
+ get hasInstrument() {
7113
+ return this.instrument.length > 0;
7114
+ }
7115
+ pick(x, y) {
7116
+ if (!this.getRect().contains(x, y))
7117
+ return [];
7118
+ let arr = this.instrText.pick(x, y);
7119
+ if (arr.length > 0) {
7120
+ return [this, ...arr];
7121
+ }
7122
+ return [this];
7123
+ }
7124
+ updateRect() {
7125
+ this.instrText.setRight(this.braceRect.left - this.space);
7126
+ this.instrText.setCenterY(this.braceRect.anchorY);
7127
+ this.rect = this.instrText.getRect().clone().expandInPlace(this.braceRect);
7128
+ }
7129
+ layout(ctx) {
7130
+ this.space = ctx.unitSize;
7131
+ this.instrText.layout(ctx);
7132
+ this.braceRect = new AnchoredRect23(-(this.hasBrace ? ctx.unitSize * 5 : 0), 0, 0, 0);
7133
+ this.forceRectUpdate();
7134
+ }
7135
+ layoutToNotationLines() {
7136
+ this.braceRect.top = this.lines[0].getTopLineY();
7137
+ this.braceRect.bottom = this.lines[this.lines.length - 1].getBottomLineY();
7138
+ this.braceRect.anchorY = this.braceRect.centerY;
7139
+ this.forceRectUpdate();
7140
+ }
7141
+ offset(dx, dy) {
7142
+ this.instrText.offset(dx, dy);
7143
+ this.braceRect.offsetInPlace(dx, dy);
7144
+ this.rect.offsetInPlace(dx, dy);
7145
+ }
7146
+ draw(ctx) {
7147
+ this.instrText.draw(ctx);
7148
+ if (this.hasBrace) {
7149
+ ctx.color("brack").lineWidth(1).drawBracket(this.braceRect, "{");
7150
+ }
7151
+ }
7152
+ };
7153
+
7154
+ // src/score/engine/obj-score-row.ts
7155
+ var ScoreRowRegions = class {
7156
+ constructor() {
7157
+ __publicField(this, "instrWidth", 0);
7158
+ __publicField(this, "staffWidth", 0);
7159
+ }
7160
+ resetWidths() {
7161
+ this.instrWidth = this.staffWidth = 0;
7162
+ }
7163
+ addRowInstrWidth(w) {
7164
+ this.instrWidth = Math.max(this.instrWidth, w);
7165
+ }
7166
+ addRowstaffWidth(w) {
7167
+ this.staffWidth = Math.max(this.staffWidth, w);
7168
+ }
7169
+ get instrLeft() {
7170
+ return 0;
7171
+ }
7172
+ get instrRight() {
7173
+ return this.instrWidth;
7174
+ }
7175
+ get staffLeft() {
7176
+ return this.instrRight;
7177
+ }
7178
+ get staffRight() {
7179
+ return this.staffLeft + this.staffWidth;
7180
+ }
7181
+ get left() {
7182
+ return this.instrLeft;
7183
+ }
7184
+ get right() {
7185
+ return this.staffRight;
7186
+ }
7187
+ get width() {
7188
+ return this.instrWidth + this.staffWidth;
7189
+ }
7190
+ };
6949
7191
  var ObjScoreRow = class extends MusicObject {
6950
7192
  constructor(doc, prevRow, scoreConfig) {
6951
7193
  super(doc);
@@ -6953,12 +7195,10 @@ var ObjScoreRow = class extends MusicObject {
6953
7195
  this.prevRow = prevRow;
6954
7196
  this.scoreConfig = scoreConfig;
6955
7197
  __publicField(this, "nextRow");
6956
- __publicField(this, "minWidth", 0);
6957
7198
  __publicField(this, "notationLines");
6958
- __publicField(this, "instrumentLineGroups");
7199
+ __publicField(this, "rowGroups");
6959
7200
  __publicField(this, "staves");
6960
7201
  __publicField(this, "tabs");
6961
- __publicField(this, "instrumentNames");
6962
7202
  __publicField(this, "measures", []);
6963
7203
  __publicField(this, "needLayout", true);
6964
7204
  __publicField(this, "mi");
@@ -6975,10 +7215,7 @@ var ObjScoreRow = class extends MusicObject {
6975
7215
  prevGroup.push(line);
6976
7216
  }
6977
7217
  }
6978
- this.instrumentLineGroups = lineGroups;
6979
- this.instrumentNames = this.instrumentLineGroups.map((lines) => {
6980
- return lines.length > 0 && Guard10.isNonEmptyString(lines[0].getConfig().instrument) ? new ObjText(this, String(lines[0].getConfig().instrument), 0, 0.5) : void 0;
6981
- });
7218
+ this.rowGroups = lineGroups.filter((lines) => lines.length > 0).map((lines) => new ObjScoreRowGroup(lines));
6982
7219
  if (this.prevRow) {
6983
7220
  this.prevRow.nextRow = this;
6984
7221
  }
@@ -7002,14 +7239,17 @@ var ObjScoreRow = class extends MusicObject {
7002
7239
  getNotationLines() {
7003
7240
  return this.notationLines;
7004
7241
  }
7005
- getInstrumentLineGroups() {
7006
- return this.instrumentLineGroups;
7242
+ getRowGroups() {
7243
+ return this.rowGroups;
7007
7244
  }
7008
7245
  findMatchingLine(line) {
7009
7246
  return line.row === this ? line : this.notationLines.find(
7010
7247
  (curLine) => Utils11.Obj.deepEqual(line.row.scoreConfig, curLine.row.scoreConfig) && line.id === curLine.id || Guard10.isNonEmptyString(line.getConfig().name) && line.getConfig().name === curLine.getConfig().name && line.getConfig().type === curLine.getConfig().type
7011
7248
  );
7012
7249
  }
7250
+ get regions() {
7251
+ return this.doc.regions;
7252
+ }
7013
7253
  getStaves() {
7014
7254
  return this.staves;
7015
7255
  }
@@ -7055,7 +7295,6 @@ var ObjScoreRow = class extends MusicObject {
7055
7295
  this.notationLines.forEach((line) => line.layoutLayoutGroups(ctx));
7056
7296
  }
7057
7297
  pick(x, y) {
7058
- var _a, _b;
7059
7298
  if (!this.getRect().contains(x, y)) {
7060
7299
  return [];
7061
7300
  }
@@ -7065,8 +7304,8 @@ var ObjScoreRow = class extends MusicObject {
7065
7304
  return [this, ...arr];
7066
7305
  }
7067
7306
  }
7068
- for (let i = 0; i < this.instrumentNames.length; i++) {
7069
- let arr = (_b = (_a = this.instrumentNames[i]) == null ? void 0 : _a.pick(x, y)) != null ? _b : [];
7307
+ for (let i = 0; i < this.rowGroups.length; i++) {
7308
+ let arr = this.rowGroups[i].pick(x, y);
7070
7309
  if (arr.length > 0) {
7071
7310
  return [this, ...arr];
7072
7311
  }
@@ -7119,9 +7358,6 @@ var ObjScoreRow = class extends MusicObject {
7119
7358
  getLastMeasure() {
7120
7359
  return this.measures.length > 0 ? this.measures[this.measures.length - 1] : void 0;
7121
7360
  }
7122
- getMinWidth() {
7123
- return this.minWidth;
7124
- }
7125
7361
  solveAutoStemDir(symbols) {
7126
7362
  if (symbols.length === 0) {
7127
7363
  return "up" /* Up */;
@@ -7138,9 +7374,6 @@ var ObjScoreRow = class extends MusicObject {
7138
7374
  return staves.length > 0 ? avgDiatonicId >= staves[0].middleLineDiatonicId ? "down" /* Down */ : "up" /* Up */ : "up" /* Up */;
7139
7375
  }
7140
7376
  }
7141
- getInstrumentNameWidth(ctx) {
7142
- return Math.max(0, ...this.instrumentNames.map((obj) => obj ? obj.getRect().width : 0));
7143
- }
7144
7377
  requestLayout() {
7145
7378
  if (!this.needLayout) {
7146
7379
  this.needLayout = true;
@@ -7152,37 +7385,39 @@ var ObjScoreRow = class extends MusicObject {
7152
7385
  return;
7153
7386
  }
7154
7387
  this.requestRectUpdate();
7155
- this.instrumentNames.forEach((obj) => obj == null ? void 0 : obj.layout(ctx));
7156
7388
  this.notationLines.forEach((line) => {
7157
7389
  line.removeObjects();
7158
7390
  line.layoutHeight(ctx);
7159
7391
  });
7160
- this.minWidth = 0;
7161
- this.measures.forEach((m) => {
7162
- m.layout(ctx);
7163
- this.minWidth += m.getMinWidth();
7164
- this.minWidth += m.getPostMeasureBreakWidth();
7392
+ this.rowGroups.forEach((grp) => {
7393
+ grp.layout(ctx);
7394
+ this.regions.addRowInstrWidth(grp.getRect().width);
7165
7395
  });
7396
+ this.measures.forEach((m) => m.layout(ctx));
7397
+ let packedWidth = this.measures.map((m) => m.getMinWidth() + m.getPostMeasureBreakWidth()).reduce((acc, cur) => acc + cur);
7398
+ this.regions.addRowstaffWidth(packedWidth);
7166
7399
  }
7167
- layoutWidth(ctx, left, right) {
7400
+ layoutStretch(ctx) {
7168
7401
  if (!this.needLayout) {
7169
7402
  return;
7170
7403
  }
7171
- this.rect = new AnchoredRect24(0, right, 0, 0);
7404
+ this.rect = new AnchoredRect24(this.regions.left, this.regions.right, 0, 0);
7172
7405
  this.notationLines.forEach((line) => line.layoutWidth(ctx));
7173
- let targetColumnsAreaWidth = right - left;
7406
+ this.rowGroups.forEach((grp) => grp.setRight(this.regions.instrRight));
7407
+ let targetColumnsAreaWidth = this.regions.staffWidth;
7174
7408
  let minColumnsAreaWidth = 0;
7175
7409
  this.measures.forEach((m) => {
7176
- targetColumnsAreaWidth -= m.getSolidAreaWidth() + m.getPostMeasureBreakWidth();
7177
- minColumnsAreaWidth += m.getMinColumnsAreaWidth();
7410
+ targetColumnsAreaWidth -= m.getTotalSolidWidth() + m.getPostMeasureBreakWidth();
7411
+ minColumnsAreaWidth += m.getMinColumnsWidth();
7178
7412
  });
7179
7413
  let columnsAreaScale = targetColumnsAreaWidth / minColumnsAreaWidth;
7180
- let x = this.doc.getInstrumentGroupSize(ctx).braceRight;
7414
+ let x = this.regions.staffLeft;
7181
7415
  this.measures.forEach((m) => {
7182
- let newMeasureWidth = m.getSolidAreaWidth() + m.getMinColumnsAreaWidth() * columnsAreaScale;
7416
+ let newMeasureWidth = m.getTotalSolidWidth() + m.getMinColumnsWidth() * columnsAreaScale;
7183
7417
  m.layoutWidth(ctx, newMeasureWidth);
7184
7418
  let r = m.getRect();
7185
- m.offset(x - r.left, -r.anchorY);
7419
+ m.setLeft(x);
7420
+ m.setAnchorY(0);
7186
7421
  x += r.width;
7187
7422
  x += m.getPostMeasureBreakWidth();
7188
7423
  });
@@ -7192,10 +7427,19 @@ var ObjScoreRow = class extends MusicObject {
7192
7427
  });
7193
7428
  }
7194
7429
  updateRect() {
7195
- let left = 0;
7196
- let right = this.measures.length > 0 ? this.measures[this.measures.length - 1].getRect().right : left;
7197
- let top = this.measures.length > 0 ? Math.min(...this.measures.map((m) => m.getRect().top)) : 0;
7198
- let bottom = this.measures.length > 0 ? Math.max(...this.measures.map((m) => m.getRect().bottom)) : 0;
7430
+ var _a;
7431
+ let left = this.regions.left;
7432
+ let right = this.regions.right;
7433
+ let top = 0;
7434
+ let bottom = 0;
7435
+ const fermata = (_a = this.getLastMeasure()) == null ? void 0 : _a.getBarLineRight().getAnchoredLayoutObjects().map((o) => o.musicObj).find((o) => o instanceof ObjFermata);
7436
+ if (fermata) {
7437
+ right = Math.max(right, fermata.getRect().right);
7438
+ }
7439
+ if (this.measures.length > 0) {
7440
+ top = Math.min(...this.measures.map((m) => m.getRect().top));
7441
+ bottom = Math.max(...this.measures.map((m) => m.getRect().bottom));
7442
+ }
7199
7443
  this.rect = new AnchoredRect24(left, right, top, bottom);
7200
7444
  }
7201
7445
  alignStemsToBeams() {
@@ -7208,10 +7452,10 @@ var ObjScoreRow = class extends MusicObject {
7208
7452
  let cur = this.notationLines[i];
7209
7453
  if (prev instanceof ObjStaff && cur instanceof ObjStaff && prev.staffConfig.grandId !== void 0 && prev.staffConfig.grandId === cur.staffConfig.grandId) {
7210
7454
  let dy = prev.getBottomLineY() - cur.getTopLineY() + unitSize * 6;
7211
- cur.offset(0, dy);
7455
+ cur.offsetY(dy);
7212
7456
  } else {
7213
7457
  let dy = prev.calcBottom() - cur.calcTop() + unitSize * 3;
7214
- cur.offset(0, dy);
7458
+ cur.offsetY(dy);
7215
7459
  }
7216
7460
  }
7217
7461
  this.measures.forEach((m) => {
@@ -7226,26 +7470,10 @@ var ObjScoreRow = class extends MusicObject {
7226
7470
  });
7227
7471
  });
7228
7472
  });
7229
- this.instrumentNames.forEach((obj, i) => {
7230
- let grp = this.instrumentLineGroups[i];
7231
- if (obj && grp.length > 0) {
7232
- obj.offset(
7233
- -obj.getRect().left,
7234
- -obj.getRect().anchorY + (grp[0].getRect().top + grp[grp.length - 1].getRect().bottom) / 2
7235
- );
7236
- }
7237
- });
7473
+ this.rowGroups.forEach((grp) => grp.layoutToNotationLines());
7238
7474
  this.alignStemsToBeams();
7239
7475
  this.requestRectUpdate();
7240
7476
  }
7241
- layoutPadding(ctx) {
7242
- let p = ctx.unitSize / 2;
7243
- this.getRect();
7244
- this.rect.left -= p;
7245
- this.rect.right += p;
7246
- this.rect.top -= p;
7247
- this.rect.bottom += p;
7248
- }
7249
7477
  layoutDone() {
7250
7478
  this.measures.forEach((m) => m.layoutDone());
7251
7479
  this.needLayout = false;
@@ -7254,13 +7482,14 @@ var ObjScoreRow = class extends MusicObject {
7254
7482
  this.measures.forEach((m) => m.offset(dx, dy));
7255
7483
  this.rect.offsetInPlace(dx, dy);
7256
7484
  this.notationLines.forEach((l) => l.offset(dx, dy));
7257
- this.instrumentNames.forEach((obj) => obj == null ? void 0 : obj.offset(dx, dy));
7485
+ this.rowGroups.forEach((grp) => grp.offset(dx, dy));
7258
7486
  }
7259
7487
  draw(ctx) {
7260
7488
  ctx.drawDebugRect(this.getRect());
7489
+ const { left, top, width, height } = this.getRect();
7490
+ const p = ctx._lineWidth;
7261
7491
  ctx.save();
7262
- let { left, top, width, height } = this.getRect();
7263
- ctx.rect(left, top, width, height);
7492
+ ctx.rect(left - p, top, width + 2 * p, height);
7264
7493
  ctx.clip();
7265
7494
  if (this.getFirstMeasure() && (this.notationLines.length > 1 || this.notationLines[0] instanceof ObjTab)) {
7266
7495
  let left2 = this.getFirstMeasure().getStaffLineLeft();
@@ -7270,22 +7499,7 @@ var ObjScoreRow = class extends MusicObject {
7270
7499
  }
7271
7500
  this.measures.forEach((m) => m.draw(ctx));
7272
7501
  this.notationLines.forEach((m) => m.draw(ctx));
7273
- let grpSize = this.doc.getInstrumentGroupSize(ctx);
7274
- this.instrumentNames.forEach((obj, i) => {
7275
- let grp = this.instrumentLineGroups[i];
7276
- if (grp.length > 1) {
7277
- let r = new AnchoredRect24(
7278
- grpSize.braceLeft,
7279
- grpSize.braceRight,
7280
- grp[0].getTopLineY(),
7281
- grp[grp.length - 1].getBottomLineY()
7282
- );
7283
- ctx.color("brack").lineWidth(1).drawBrace(r, "left");
7284
- }
7285
- if (obj) {
7286
- obj.draw(ctx);
7287
- }
7288
- });
7502
+ this.rowGroups.forEach((grp) => grp.draw(ctx));
7289
7503
  ctx.restore();
7290
7504
  }
7291
7505
  };
@@ -7295,6 +7509,7 @@ import { AnchoredRect as AnchoredRect25 } from "@tspro/ts-utils-lib";
7295
7509
  var ObjHeader = class extends MusicObject {
7296
7510
  constructor(doc, title, composer, arranger) {
7297
7511
  super(doc);
7512
+ this.doc = doc;
7298
7513
  this.title = title;
7299
7514
  this.composer = composer;
7300
7515
  this.arranger = arranger;
@@ -7334,24 +7549,29 @@ var ObjHeader = class extends MusicObject {
7334
7549
  }
7335
7550
  return [this];
7336
7551
  }
7337
- layoutWidth(ctx, left, right) {
7552
+ layout(ctx) {
7338
7553
  let top = 0;
7554
+ const left = this.doc.regions.staffLeft;
7555
+ const right = this.doc.regions.staffRight;
7339
7556
  this.rect = new AnchoredRect25(left, right, 0, 0);
7340
7557
  if (this.titleText) {
7341
7558
  this.titleText.layout(ctx);
7342
- this.titleText.offset((left + right) / 2, top);
7559
+ this.titleText.setCenterX((left + right) / 2);
7560
+ this.titleText.setTop(top);
7343
7561
  top += this.titleText.getRect().height;
7344
7562
  this.rect.expandInPlace(this.titleText.getRect());
7345
7563
  }
7346
7564
  if (this.composerText) {
7347
7565
  this.composerText.layout(ctx);
7348
- this.composerText.offset(right, top);
7566
+ this.composerText.setRight(right);
7567
+ this.composerText.setTop(top);
7349
7568
  top += this.composerText.getRect().height;
7350
7569
  this.rect.expandInPlace(this.composerText.getRect());
7351
7570
  }
7352
7571
  if (this.arrangerText) {
7353
7572
  this.arrangerText.layout(ctx);
7354
- this.arrangerText.offset(right, top);
7573
+ this.arrangerText.setRight(right);
7574
+ this.arrangerText.setTop(top);
7355
7575
  top += this.arrangerText.getRect().height;
7356
7576
  this.rect.expandInPlace(this.arrangerText.getRect());
7357
7577
  }
@@ -7382,13 +7602,14 @@ var ObjHeader = class extends MusicObject {
7382
7602
  };
7383
7603
 
7384
7604
  // src/score/engine/obj-document.ts
7385
- import { AnchoredRect as AnchoredRect26, Guard as Guard11, UniMap as UniMap8 } from "@tspro/ts-utils-lib";
7605
+ import { AnchoredRect as AnchoredRect26, Guard as Guard11, UniMap as UniMap9 } from "@tspro/ts-utils-lib";
7386
7606
  import { MusicError as MusicError17, MusicErrorType as MusicErrorType17 } from "@tspro/web-music-score/core";
7387
7607
  var ObjDocument = class extends MusicObject {
7388
7608
  constructor() {
7389
7609
  super(void 0);
7390
7610
  __publicField(this, "needLayout", true);
7391
7611
  __publicField(this, "ctx");
7612
+ __publicField(this, "regions", new ScoreRowRegions());
7392
7613
  __publicField(this, "rows", []);
7393
7614
  __publicField(this, "measures", []);
7394
7615
  __publicField(this, "measuresPerRow", Infinity);
@@ -7396,7 +7617,7 @@ var ObjDocument = class extends MusicObject {
7396
7617
  __publicField(this, "header");
7397
7618
  __publicField(this, "newRowRequested", false);
7398
7619
  __publicField(this, "allConnectiveProps", []);
7399
- __publicField(this, "staffGroups", new UniMap8());
7620
+ __publicField(this, "staffGroups", new UniMap9());
7400
7621
  __publicField(this, "mi");
7401
7622
  this.mi = new MDocument2(this);
7402
7623
  }
@@ -7593,18 +7814,6 @@ var ObjDocument = class extends MusicObject {
7593
7814
  this.ctx.updateCursorRect(cursorRect);
7594
7815
  }
7595
7816
  }
7596
- getInstrumentGroupSize(ctx) {
7597
- let nameWidth = Math.max(0, ...this.rows.map((row) => row.getInstrumentNameWidth(ctx)));
7598
- let hasName = nameWidth > 0;
7599
- let padding = hasName ? ctx.unitSize : 0;
7600
- let braceWidth = hasName ? ctx.unitSize * 5 : 0;
7601
- return {
7602
- nameLeft: 0,
7603
- nameRight: nameWidth,
7604
- braceLeft: nameWidth + padding,
7605
- braceRight: nameWidth + padding + braceWidth + padding
7606
- };
7607
- }
7608
7817
  requestLayout() {
7609
7818
  this.needLayout = true;
7610
7819
  }
@@ -7632,28 +7841,27 @@ var ObjDocument = class extends MusicObject {
7632
7841
  this.allConnectiveProps.forEach((props) => props.removeConnectives());
7633
7842
  this.allConnectiveProps.forEach((props) => props.createConnectives());
7634
7843
  this.rows.forEach((row) => row.resetLayoutGroups(ctx));
7844
+ this.regions.resetWidths();
7845
+ this.regions.addRowstaffWidth(DocumentSettings.MinStaffWidth * unitSize);
7635
7846
  this.rows.forEach((row) => row.layout(ctx));
7636
- let left = this.getInstrumentGroupSize(ctx).braceRight;
7637
- let right = Math.max(
7638
- DocumentSettings.DocumentMinWidth * unitSize,
7639
- ...this.rows.map((row) => 1.4 * row.getMinWidth())
7640
- );
7641
- this.rows.forEach((row) => row.layoutWidth(ctx, left, right));
7847
+ this.rows.forEach((row) => row.layoutStretch(ctx));
7642
7848
  this.rows.forEach((row) => row.layoutLayoutGroups(ctx));
7643
7849
  this.rows.forEach((row) => row.layoutSetNotationLines(ctx));
7644
- this.rows.forEach((row) => row.layoutPadding(ctx));
7645
7850
  this.rect = new AnchoredRect26();
7646
7851
  if (this.header) {
7647
- this.header.layoutWidth(ctx, left, right);
7852
+ this.header.layout(ctx);
7648
7853
  this.rect.expandInPlace(this.header.getRect());
7649
7854
  }
7650
7855
  this.rows.forEach((row) => {
7651
- row.offset(-this.rect.left, this.rect.bottom + unitSize * 2 - row.getRect().top);
7856
+ row.setLeft(0);
7857
+ row.setTop(this.rect.bottom + unitSize * 2);
7652
7858
  this.rect.expandInPlace(row.getRect());
7653
7859
  });
7654
7860
  this.rows.forEach((row) => row.layoutDone());
7655
7861
  this.needLayout = false;
7656
7862
  }
7863
+ offset(dx, dy) {
7864
+ }
7657
7865
  drawContent() {
7658
7866
  const { ctx } = this;
7659
7867
  if (!ctx) {
@@ -8431,7 +8639,7 @@ var ScoreObjectEvent = class extends ScoreEvent {
8431
8639
 
8432
8640
  // src/score/pub/music-interface.ts
8433
8641
  import * as Audio2 from "@tspro/web-music-score/audio";
8434
- import { Guard as Guard14, UniMap as UniMap9, ValueSet as ValueSet2, Utils as Utils13 } from "@tspro/ts-utils-lib";
8642
+ import { Guard as Guard14, UniMap as UniMap10, ValueSet as ValueSet2, Utils as Utils13 } from "@tspro/ts-utils-lib";
8435
8643
 
8436
8644
  // src/score/pub/music-objects.ts
8437
8645
  import { Guard as Guard13 } from "@tspro/ts-utils-lib";
@@ -8778,10 +8986,10 @@ var _MBarLineLeft = class _MBarLineLeft extends MusicInterface5 {
8778
8986
  /** Object name. */
8779
8987
  __publicField(_MBarLineLeft, "Name", "BarLineLeft");
8780
8988
  var MBarLineLeft = _MBarLineLeft;
8781
- var _MStaffTabBarLine = class _MStaffTabBarLine extends MusicInterface5 {
8989
+ var _MStaffBarLine = class _MStaffBarLine extends MusicInterface5 {
8782
8990
  /** @internal */
8783
8991
  constructor(obj) {
8784
- super(_MStaffTabBarLine.Name);
8992
+ super(_MStaffBarLine.Name);
8785
8993
  this.obj = obj;
8786
8994
  }
8787
8995
  /** @internal */
@@ -8797,7 +9005,7 @@ var _MStaffTabBarLine = class _MStaffTabBarLine extends MusicInterface5 {
8797
9005
  if (barLine instanceof ObjBarLineLeft || barLine instanceof ObjBarLineRight) {
8798
9006
  return barLine.getMusicInterface();
8799
9007
  } else {
8800
- throw new MusicError20(MusicErrorType20.Score, `Bar line not let nor right.`);
9008
+ throw new MusicError20(MusicErrorType20.Score, `Bar line not left nor right.`);
8801
9009
  }
8802
9010
  }
8803
9011
  /**
@@ -8809,8 +9017,8 @@ var _MStaffTabBarLine = class _MStaffTabBarLine extends MusicInterface5 {
8809
9017
  }
8810
9018
  };
8811
9019
  /** Object name. */
8812
- __publicField(_MStaffTabBarLine, "Name", "StaffTabBarLine");
8813
- var MStaffTabBarLine = _MStaffTabBarLine;
9020
+ __publicField(_MStaffBarLine, "Name", "StaffBarLine");
9021
+ var MStaffBarLine = _MStaffBarLine;
8814
9022
  var _MNoteGroup = class _MNoteGroup extends MusicInterface5 {
8815
9023
  /** @internal */
8816
9024
  constructor(obj) {
@@ -9091,6 +9299,27 @@ var _MScoreRow = class _MScoreRow extends MusicInterface5 {
9091
9299
  /** Object name. */
9092
9300
  __publicField(_MScoreRow, "Name", "ScoreRow");
9093
9301
  var MScoreRow = _MScoreRow;
9302
+ var _MScoreRowGroup = class _MScoreRowGroup extends MusicInterface5 {
9303
+ /** @internal */
9304
+ constructor(obj) {
9305
+ super(_MScoreRowGroup.Name);
9306
+ this.obj = obj;
9307
+ }
9308
+ /** @internal */
9309
+ getMusicObject() {
9310
+ return this.obj;
9311
+ }
9312
+ /**
9313
+ * Get instrument name.
9314
+ * @returns - instrument name.
9315
+ */
9316
+ getInstrument() {
9317
+ return this.obj.instrument;
9318
+ }
9319
+ };
9320
+ /** Object name. */
9321
+ __publicField(_MScoreRowGroup, "Name", "ScoreRowGroup");
9322
+ var MScoreRowGroup = _MScoreRowGroup;
9094
9323
  var _MStaff = class _MStaff extends MusicInterface5 {
9095
9324
  /** @internal */
9096
9325
  constructor(obj) {
@@ -9609,7 +9838,7 @@ var _MPlaybackButtons = class _MPlaybackButtons {
9609
9838
  this.savedOnClickListeners.getOrCreate(btn, []).push(onClickListener);
9610
9839
  }
9611
9840
  };
9612
- __publicField(_MPlaybackButtons, "savedOnClickListeners", new UniMap9());
9841
+ __publicField(_MPlaybackButtons, "savedOnClickListeners", new UniMap10());
9613
9842
  var MPlaybackButtons = _MPlaybackButtons;
9614
9843
 
9615
9844
  // src/score/index.ts
@@ -9649,13 +9878,14 @@ export {
9649
9878
  MRest,
9650
9879
  MRhythmColumn,
9651
9880
  MScoreRow,
9881
+ MScoreRowGroup,
9652
9882
  MSpecialText,
9653
9883
  MStaff,
9884
+ MStaffBarLine,
9654
9885
  MStaffBeamGroup,
9655
9886
  MStaffNoteGroup,
9656
9887
  MStaffRest,
9657
9888
  MStaffSignature,
9658
- MStaffTabBarLine,
9659
9889
  MTab,
9660
9890
  MTabNoteGroup,
9661
9891
  MTabRhythm,