@viritura/score-engine 0.0.0 → 0.1.0-next.1

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.
@@ -0,0 +1,255 @@
1
+ /**
2
+ * Public types for @viritura/score-engine.
3
+ *
4
+ * These are self-contained: nothing here re-exports internal renderer types,
5
+ * so the published declarations stay small and the engine can change its
6
+ * internal display-list representation without breaking consumers.
7
+ *
8
+ * Coordinate system: all geometry is in display-list units (CSS pixels at
9
+ * zoom 1). Geometry that belongs to a page is **page-local** — `y = 0` is the
10
+ * top of that page. Unpaged (horizon) layouts have exactly one page.
11
+ */
12
+ declare const displayListBrand: unique symbol;
13
+ /**
14
+ * Opaque handle to a computed layout. Produced by `engine.layout()` or a
15
+ * `LayoutWorker`; pass it back to the engine to paint or query geometry.
16
+ */
17
+ export interface DisplayList {
18
+ readonly [displayListBrand]: true;
19
+ /** Page width (paged) or full score width (unpaged). */
20
+ readonly width: number;
21
+ /** Total height of all pages stacked without gaps. */
22
+ readonly height: number;
23
+ /** Number of pages (1 for unpaged layouts). */
24
+ readonly pageCount: number;
25
+ /** True when the layout was computed with page geometry. */
26
+ readonly paged: boolean;
27
+ }
28
+ /** Axis-aligned rectangle in display-list units. */
29
+ export interface Rect {
30
+ readonly x: number;
31
+ readonly y: number;
32
+ readonly width: number;
33
+ readonly height: number;
34
+ }
35
+ /** A part in score order with its stable identifier. */
36
+ export interface PartInfo {
37
+ /**
38
+ * Stable part ID: the source MNX `parts[n].id` when present, otherwise the
39
+ * positional fallback `#<n>` (0-based). Deterministic across calls.
40
+ */
41
+ readonly id: string;
42
+ /** 0-based index in MNX `parts[]`. */
43
+ readonly index: number;
44
+ /** Display name (may be empty). */
45
+ readonly name: string;
46
+ }
47
+ /** Score metadata derived from MNX without running layout. */
48
+ export interface ScoreInfo {
49
+ readonly parts: readonly PartInfo[];
50
+ readonly measureCount: number;
51
+ /** Entries of MNX `scores[]`, selectable via `LayoutOptions.scoreIndex`. */
52
+ readonly scores: ReadonlyArray<{
53
+ readonly index: number;
54
+ readonly name: string;
55
+ }>;
56
+ }
57
+ /** Engine build identity. */
58
+ export interface EngineVersion {
59
+ /** Rust layout engine version reported by the loaded WASM module. */
60
+ readonly engine: string;
61
+ /** `@viritura/score-engine` package version. */
62
+ readonly package: string;
63
+ /** Viritura commit the bundle was built from, when known. */
64
+ readonly commit: string | null;
65
+ }
66
+ /** Explicit page geometry for paged layout. */
67
+ export interface LayoutPageSetup {
68
+ /** Page height in display-list units. */
69
+ height: number;
70
+ /** Page margins in display-list units. */
71
+ margins: {
72
+ top: number;
73
+ right: number;
74
+ bottom: number;
75
+ left: number;
76
+ };
77
+ }
78
+ /** Engraving inputs for `engine.layout()`. Changing any of these reflows the music. */
79
+ export interface LayoutOptions {
80
+ /** Page width in display-list units. `0` selects unpaged (horizon) layout. */
81
+ pageWidth: number;
82
+ /** Staff space in display-list units. Default 7. */
83
+ spatium?: number;
84
+ /** Zero-based index into MNX `scores[]`. Default 0. */
85
+ scoreIndex?: number;
86
+ /** Page geometry. Omit for the engine's default page proportions. */
87
+ pageSetup?: LayoutPageSetup;
88
+ }
89
+ /**
90
+ * Options for `engine.paint()`.
91
+ *
92
+ * `paint` draws ink only into whatever transform the caller has set on the
93
+ * context (hi-DPI scale, zoom, scroll). It never clears the canvas.
94
+ */
95
+ export interface PaintOptions {
96
+ /** Zero-based page to paint. Default 0. */
97
+ page?: number;
98
+ /** Page-local rectangle to paint; commands entirely outside it are skipped. */
99
+ region?: Rect;
100
+ /** Colour substituted for default (black) ink, e.g. for dark themes. Explicitly coloured elements keep their colour. */
101
+ ink?: string;
102
+ /** Fill painted under the page before the ink. Default none (transparent). */
103
+ background?: string | null;
104
+ }
105
+ /** Options for `engine.toSvg()`. */
106
+ export interface SvgOptions {
107
+ /** Zero-based page to export. Default 0. */
108
+ page?: number;
109
+ /** Colour substituted for default (black) ink. */
110
+ ink?: string;
111
+ }
112
+ /** Options for `loadEngine()`. */
113
+ export interface LoadEngineOptions {
114
+ /**
115
+ * Base URL containing `wasm/` and `fonts/`. Defaults to the directory of
116
+ * the prebuilt bundle, or the page's asset base inside Viritura's own apps.
117
+ * Sandboxed hosts (VS Code webviews) pass their rewritten asset URL here.
118
+ */
119
+ assetBaseUrl?: string;
120
+ /**
121
+ * Load the bundled Libertinus Serif text face as `Viritura Serif`. Default
122
+ * true. Pass false to use the page's generic `serif` family (or register a
123
+ * `Viritura Serif` face yourself). The Bravura music font is always loaded:
124
+ * layout is measured with Bravura's metrics, so it cannot be replaced.
125
+ */
126
+ textFont?: boolean;
127
+ }
128
+ /** Options for `engine.createLayoutWorker()`. */
129
+ export interface LayoutWorkerOptions {
130
+ /** URL of the engine's worker script. Defaults to `score-engine.worker.js` in the asset base. */
131
+ url?: string | URL;
132
+ }
133
+ /** Layout computed off the main thread. */
134
+ export interface LayoutWorker {
135
+ /** Same contract as `engine.layout()`, resolved asynchronously. */
136
+ layout(mnx: string | object, opts: LayoutOptions): Promise<DisplayList>;
137
+ /** Terminate the worker. Pending layouts reject. */
138
+ dispose(): void;
139
+ }
140
+ /** A page of a display list. */
141
+ export interface PageGeometry {
142
+ readonly index: number;
143
+ readonly width: number;
144
+ readonly height: number;
145
+ /** Offset of this page within the gap-free vertical page stack. */
146
+ readonly offsetY: number;
147
+ }
148
+ /** Page-by-page sizing derived from a display list. */
149
+ export interface ScoreMeasurements {
150
+ readonly pageCount: number;
151
+ readonly pages: readonly PageGeometry[];
152
+ /** Sum of all page heights. */
153
+ readonly totalHeight: number;
154
+ /** Widest page. */
155
+ readonly maxPageWidth: number;
156
+ /** Parts present in the layout, in score order. */
157
+ readonly parts: readonly PartInfo[];
158
+ }
159
+ /** A system (line of music) on a page. Page-local. */
160
+ export interface SystemGeometry {
161
+ readonly index: number;
162
+ readonly page: number;
163
+ readonly x: number;
164
+ readonly y: number;
165
+ readonly width: number;
166
+ readonly height: number;
167
+ }
168
+ /** One measure on one staff. Page-local. */
169
+ export interface MeasureGeometry {
170
+ /** 0-based measure index in the score. */
171
+ readonly index: number;
172
+ /** Source measure ID when authored. */
173
+ readonly measureId?: string;
174
+ readonly partId: string;
175
+ /** Visual staff index, unique per rendered staff. */
176
+ readonly staffIndex: number;
177
+ readonly systemIndex: number;
178
+ readonly page: number;
179
+ readonly x: number;
180
+ /** Top staff line. */
181
+ readonly y: number;
182
+ readonly width: number;
183
+ /** Staff height (four staff spaces for a five-line staff). */
184
+ readonly height: number;
185
+ /** Start of the rhythmic content after clef/key/time. */
186
+ readonly contentX: number;
187
+ /** Measure length in quarter-note beats. */
188
+ readonly totalBeats: number;
189
+ }
190
+ /**
191
+ * Unpaged (horizon) paper rectangle around the music, plus the vertical extent
192
+ * a viewport needs to centre it.
193
+ */
194
+ export interface HorizonPaper extends Rect {
195
+ readonly contentHeight: number;
196
+ }
197
+ /** A musical position: global quarter-note beat, or measure + beat within it. */
198
+ export type ScorePosition = {
199
+ readonly beat: number;
200
+ readonly partId?: string;
201
+ } | {
202
+ readonly measureIndex: number;
203
+ readonly beat: number;
204
+ readonly partId?: string;
205
+ };
206
+ /** Where a musical position lands on a single staff. Page-local. */
207
+ export interface CanvasBeatPosition {
208
+ readonly page: number;
209
+ readonly x: number;
210
+ /** Top staff line. */
211
+ readonly y: number;
212
+ readonly height: number;
213
+ }
214
+ /** Vertical cursor spanning the whole system at a position. Page-local. */
215
+ export interface PlayheadGeometry {
216
+ readonly page: number;
217
+ readonly x: number;
218
+ readonly y: number;
219
+ readonly height: number;
220
+ readonly systemIndex: number;
221
+ }
222
+ /** Result of `engine.canvasToBeat()`. */
223
+ export interface CanvasBeatHit {
224
+ /** Global quarter-note beat in visual (unexpanded) measure order. */
225
+ readonly beat: number;
226
+ readonly measureIndex: number;
227
+ readonly partId: string;
228
+ }
229
+ /** Options for `TileRenderer.paint()`. */
230
+ export interface TilePaintOptions {
231
+ /** Horizontal scroll in display-list units. */
232
+ scrollX: number;
233
+ /** Vertical scroll in display-list units. */
234
+ scrollY: number;
235
+ zoom: number;
236
+ /** Paper fill drawn behind the music. Default none. */
237
+ background?: string | null;
238
+ /** Colour substituted for default (black) ink. */
239
+ ink?: string;
240
+ }
241
+ /**
242
+ * Cached, incremental painter for very large unpaged layouts: renders the
243
+ * visible viewport from reusable tiles instead of repainting every command.
244
+ */
245
+ export interface TileRenderer {
246
+ /**
247
+ * Paint the visible viewport into `canvas` (sized by the caller in device
248
+ * pixels). Returns true when tiles are still pending and another frame
249
+ * should be requested.
250
+ */
251
+ paint(canvas: HTMLCanvasElement, displayList: DisplayList, opts: TilePaintOptions): boolean;
252
+ /** Drop cached tiles (e.g. after a theme change). */
253
+ invalidate(): void;
254
+ }
255
+ export {};