@sudobility/music_drawing 0.0.33 → 0.0.34

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 (47) hide show
  1. package/dist/cursor.d.ts +60 -0
  2. package/dist/cursor.d.ts.map +1 -0
  3. package/dist/cursor.js +157 -0
  4. package/dist/cursor.js.map +1 -0
  5. package/dist/index.d.ts +15 -0
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +15 -0
  8. package/dist/index.js.map +1 -1
  9. package/dist/keyboard-geometry.d.ts +50 -2
  10. package/dist/keyboard-geometry.d.ts.map +1 -1
  11. package/dist/keyboard-geometry.js +71 -2
  12. package/dist/keyboard-geometry.js.map +1 -1
  13. package/dist/keyboard-keys.d.ts +93 -0
  14. package/dist/keyboard-keys.d.ts.map +1 -0
  15. package/dist/keyboard-keys.js +60 -0
  16. package/dist/keyboard-keys.js.map +1 -0
  17. package/dist/pagination.d.ts +6 -2
  18. package/dist/pagination.d.ts.map +1 -1
  19. package/dist/pagination.js +4 -0
  20. package/dist/pagination.js.map +1 -1
  21. package/dist/playback-binding.d.ts +57 -0
  22. package/dist/playback-binding.d.ts.map +1 -0
  23. package/dist/playback-binding.js +110 -0
  24. package/dist/playback-binding.js.map +1 -0
  25. package/dist/playhead.d.ts.map +1 -1
  26. package/dist/playhead.js +22 -3
  27. package/dist/playhead.js.map +1 -1
  28. package/dist/press.d.ts +66 -0
  29. package/dist/press.d.ts.map +1 -0
  30. package/dist/press.js +64 -0
  31. package/dist/press.js.map +1 -0
  32. package/dist/print-plan.d.ts +64 -0
  33. package/dist/print-plan.d.ts.map +1 -0
  34. package/dist/print-plan.js +101 -0
  35. package/dist/print-plan.js.map +1 -0
  36. package/dist/render-theme.d.ts.map +1 -1
  37. package/dist/render-theme.js +11 -2
  38. package/dist/render-theme.js.map +1 -1
  39. package/dist/score-canvas.d.ts +225 -0
  40. package/dist/score-canvas.d.ts.map +1 -0
  41. package/dist/score-canvas.js +541 -0
  42. package/dist/score-canvas.js.map +1 -0
  43. package/dist/types.d.ts +13 -0
  44. package/dist/types.d.ts.map +1 -1
  45. package/dist/types.js +1 -1
  46. package/dist/types.js.map +1 -1
  47. package/package.json +3 -3
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Everything a print view needs before it draws a single page: the score that
3
+ * is actually printed, its layout, the system slices and which of them go on
4
+ * which page.
5
+ *
6
+ * Both apps had written this, and each had half of it right. The web extracted
7
+ * a part for its instrument, added rehearsal marks and laid page turns out for
8
+ * one player only — but drew the stored score, so an `8va` printed an octave
9
+ * off. The native app drew through `displayScore` and dropped empty pages — but
10
+ * printed every track in concert pitch with no marks, and laid turns out for the
11
+ * first track even across a whole score. This is the union, with the web's
12
+ * rules wherever the two disagreed.
13
+ *
14
+ * Pure: no renderer, no DOM, no Skia. Each app still owns how a slice reaches
15
+ * paper (the web scales canvases under a print stylesheet; the native app hands
16
+ * page images to the platform's print service).
17
+ */
18
+ import { displayScore, extractPart, withRehearsalMarks, } from '@sudobility/music_types';
19
+ import { computeLayout } from './layout.js';
20
+ import { PAPER_ORIENTATIONS, PAPER_SIZES, paginate, usablePageHeight, } from './pagination.js';
21
+ import { PRINT_WIDTH, printRenderOptions, printSystems, } from './print-layout.js';
22
+ const PAPER_LABEL_KEY = {
23
+ a4: 'print.paperA4',
24
+ letter: 'print.paperLetter',
25
+ legal: 'print.paperLegal',
26
+ };
27
+ /** The CSS `@page { size }` keyword for each paper. */
28
+ const PAPER_CSS = {
29
+ a4: 'A4',
30
+ letter: 'letter',
31
+ legal: 'legal',
32
+ };
33
+ const ORIENTATION_LABEL_KEY = {
34
+ portrait: 'print.portrait',
35
+ landscape: 'print.landscape',
36
+ };
37
+ /**
38
+ * The paper picker. `css` is the `@page` size keyword; an orientation's value
39
+ * is its own CSS keyword already.
40
+ *
41
+ * A4 has a key like the others even though it reads "A4" in both languages —
42
+ * one shape for every entry is what lets a picker map straight through, and the
43
+ * locales list it as shared by design.
44
+ */
45
+ export const PAPER_OPTIONS = PAPER_SIZES.map(value => ({
46
+ value,
47
+ labelKey: PAPER_LABEL_KEY[value],
48
+ css: PAPER_CSS[value],
49
+ }));
50
+ export const ORIENTATION_OPTIONS = PAPER_ORIENTATIONS.map(value => ({
51
+ value,
52
+ labelKey: ORIENTATION_LABEL_KEY[value],
53
+ }));
54
+ /** The whole score, as against one track's id. */
55
+ export const WHOLE_SCORE = 'score';
56
+ /**
57
+ * Plan the printout of `score` (the **stored** score).
58
+ *
59
+ * - A part goes through `extractPart`: that track alone, written for its
60
+ * instrument (a clarinet a tone up), with the whole score's rehearsal marks,
61
+ * collapsed rests and cues. Page turns are laid out for that player.
62
+ * - The whole score stays in concert pitch — a conductor compares parts, so
63
+ * none may be transposed — gains rehearsal marks, and prints the visible
64
+ * tracks. Nobody turns for a dozen staves at once, so it has no turn track.
65
+ * - Both are drawn through `displayScore` in concert mode, which applies the
66
+ * octave-bracket lens: an `8va` is part of the notation, not a reading mode.
67
+ * (A part is already written pitch; the lens adds only the bracket.)
68
+ *
69
+ * Null when `scope` names a track the score does not have.
70
+ */
71
+ export function printPlan(score, options = {}) {
72
+ const scope = options.scope ?? WHOLE_SCORE;
73
+ const paper = options.paper ?? 'a4';
74
+ const orientation = options.orientation ?? 'portrait';
75
+ const isPart = scope !== WHOLE_SCORE;
76
+ const source = isPart ? extractPart(score, scope) : withRehearsalMarks(score);
77
+ if (!source)
78
+ return null;
79
+ const printed = displayScore(source);
80
+ const trackIds = isPart
81
+ ? [scope]
82
+ : [...(options.visibleTrackIds ?? [])];
83
+ const renderOptions = printRenderOptions(trackIds);
84
+ const plan = computeLayout(printed, renderOptions);
85
+ const pageHeight = usablePageHeight(paper, orientation, PRINT_WIDTH);
86
+ const turnTrack = isPart ? printed.tracks[0] : undefined;
87
+ const pages = paginate(plan, pageHeight, turnTrack).filter(
88
+ // A page holding no systems is a page turn onto silence.
89
+ page => page.systemIndices.length > 0);
90
+ return {
91
+ score: printed,
92
+ trackIds,
93
+ plan,
94
+ slices: printSystems(plan),
95
+ pages,
96
+ pageHeight,
97
+ renderOptions,
98
+ turnTrackId: turnTrack?.id ?? null,
99
+ };
100
+ }
101
+ //# sourceMappingURL=print-plan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"print-plan.js","sourceRoot":"","sources":["../src/print-plan.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"render-theme.d.ts","sourceRoot":"","sources":["../src/render-theme.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,eAAO,MAAM,kBAAkB,EAAE,WAWhC,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,WAW/B,CAAC"}
1
+ {"version":3,"file":"render-theme.d.ts","sourceRoot":"","sources":["../src/render-theme.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE9C,eAAO,MAAM,kBAAkB,EAAE,WAahC,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,WAkB/B,CAAC"}
@@ -5,10 +5,12 @@ export const LIGHT_RENDER_THEME = {
5
5
  noteSelected: '#6d28d9',
6
6
  noteRegenerated: '#8b5a2b',
7
7
  notePlaying: '#1565c0',
8
- noteOutOfRange: '#c2185b',
8
+ noteOutOfRange: '#ea580c',
9
9
  staveActive: '#000000',
10
10
  staveInactive: '#71717a',
11
11
  caret: '#d32f2f',
12
+ keyboardLit: '#1565c0',
13
+ keyboardSelected: '#6d28d9',
12
14
  };
13
15
  export const DARK_RENDER_THEME = {
14
16
  foreground: '#d4d4d8',
@@ -17,9 +19,16 @@ export const DARK_RENDER_THEME = {
17
19
  noteSelected: '#a78bfa',
18
20
  noteRegenerated: '#d9a066',
19
21
  notePlaying: '#64b5f6',
20
- noteOutOfRange: '#f06292',
22
+ /*
23
+ Saturated rather than the lighter `#fb923c` it was: that sat beside
24
+ `noteRegenerated`'s `#d9a066` closely enough that a regenerated note and one
25
+ the instrument cannot play were hard to tell apart on a dark stave.
26
+ */
27
+ noteOutOfRange: '#f97316',
21
28
  staveActive: '#ffffff',
22
29
  staveInactive: '#8a8a93',
23
30
  caret: '#ef5350',
31
+ keyboardLit: '#64b5f6',
32
+ keyboardSelected: '#a78bfa',
24
33
  };
25
34
  //# sourceMappingURL=render-theme.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"render-theme.js","sourceRoot":"","sources":["../src/render-theme.ts"],"names":[],"mappings":"AA4BA,MAAM,CAAC,MAAM,kBAAkB,GAAgB;IAC7C,UAAU,EAAE,SAAS;IACrB,UAAU,EAAE,SAAS;IACrB,YAAY,EAAE,SAAS;IACvB,YAAY,EAAE,SAAS;IACvB,eAAe,EAAE,SAAS;IAC1B,WAAW,EAAE,SAAS;IACtB,cAAc,EAAE,SAAS;IACzB,WAAW,EAAE,SAAS;IACtB,aAAa,EAAE,SAAS;IACxB,KAAK,EAAE,SAAS;CACjB,CAAC;AAEF,MAAM,CAAC,MAAM,iBAAiB,GAAgB;IAC5C,UAAU,EAAE,SAAS;IACrB,UAAU,EAAE,SAAS;IACrB,YAAY,EAAE,SAAS;IACvB,YAAY,EAAE,SAAS;IACvB,eAAe,EAAE,SAAS;IAC1B,WAAW,EAAE,SAAS;IACtB,cAAc,EAAE,SAAS;IACzB,WAAW,EAAE,SAAS;IACtB,aAAa,EAAE,SAAS;IACxB,KAAK,EAAE,SAAS;CACjB,CAAC"}
1
+ {"version":3,"file":"render-theme.js","sourceRoot":"","sources":["../src/render-theme.ts"],"names":[],"mappings":"AA4BA,MAAM,CAAC,MAAM,kBAAkB,GAAgB;IAC7C,UAAU,EAAE,SAAS;IACrB,UAAU,EAAE,SAAS;IACrB,YAAY,EAAE,SAAS;IACvB,YAAY,EAAE,SAAS;IACvB,eAAe,EAAE,SAAS;IAC1B,WAAW,EAAE,SAAS;IACtB,cAAc,EAAE,SAAS;IACzB,WAAW,EAAE,SAAS;IACtB,aAAa,EAAE,SAAS;IACxB,KAAK,EAAE,SAAS;IAChB,WAAW,EAAE,SAAS;IACtB,gBAAgB,EAAE,SAAS;CAC5B,CAAC;AAEF,MAAM,CAAC,MAAM,iBAAiB,GAAgB;IAC5C,UAAU,EAAE,SAAS;IACrB,UAAU,EAAE,SAAS;IACrB,YAAY,EAAE,SAAS;IACvB,YAAY,EAAE,SAAS;IACvB,eAAe,EAAE,SAAS;IAC1B,WAAW,EAAE,SAAS;IACtB;;;;MAIE;IACF,cAAc,EAAE,SAAS;IACzB,WAAW,EAAE,SAAS;IACtB,aAAa,EAAE,SAAS;IACxB,KAAK,EAAE,SAAS;IAChB,WAAW,EAAE,SAAS;IACtB,gBAAgB,EAAE,SAAS;CAC5B,CAAC"}
@@ -0,0 +1,225 @@
1
+ /**
2
+ * The score canvas: one contract between the drawn score and what drives it.
3
+ *
4
+ * See `docs/score-canvas.md` for the interface and the expectations the tests
5
+ * pin. In short: playback, selection and the active track talk to a
6
+ * `ScoreCanvas`; the canvas owns every geometric decision (layout, units, the
7
+ * cursor path, hit-testing, where following playback scrolls); and each app
8
+ * supplies only a `ScoreCanvasSurface` that puts pixels on its platform. Both
9
+ * apps therefore answer "where is tick N" and "what is under this point" with
10
+ * the same code.
11
+ */
12
+ import type { Pitch, PitchDisplay, Score, SoundingNote } from '@sudobility/music_types';
13
+ import type { CanvasRenderOptions, CanvasRenderResult } from './canvas-renderer.js';
14
+ import type { LayoutPlan } from './layout.js';
15
+ import type { PlaybackScrollTarget } from './playback-scroll.js';
16
+ import type { LayoutMode, RenderTheme } from './types.js';
17
+ import type { CursorGeometry, CursorMotion, CursorPath } from './cursor.js';
18
+ /** What the canvas is showing and at what size. `width`/`height` are view px. */
19
+ export type ScoreCanvasView = {
20
+ width: number;
21
+ height: number;
22
+ zoom: number;
23
+ layoutMode: LayoutMode;
24
+ theme: RenderTheme;
25
+ /** Tracks to draw, top to bottom; omitted means all. */
26
+ trackIds?: string[];
27
+ devicePixelRatio?: number;
28
+ };
29
+ /** A point in view px: relative to the visible top-left, scroll not added. */
30
+ export type ViewPoint = {
31
+ x: number;
32
+ y: number;
33
+ };
34
+ export type ScoreCanvasHit = {
35
+ kind: 'trackGutter';
36
+ trackId: string;
37
+ } | {
38
+ kind: 'measureNumber';
39
+ measureIndex: number;
40
+ } | {
41
+ kind: 'note';
42
+ /** Every event sharing the notehead's box: a chord is one target. */
43
+ eventIds: string[];
44
+ trackId: string;
45
+ measureIndex: number;
46
+ tick: number;
47
+ } | {
48
+ kind: 'stave';
49
+ trackId: string;
50
+ measureIndex: number;
51
+ tick: number;
52
+ /** The pitch *as drawn* at that point, when the point is on a stave. */
53
+ pitch: Pitch | null;
54
+ };
55
+ /** What a platform provides. */
56
+ export interface ScoreCanvasSurface {
57
+ /**
58
+ * Draw the window described by `options` with a `CanvasScoreRenderer` the
59
+ * surface keeps for its life (its column cache is what makes a repaint cheap),
60
+ * and return what it returned. The surface renders because only it has a
61
+ * drawing context: Skia's exists only inside a picture recording.
62
+ */
63
+ paint(score: Score, options: CanvasRenderOptions): CanvasRenderResult | null;
64
+ /**
65
+ * Show the cursor moving along `path` per `motion` (held when the rate is 0),
66
+ * or hide it with `null`. Called only when either changes.
67
+ */
68
+ showCursor(path: CursorPath | null, motion: CursorMotion): void;
69
+ /** Scroll the view to a content-px target. */
70
+ scrollTo?(target: PlaybackScrollTarget, how: 'jump' | 'smooth'): void;
71
+ /**
72
+ * How long a painted frame takes to reach the screen after `paint` returns,
73
+ * in ms — the part of highlight latency the canvas cannot time itself. One
74
+ * frame when omitted: a browser composites the canvas at the next frame, and
75
+ * the native app's React commit and Skia draw land about a frame later too.
76
+ */
77
+ readonly presentLatencyMs?: number;
78
+ }
79
+ /**
80
+ * Time and frames, injected.
81
+ *
82
+ * Required rather than defaulted: this package names no host global (see
83
+ * `globals.d.ts`), so a web host passes `requestAnimationFrame` and a native one
84
+ * whatever its runtime offers.
85
+ */
86
+ export type CanvasScheduler = {
87
+ /** Run `callback` before the next paint; returns a canceller. */
88
+ frame(callback: () => void): () => void;
89
+ /** Run `callback` after `ms`; returns a canceller. */
90
+ timeout(callback: () => void, ms: number): () => void;
91
+ /** `performance.now()`. */
92
+ now(): number;
93
+ };
94
+ export type ScoreCanvasOptions = {
95
+ surface: ScoreCanvasSurface;
96
+ scheduler: CanvasScheduler;
97
+ };
98
+ export declare class ScoreCanvas {
99
+ private readonly surface;
100
+ private readonly scheduler;
101
+ private score;
102
+ /** What `setStoredScore` was last given, so a repeat call does no work. */
103
+ private stored;
104
+ private pitchDisplay;
105
+ private view;
106
+ private scrollLeft;
107
+ private scrollTop;
108
+ private activeTrackId;
109
+ private playing;
110
+ private selectedIds;
111
+ private regenerated;
112
+ private outOfRangeIds;
113
+ private selectedMeasureIds;
114
+ private lastFrame;
115
+ /** The plan the last frame was drawn against is only trusted while this matches. */
116
+ private currentPlan;
117
+ private starts;
118
+ private cancelPaint;
119
+ /** What the drawn window last showed, so an invisible colour change skips the paint. */
120
+ private paintedSignature;
121
+ /** When the lit notes last changed without being painted yet. */
122
+ private highlightRequestedAt;
123
+ private highlightSamples;
124
+ private highlightLatency;
125
+ private readonly highlightListeners;
126
+ private motion;
127
+ private path;
128
+ private shownMotion;
129
+ private cancelWrap;
130
+ constructor({ surface, scheduler }: ScoreCanvasOptions);
131
+ /**
132
+ * The score as the store holds it — sounding pitch, before any lens — and
133
+ * the reading mode to draw it in.
134
+ *
135
+ * The preferred way in. The canvas applies `displayScore` itself and scans
136
+ * the stored score with `outOfRangeNoteIds`, so no host has to remember
137
+ * either half: the scan must see **stored** pitch (the compass is sounding
138
+ * pitch) while the paint must see the **display** score, and a host handed
139
+ * only one of the two was always one line away from colouring a clarinet's
140
+ * part a tone out, or from marking nothing at all.
141
+ *
142
+ * The ids it marks survive the lenses — both keep event ids — so they colour
143
+ * the drawn notes correctly in either mode. Calling again with the same
144
+ * score and mode does nothing. A later `setOutOfRangeNotes` overrides the
145
+ * marks until the stored score next changes.
146
+ */
147
+ setStoredScore(score: Score | null, pitchDisplay?: PitchDisplay): void;
148
+ /**
149
+ * The **display** score, lenses already applied.
150
+ *
151
+ * Lower level than `setStoredScore`: the host owns the lenses and, if it
152
+ * wants out-of-range marks, must pass them to `setOutOfRangeNotes` from a
153
+ * scan of the stored score. Kept for hosts that have not moved over.
154
+ */
155
+ setScore(score: Score | null): void;
156
+ setView(view: ScoreCanvasView): void;
157
+ /** Content px. */
158
+ setScroll(left: number, top: number): void;
159
+ setCursorTick(tick: number): void;
160
+ animateCursor(motion: CursorMotion): void;
161
+ setActiveTrack(trackId: string | null): void;
162
+ setPlayingNotes(notes: readonly SoundingNote[]): void;
163
+ setSelectedNotes(ids: readonly string[], options?: {
164
+ regenerated?: boolean;
165
+ }): void;
166
+ setSelectedMeasures(ids: readonly string[]): void;
167
+ setOutOfRangeNotes(ids: readonly string[]): void;
168
+ /** The layout the canvas draws against, or null with no score or view. */
169
+ get plan(): LayoutPlan | null;
170
+ /** What the last paint drew, while it still describes the current layout. */
171
+ get frame(): CanvasRenderResult | null;
172
+ get zoom(): number;
173
+ /** How large the scrollable content is, in content px. */
174
+ contentSize(): {
175
+ width: number;
176
+ height: number;
177
+ };
178
+ /** Content px. */
179
+ cursorGeometry(tick: number): CursorGeometry | null;
180
+ hitTest(point: ViewPoint): ScoreCanvasHit | null;
181
+ /** The tick under a view point: the inverse of the cursor. */
182
+ tickAt(point: ViewPoint): number | null;
183
+ /** Drawn notes inside a view-px rectangle spanned by two corners. */
184
+ noteIdsInRect(a: ViewPoint, b: ViewPoint): string[];
185
+ /** The bar index `tick` falls in, or null — following playback decides per bar. */
186
+ measureIndexAt(tick: number): number | null;
187
+ /**
188
+ * Ticks per second at `tick` from the written tempo — a first guess for a
189
+ * cursor that has just started moving, before the real rate is measured.
190
+ */
191
+ writtenTicksPerSecond(tick: number): number;
192
+ /** Where following playback should scroll for `tick`, or null to stay. */
193
+ followTarget(tick: number): PlaybackScrollTarget | null;
194
+ /** Scroll so `tick` is in view: a jump for more than a screen, else smooth. */
195
+ scrollToFollow(tick: number): void;
196
+ /**
197
+ * How long a change of lit notes takes to reach the screen here, in seconds:
198
+ * waiting for the frame, drawing, and presenting.
199
+ *
200
+ * Measured rather than assumed because it is a property of the host. A web
201
+ * canvas repaints a window of notation in a few milliseconds; the native app
202
+ * records a Skia picture and waits a React commit, measured at 45–70ms on a
203
+ * dense score. The player publishes the lit notes this far ahead
204
+ * (`setSoundingRenderDelay`), which is what keeps them with the sound on
205
+ * both. The median of recent paints, so one stalled frame does not move it.
206
+ */
207
+ get highlightLatencySeconds(): number;
208
+ subscribeHighlightLatency(listener: (seconds: number) => void): () => void;
209
+ /** Paint now rather than on the next frame — for a host that must, like a resize. */
210
+ paintNow(): void;
211
+ dispose(): void;
212
+ private layoutOptions;
213
+ private positions;
214
+ private invalidateLayout;
215
+ /** Schedules a paint for a colour change; says whether one was needed. */
216
+ private scheduleColourPaint;
217
+ private colourSignature;
218
+ private noteColors;
219
+ private schedulePaint;
220
+ private paint;
221
+ private measureHighlight;
222
+ private refreshCursor;
223
+ private show;
224
+ }
225
+ //# sourceMappingURL=score-canvas.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"score-canvas.d.ts","sourceRoot":"","sources":["../src/score-canvas.ts"],"names":[],"mappings":"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"}