@oh-just-another/renderer-canvas 0.60.0 → 0.61.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/CHANGELOG.md +54 -0
  2. package/README.md +7 -7
  3. package/dist/.tsbuildinfo +1 -1
  4. package/dist/layered-surface.d.ts.map +1 -1
  5. package/dist/layered-surface.js +11 -3
  6. package/dist/layered-surface.js.map +1 -1
  7. package/dist/recording-target.d.ts +20 -1
  8. package/dist/recording-target.d.ts.map +1 -1
  9. package/dist/recording-target.js +70 -5
  10. package/dist/recording-target.js.map +1 -1
  11. package/dist/render-worker.js +19 -7
  12. package/dist/render-worker.js.map +1 -1
  13. package/dist/replay-codec.d.ts +56 -0
  14. package/dist/replay-codec.d.ts.map +1 -0
  15. package/dist/replay-codec.js +543 -0
  16. package/dist/replay-codec.js.map +1 -0
  17. package/dist/tile-compositor.d.ts +9 -0
  18. package/dist/tile-compositor.d.ts.map +1 -1
  19. package/dist/tile-compositor.js +37 -3
  20. package/dist/tile-compositor.js.map +1 -1
  21. package/dist/webgl2-curve.d.ts +1 -2
  22. package/dist/webgl2-curve.d.ts.map +1 -1
  23. package/dist/webgl2-curve.js +21 -8
  24. package/dist/webgl2-curve.js.map +1 -1
  25. package/dist/webgl2-ellipse.d.ts +1 -2
  26. package/dist/webgl2-ellipse.d.ts.map +1 -1
  27. package/dist/webgl2-ellipse.js +18 -10
  28. package/dist/webgl2-ellipse.js.map +1 -1
  29. package/dist/webgl2-msdf-text.d.ts +1 -2
  30. package/dist/webgl2-msdf-text.d.ts.map +1 -1
  31. package/dist/webgl2-msdf-text.js +21 -8
  32. package/dist/webgl2-msdf-text.js.map +1 -1
  33. package/dist/webgl2-stroke.d.ts +8 -5
  34. package/dist/webgl2-stroke.d.ts.map +1 -1
  35. package/dist/webgl2-stroke.js +12 -7
  36. package/dist/webgl2-stroke.js.map +1 -1
  37. package/dist/webgl2-target.d.ts +32 -6
  38. package/dist/webgl2-target.d.ts.map +1 -1
  39. package/dist/webgl2-target.js +116 -38
  40. package/dist/webgl2-target.js.map +1 -1
  41. package/package.json +3 -3
@@ -0,0 +1,543 @@
1
+ import { LruCache, } from "@oh-just-another/renderer-core";
2
+ import { OFFSCREEN_IMAGE_CACHE_CAP } from "./constants.js";
3
+ /**
4
+ * Packed-frame codec for the offscreen backend's per-frame worker hop.
5
+ *
6
+ * `structuredClone`-ing an array of {@link RenderCommand} objects costs
7
+ * ~1.6 ms for a ~4.5k-command frame (see `tests/offscreen-transfer.bench.ts`)
8
+ * — every object, key, and string is walked and copied. This codec flattens
9
+ * the stream into one transferable `ArrayBuffer` of Float64 words (opcode +
10
+ * args per command) plus a per-frame deduplicated string table, so
11
+ * `postMessage` transfers the numeric bulk for free and only clones a small
12
+ * string array. `ImageBitmap` payloads (`defineImage`) travel in a side
13
+ * array — see {@link packReplayFrame}.
14
+ */
15
+ /**
16
+ * Opcodes for the packed numeric stream — one per {@link RenderCommand}
17
+ * variant except `defineImage`, which travels in the side bitmap array and
18
+ * emits nothing here. Wire format only: values are arbitrary but must stay
19
+ * in sync between {@link packReplayFrame} and {@link replayPackedFrame}
20
+ * (same-package protocol; both sides always ship together).
21
+ */
22
+ const OP_SET_FILL = 0;
23
+ const OP_SET_STROKE = 1;
24
+ const OP_SET_STROKE_WIDTH = 2;
25
+ const OP_SET_OPACITY = 3;
26
+ const OP_SET_LINE_CAP = 4;
27
+ const OP_SET_LINE_JOIN = 5;
28
+ const OP_SET_DASH_ARRAY = 6;
29
+ const OP_SET_FONT = 7;
30
+ const OP_SET_TEXT_ALIGN = 8;
31
+ const OP_SET_TEXT_BASELINE = 9;
32
+ const OP_SAVE = 10;
33
+ const OP_RESTORE = 11;
34
+ const OP_TRANSLATE = 12;
35
+ const OP_ROTATE = 13;
36
+ const OP_SCALE = 14;
37
+ const OP_SET_TRANSFORM = 15;
38
+ const OP_RESET_TRANSFORM = 16;
39
+ const OP_BEGIN_PATH = 17;
40
+ const OP_CLOSE_PATH = 18;
41
+ const OP_MOVE_TO = 19;
42
+ const OP_LINE_TO = 20;
43
+ const OP_QUADRATIC_CURVE_TO = 21;
44
+ const OP_BEZIER_CURVE_TO = 22;
45
+ const OP_RECT = 23;
46
+ const OP_ELLIPSE = 24;
47
+ const OP_FILL = 25;
48
+ const OP_STROKE = 26;
49
+ const OP_FILL_TEXT = 27;
50
+ const OP_CLEAR = 28;
51
+ const OP_MARK_DIRTY = 29;
52
+ const OP_RESIZE = 30;
53
+ const OP_DRAW_IMAGE = 31;
54
+ /**
55
+ * String-table index sentinel for a `null` color (`setFill` / `setStroke`
56
+ * accept `Color | null`). Real indices are >= 0.
57
+ */
58
+ const NULL_STRING_INDEX = -1;
59
+ /** `setDashArray(null)` marker written in place of the dash length. */
60
+ const NULL_DASH_LENGTH = -1;
61
+ /**
62
+ * Enum wire codes. Encode side uses the `*_CODE` records, decode side the
63
+ * positional arrays — index === code. Order is wire format; append only.
64
+ */
65
+ const LINE_CAPS = ["butt", "round", "square"];
66
+ const LINE_CAP_CODE = { butt: 0, round: 1, square: 2 };
67
+ const LINE_JOINS = ["miter", "round", "bevel"];
68
+ const LINE_JOIN_CODE = { miter: 0, round: 1, bevel: 2 };
69
+ const TEXT_ALIGNS = ["left", "center", "right"];
70
+ const TEXT_ALIGN_CODE = { left: 0, center: 1, right: 2 };
71
+ const TEXT_BASELINES = ["top", "middle", "bottom"];
72
+ const TEXT_BASELINE_CODE = { top: 0, middle: 1, bottom: 2 };
73
+ /**
74
+ * `fill(rule?)` wire codes: 0 = no rule argument, 1 = "nonzero",
75
+ * 2 = "evenodd".
76
+ */
77
+ const FILL_RULE_CODE = { nonzero: 1, evenodd: 2 };
78
+ /**
79
+ * `setFont` options wire codes. 0 = key absent from the options object;
80
+ * 1 / 2 = the two allowed values. A separate leading flag word (0 / 1)
81
+ * distinguishes "no options argument at all" from an empty options object.
82
+ */
83
+ const FONT_WEIGHT_CODE = { normal: 1, bold: 2 };
84
+ const FONT_STYLE_CODE = { normal: 1, italic: 2 };
85
+ /** Optional-argument presence flags (`fillText` maxWidth, `clear` bounds). */
86
+ const ABSENT = 0;
87
+ const PRESENT = 1;
88
+ /**
89
+ * Initial capacity (in Float64 words) of the packed stream, as a multiple
90
+ * of the command count. Most commands fit in opcode + ≤6 args; the writer
91
+ * doubles on overflow, so this only tunes how often the first frames
92
+ * reallocate.
93
+ */
94
+ const PACK_WORDS_PER_COMMAND = 4;
95
+ /** Floor for the writer's initial capacity so tiny frames don't thrash. */
96
+ const PACK_MIN_CAPACITY = 64;
97
+ /**
98
+ * Flatten a flushed {@link RenderCommand} buffer into a transferable packed
99
+ * frame: one Float64 word per opcode / argument, strings deduplicated into
100
+ * a side table, enums and presence flags as small ints.
101
+ *
102
+ * `defineImage` commands emit nothing into the numeric stream; their
103
+ * `{ id, bitmap }` payloads are collected into `bitmaps` instead. The
104
+ * caller must post them WITHOUT a transfer-list entry so `postMessage`
105
+ * clones the pixels: the recorder's intern LRU still owns the source
106
+ * bitmap and will keep drawing it on later frames (GIF / video), so
107
+ * transferring (detaching) it would break the main thread's copy.
108
+ */
109
+ export const packReplayFrame = (commands) => {
110
+ let words = new Float64Array(Math.max(PACK_MIN_CAPACITY, commands.length * PACK_WORDS_PER_COMMAND));
111
+ let used = 0;
112
+ const push = (v) => {
113
+ if (used === words.length) {
114
+ const grown = new Float64Array(words.length * 2);
115
+ grown.set(words);
116
+ words = grown;
117
+ }
118
+ words[used++] = v;
119
+ };
120
+ const strings = [];
121
+ const stringIndex = new Map();
122
+ /** Dedup a string through the per-frame table, returning its index. */
123
+ const intern = (s) => {
124
+ let idx = stringIndex.get(s);
125
+ if (idx === undefined) {
126
+ idx = strings.length;
127
+ strings.push(s);
128
+ stringIndex.set(s, idx);
129
+ }
130
+ return idx;
131
+ };
132
+ const bitmaps = [];
133
+ for (const cmd of commands) {
134
+ switch (cmd.k) {
135
+ case "setFill":
136
+ push(OP_SET_FILL);
137
+ push(cmd.color === null ? NULL_STRING_INDEX : intern(cmd.color));
138
+ break;
139
+ case "setStroke":
140
+ push(OP_SET_STROKE);
141
+ push(cmd.color === null ? NULL_STRING_INDEX : intern(cmd.color));
142
+ break;
143
+ case "setStrokeWidth":
144
+ push(OP_SET_STROKE_WIDTH);
145
+ push(cmd.w);
146
+ break;
147
+ case "setOpacity":
148
+ push(OP_SET_OPACITY);
149
+ push(cmd.a);
150
+ break;
151
+ case "setLineCap":
152
+ push(OP_SET_LINE_CAP);
153
+ push(LINE_CAP_CODE[cmd.cap]);
154
+ break;
155
+ case "setLineJoin":
156
+ push(OP_SET_LINE_JOIN);
157
+ push(LINE_JOIN_CODE[cmd.join]);
158
+ break;
159
+ case "setDashArray":
160
+ push(OP_SET_DASH_ARRAY);
161
+ if (cmd.dash === null) {
162
+ push(NULL_DASH_LENGTH);
163
+ }
164
+ else {
165
+ push(cmd.dash.length);
166
+ for (const d of cmd.dash)
167
+ push(d);
168
+ }
169
+ break;
170
+ case "setFont":
171
+ push(OP_SET_FONT);
172
+ push(intern(cmd.family));
173
+ push(cmd.size);
174
+ if (cmd.options === undefined) {
175
+ push(ABSENT);
176
+ }
177
+ else {
178
+ push(PRESENT);
179
+ push(cmd.options.weight === undefined ? 0 : FONT_WEIGHT_CODE[cmd.options.weight]);
180
+ push(cmd.options.style === undefined ? 0 : FONT_STYLE_CODE[cmd.options.style]);
181
+ }
182
+ break;
183
+ case "setTextAlign":
184
+ push(OP_SET_TEXT_ALIGN);
185
+ push(TEXT_ALIGN_CODE[cmd.align]);
186
+ break;
187
+ case "setTextBaseline":
188
+ push(OP_SET_TEXT_BASELINE);
189
+ push(TEXT_BASELINE_CODE[cmd.baseline]);
190
+ break;
191
+ case "save":
192
+ push(OP_SAVE);
193
+ break;
194
+ case "restore":
195
+ push(OP_RESTORE);
196
+ break;
197
+ case "translate":
198
+ push(OP_TRANSLATE);
199
+ push(cmd.x);
200
+ push(cmd.y);
201
+ break;
202
+ case "rotate":
203
+ push(OP_ROTATE);
204
+ push(cmd.r);
205
+ break;
206
+ case "scale":
207
+ push(OP_SCALE);
208
+ push(cmd.sx);
209
+ push(cmd.sy);
210
+ break;
211
+ case "setTransform":
212
+ push(OP_SET_TRANSFORM);
213
+ push(cmd.t.a);
214
+ push(cmd.t.b);
215
+ push(cmd.t.c);
216
+ push(cmd.t.d);
217
+ push(cmd.t.e);
218
+ push(cmd.t.f);
219
+ break;
220
+ case "resetTransform":
221
+ push(OP_RESET_TRANSFORM);
222
+ break;
223
+ case "beginPath":
224
+ push(OP_BEGIN_PATH);
225
+ break;
226
+ case "closePath":
227
+ push(OP_CLOSE_PATH);
228
+ break;
229
+ case "moveTo":
230
+ push(OP_MOVE_TO);
231
+ push(cmd.x);
232
+ push(cmd.y);
233
+ break;
234
+ case "lineTo":
235
+ push(OP_LINE_TO);
236
+ push(cmd.x);
237
+ push(cmd.y);
238
+ break;
239
+ case "quadraticCurveTo":
240
+ push(OP_QUADRATIC_CURVE_TO);
241
+ push(cmd.cx);
242
+ push(cmd.cy);
243
+ push(cmd.x);
244
+ push(cmd.y);
245
+ break;
246
+ case "bezierCurveTo":
247
+ push(OP_BEZIER_CURVE_TO);
248
+ push(cmd.c1x);
249
+ push(cmd.c1y);
250
+ push(cmd.c2x);
251
+ push(cmd.c2y);
252
+ push(cmd.x);
253
+ push(cmd.y);
254
+ break;
255
+ case "rect":
256
+ push(OP_RECT);
257
+ push(cmd.x);
258
+ push(cmd.y);
259
+ push(cmd.w);
260
+ push(cmd.h);
261
+ break;
262
+ case "ellipse":
263
+ push(OP_ELLIPSE);
264
+ push(cmd.cx);
265
+ push(cmd.cy);
266
+ push(cmd.rx);
267
+ push(cmd.ry);
268
+ break;
269
+ case "fill":
270
+ push(OP_FILL);
271
+ push(cmd.rule === undefined ? ABSENT : FILL_RULE_CODE[cmd.rule]);
272
+ break;
273
+ case "stroke":
274
+ push(OP_STROKE);
275
+ break;
276
+ case "fillText":
277
+ push(OP_FILL_TEXT);
278
+ push(intern(cmd.text));
279
+ push(cmd.x);
280
+ push(cmd.y);
281
+ if (cmd.maxWidth === undefined) {
282
+ push(ABSENT);
283
+ }
284
+ else {
285
+ push(PRESENT);
286
+ push(cmd.maxWidth);
287
+ }
288
+ break;
289
+ case "clear":
290
+ push(OP_CLEAR);
291
+ if (cmd.bounds === undefined) {
292
+ push(ABSENT);
293
+ }
294
+ else {
295
+ push(PRESENT);
296
+ push(cmd.bounds.x);
297
+ push(cmd.bounds.y);
298
+ push(cmd.bounds.width);
299
+ push(cmd.bounds.height);
300
+ }
301
+ break;
302
+ case "markDirty":
303
+ push(OP_MARK_DIRTY);
304
+ push(cmd.bounds.x);
305
+ push(cmd.bounds.y);
306
+ push(cmd.bounds.width);
307
+ push(cmd.bounds.height);
308
+ break;
309
+ case "resize":
310
+ push(OP_RESIZE);
311
+ push(cmd.w);
312
+ push(cmd.h);
313
+ break;
314
+ case "defineImage":
315
+ // Not packed: the bitmap travels beside the numeric stream. The
316
+ // worker registers all side bitmaps before replaying, so the
317
+ // stream's `drawImage` id references always resolve.
318
+ bitmaps.push({ id: cmd.id, bitmap: cmd.bitmap });
319
+ break;
320
+ case "drawImage":
321
+ push(OP_DRAW_IMAGE);
322
+ push(cmd.id);
323
+ push(cmd.dx);
324
+ push(cmd.dy);
325
+ push(cmd.dw);
326
+ push(cmd.dh);
327
+ break;
328
+ }
329
+ }
330
+ // Exact-size copy so the transferred buffer carries no slack capacity.
331
+ return { buffer: words.slice(0, used).buffer, strings, bitmaps };
332
+ };
333
+ /**
334
+ * Decode a packed frame and dispatch each command straight onto `target`
335
+ * in one pass — no intermediate {@link RenderCommand} objects.
336
+ *
337
+ * `images` is the worker's persistent id → bitmap LRU (mirrors the
338
+ * recorder's same-capacity intern LRU): the caller must have registered
339
+ * the frame's side bitmaps into it BEFORE calling. Semantics match
340
+ * {@link replayCommands}: `resize` is a no-op (the worker owns the canvas
341
+ * size via its own `resize` message) and a `drawImage` whose id misses the
342
+ * cache is skipped rather than thrown.
343
+ */
344
+ export const replayPackedFrame = (target, buffer, strings, images = new LruCache(OFFSCREEN_IMAGE_CACHE_CAP)) => {
345
+ const words = new Float64Array(buffer);
346
+ let i = 0;
347
+ const next = () => {
348
+ const v = words[i++];
349
+ if (v === undefined)
350
+ throw new Error("replayPackedFrame: truncated stream");
351
+ return v;
352
+ };
353
+ const str = (idx) => {
354
+ const s = strings[idx];
355
+ if (s === undefined)
356
+ throw new Error(`replayPackedFrame: bad string index ${String(idx)}`);
357
+ return s;
358
+ };
359
+ const at = (table, code) => {
360
+ const v = table[code];
361
+ if (v === undefined)
362
+ throw new Error(`replayPackedFrame: bad enum code ${String(code)}`);
363
+ return v;
364
+ };
365
+ while (i < words.length) {
366
+ const op = next();
367
+ switch (op) {
368
+ case OP_SET_FILL: {
369
+ const idx = next();
370
+ target.setFill(idx === NULL_STRING_INDEX ? null : str(idx));
371
+ break;
372
+ }
373
+ case OP_SET_STROKE: {
374
+ const idx = next();
375
+ target.setStroke(idx === NULL_STRING_INDEX ? null : str(idx));
376
+ break;
377
+ }
378
+ case OP_SET_STROKE_WIDTH:
379
+ target.setStrokeWidth(next());
380
+ break;
381
+ case OP_SET_OPACITY:
382
+ target.setOpacity(next());
383
+ break;
384
+ case OP_SET_LINE_CAP:
385
+ target.setLineCap(at(LINE_CAPS, next()));
386
+ break;
387
+ case OP_SET_LINE_JOIN:
388
+ target.setLineJoin(at(LINE_JOINS, next()));
389
+ break;
390
+ case OP_SET_DASH_ARRAY: {
391
+ const n = next();
392
+ if (n === NULL_DASH_LENGTH) {
393
+ target.setDashArray(null);
394
+ }
395
+ else {
396
+ const dash = [];
397
+ for (let d = 0; d < n; d++)
398
+ dash.push(next());
399
+ target.setDashArray(dash);
400
+ }
401
+ break;
402
+ }
403
+ case OP_SET_FONT: {
404
+ const family = str(next());
405
+ const size = next();
406
+ if (next() === ABSENT) {
407
+ target.setFont(family, size);
408
+ break;
409
+ }
410
+ const weight = next();
411
+ const style = next();
412
+ const options = {};
413
+ if (weight === FONT_WEIGHT_CODE.normal)
414
+ options.weight = "normal";
415
+ else if (weight === FONT_WEIGHT_CODE.bold)
416
+ options.weight = "bold";
417
+ if (style === FONT_STYLE_CODE.normal)
418
+ options.style = "normal";
419
+ else if (style === FONT_STYLE_CODE.italic)
420
+ options.style = "italic";
421
+ target.setFont(family, size, options);
422
+ break;
423
+ }
424
+ case OP_SET_TEXT_ALIGN:
425
+ target.setTextAlign(at(TEXT_ALIGNS, next()));
426
+ break;
427
+ case OP_SET_TEXT_BASELINE:
428
+ target.setTextBaseline(at(TEXT_BASELINES, next()));
429
+ break;
430
+ case OP_SAVE:
431
+ target.save();
432
+ break;
433
+ case OP_RESTORE:
434
+ target.restore();
435
+ break;
436
+ case OP_TRANSLATE:
437
+ target.translate(next(), next());
438
+ break;
439
+ case OP_ROTATE:
440
+ target.rotate(next());
441
+ break;
442
+ case OP_SCALE:
443
+ target.scale(next(), next());
444
+ break;
445
+ case OP_SET_TRANSFORM:
446
+ target.setTransform({
447
+ a: next(),
448
+ b: next(),
449
+ c: next(),
450
+ d: next(),
451
+ e: next(),
452
+ f: next(),
453
+ });
454
+ break;
455
+ case OP_RESET_TRANSFORM:
456
+ target.resetTransform();
457
+ break;
458
+ case OP_BEGIN_PATH:
459
+ target.beginPath();
460
+ break;
461
+ case OP_CLOSE_PATH:
462
+ target.closePath();
463
+ break;
464
+ case OP_MOVE_TO:
465
+ target.moveTo(next(), next());
466
+ break;
467
+ case OP_LINE_TO:
468
+ target.lineTo(next(), next());
469
+ break;
470
+ case OP_QUADRATIC_CURVE_TO:
471
+ target.quadraticCurveTo(next(), next(), next(), next());
472
+ break;
473
+ case OP_BEZIER_CURVE_TO:
474
+ target.bezierCurveTo(next(), next(), next(), next(), next(), next());
475
+ break;
476
+ case OP_RECT:
477
+ target.rect(next(), next(), next(), next());
478
+ break;
479
+ case OP_ELLIPSE:
480
+ target.ellipse(next(), next(), next(), next());
481
+ break;
482
+ case OP_FILL: {
483
+ const code = next();
484
+ if (code === FILL_RULE_CODE.nonzero)
485
+ target.fill("nonzero");
486
+ else if (code === FILL_RULE_CODE.evenodd)
487
+ target.fill("evenodd");
488
+ else
489
+ target.fill();
490
+ break;
491
+ }
492
+ case OP_STROKE:
493
+ target.stroke();
494
+ break;
495
+ case OP_FILL_TEXT: {
496
+ const text = str(next());
497
+ const x = next();
498
+ const y = next();
499
+ if (next() === PRESENT)
500
+ target.fillText(text, x, y, next());
501
+ else
502
+ target.fillText(text, x, y);
503
+ break;
504
+ }
505
+ case OP_CLEAR:
506
+ if (next() === PRESENT) {
507
+ const bounds = { x: next(), y: next(), width: next(), height: next() };
508
+ target.clear(bounds);
509
+ }
510
+ else {
511
+ target.clear();
512
+ }
513
+ break;
514
+ case OP_MARK_DIRTY:
515
+ target.markDirty?.({ x: next(), y: next(), width: next(), height: next() });
516
+ break;
517
+ case OP_RESIZE:
518
+ // No-op for replay — the worker owns the canvas size and resizes
519
+ // via its own `resize` message, not via the command stream. Still
520
+ // consume the args to stay in sync with the stream.
521
+ next();
522
+ next();
523
+ break;
524
+ case OP_DRAW_IMAGE: {
525
+ // `get` bumps recency so the worker LRU evicts in lockstep with
526
+ // the recorder's. A miss means an out-of-sync stream — skip
527
+ // rather than throw (matches the non-drawable skip on record).
528
+ const id = next();
529
+ const dx = next();
530
+ const dy = next();
531
+ const dw = next();
532
+ const dh = next();
533
+ const bitmap = images.get(id);
534
+ if (bitmap)
535
+ target.drawImage(bitmap, dx, dy, dw, dh);
536
+ break;
537
+ }
538
+ default:
539
+ throw new Error(`replayPackedFrame: unknown opcode ${String(op)}`);
540
+ }
541
+ }
542
+ };
543
+ //# sourceMappingURL=replay-codec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"replay-codec.js","sourceRoot":"","sources":["../src/replay-codec.ts"],"names":[],"mappings":"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"}
@@ -50,6 +50,15 @@ export interface RenderViaTilesOptions {
50
50
  * persistent index pay nothing and behave exactly as before.
51
51
  */
52
52
  readonly index?: SpatialGrid;
53
+ /**
54
+ * Elements to omit from tile rasterisation (e.g. the stroke-eraser preview
55
+ * hides touched originals while their fragments draw on the overlay). Tiles
56
+ * are baked WITH the set applied; when the set changes between frames the
57
+ * compositor invalidates every tile the entering/leaving elements touch, so
58
+ * the cache never shows a stale hidden/unhidden shape. Keep the set small —
59
+ * each membership change re-rasterises the affected tiles.
60
+ */
61
+ readonly hideElements?: ReadonlySet<ElementId>;
53
62
  }
54
63
  /**
55
64
  * Precomputed draw-order lookup used by the indexed tile-query path.
@@ -1 +1 @@
1
- {"version":3,"file":"tile-compositor.d.ts","sourceRoot":"","sources":["../src/tile-compositor.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,SAAS,EAGf,MAAM,gCAAgC,CAAC;AACxC,OAAO,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,EAIL,KAAK,WAAW,EAChB,KAAK,KAAK,EACV,KAAK,OAAO,EACb,MAAM,wBAAwB,CAAC;AAEhC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAGzD;;;;;;;;;;;;;GAaG;AAEH,MAAM,WAAW,oBAAoB;IACnC,mFAAmF;IACnF,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,oFAAoF;IACpF,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,MAAM,WAAW,qBAAqB;IACpC,qEAAqE;IACrE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,2DAA2D;IAC3D,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,eAAe,CAAC,CAAC;IAC3C;;;;;;;;OAQG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,WAAW,CAAC,SAAS,EAAE,oBAAoB,CAAC,CAAC;IACxE,oDAAoD;IACpD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B;;;;;;;;;OASG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,WAAW,CAAC;CAC9B;AAED;;;;;;;;;GASG;AACH,UAAU,cAAc;IACtB,4DAA4D;IAC5D,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IAC/C,qEAAqE;IACrE,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;CAChD;AAED,sEAAsE;AACtE,eAAO,MAAM,mBAAmB,GAAI,OAAO,KAAK,KAAG,cAYlD,CAAC;AAEF,eAAO,MAAM,cAAc,GACzB,OAAO,KAAK,EACZ,YAAY,cAAc,EAC1B,SAAS,qBAAqB,KAC7B,IA8CF,CAAC;AAiEF,sEAAsE;AACtE,eAAO,MAAM,wBAAwB,GAAI,OAAO,KAAK,EAAE,YAAY,MAAM,KAAG,SAAS,OAAO,EAU3F,CAAC;AAEF;;;;;;;GAOG;AACH,sEAAsE;AACtE,eAAO,MAAM,+BAA+B,GAC1C,OAAO,WAAW,EAClB,WAAW,cAAc,EACzB,YAAY,MAAM,KACjB,SAAS,OAAO,EAUlB,CAAC"}
1
+ {"version":3,"file":"tile-compositor.d.ts","sourceRoot":"","sources":["../src/tile-compositor.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,SAAS,EAGf,MAAM,gCAAgC,CAAC;AACxC,OAAO,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,EAIL,KAAK,WAAW,EAChB,KAAK,KAAK,EACV,KAAK,OAAO,EACb,MAAM,wBAAwB,CAAC;AAEhC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAGzD;;;;;;;;;;;;;GAaG;AAEH,MAAM,WAAW,oBAAoB;IACnC,mFAAmF;IACnF,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,oFAAoF;IACpF,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAED,MAAM,WAAW,qBAAqB;IACpC,qEAAqE;IACrE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,2DAA2D;IAC3D,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,eAAe,CAAC,CAAC;IAC3C;;;;;;;;OAQG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,WAAW,CAAC,SAAS,EAAE,oBAAoB,CAAC,CAAC;IACxE,oDAAoD;IACpD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B;;;;;;;;;OASG;IACH,QAAQ,CAAC,KAAK,CAAC,EAAE,WAAW,CAAC;IAC7B;;;;;;;OAOG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,WAAW,CAAC,SAAS,CAAC,CAAC;CAChD;AAiBD;;;;;;;;;GASG;AACH,UAAU,cAAc;IACtB,4DAA4D;IAC5D,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IAC/C,qEAAqE;IACrE,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;CAChD;AAED,sEAAsE;AACtE,eAAO,MAAM,mBAAmB,GAAI,OAAO,KAAK,KAAG,cAYlD,CAAC;AAEF,eAAO,MAAM,cAAc,GACzB,OAAO,KAAK,EACZ,YAAY,cAAc,EAC1B,SAAS,qBAAqB,KAC7B,IAgEF,CAAC;AAmEF,sEAAsE;AACtE,eAAO,MAAM,wBAAwB,GAAI,OAAO,KAAK,EAAE,YAAY,MAAM,KAAG,SAAS,OAAO,EAU3F,CAAC;AAEF;;;;;;;GAOG;AACH,sEAAsE;AACtE,eAAO,MAAM,+BAA+B,GAC1C,OAAO,WAAW,EAClB,WAAW,cAAc,EACzB,YAAY,MAAM,KACjB,SAAS,OAAO,EAUlB,CAAC"}
@@ -2,6 +2,21 @@ import { TILE_SIZE, } from "@oh-just-another/renderer-core";
2
2
  import { getElementsInLayer, getElementWorldBounds, getLayersInOrder, } from "@oh-just-another/scene";
3
3
  import { createOffscreenCanvas2DTarget } from "./offscreen.js";
4
4
  import { getElementRenderer } from "@oh-just-another/renderer-core";
5
+ /**
6
+ * Last hide-set a given cache was baked with — keyed by the cache instance so
7
+ * the stateless `renderViaTiles` can detect set changes across frames without
8
+ * growing its public API. WeakMap: dropping the cache drops the record.
9
+ */
10
+ const lastHideByCache = new WeakMap();
11
+ const EMPTY_HIDE = new Set();
12
+ const setsEqual = (a, b) => {
13
+ if (a.size !== b.size)
14
+ return false;
15
+ for (const id of a)
16
+ if (!b.has(id))
17
+ return false;
18
+ return true;
19
+ };
5
20
  /** @internal Exported for unit tests; not part of the package API. */
6
21
  export const buildDrawOrderIndex = (scene) => {
7
22
  const byId = new Map();
@@ -19,9 +34,27 @@ export const buildDrawOrderIndex = (scene) => {
19
34
  };
20
35
  export const renderViaTiles = (scene, mainTarget, options) => {
21
36
  const { viewport, cache, changedElements, zoomBucket, index } = options;
37
+ const hide = options.hideElements && options.hideElements.size > 0 ? options.hideElements : EMPTY_HIDE;
22
38
  // Build the draw-order lookup once per frame when an index is supplied;
23
39
  // each fresh tile reuses it instead of re-walking the scene.
24
40
  const drawOrder = index ? buildDrawOrderIndex(scene) : null;
41
+ // 0) Hide-set diff: tiles are baked with `hideElements` applied, so any
42
+ // element entering or leaving the set makes the tiles it touches stale.
43
+ // Invalidate by the element's current world bbox (a removed element's
44
+ // tiles are already handled by `changedElements`).
45
+ const lastHide = lastHideByCache.get(cache) ?? EMPTY_HIDE;
46
+ if (!setsEqual(hide, lastHide)) {
47
+ const affected = new Set([...hide, ...lastHide]);
48
+ for (const id of affected) {
49
+ if (hide.has(id) && lastHide.has(id))
50
+ continue; // still hidden — tiles stay valid
51
+ const el = scene.elements.get(id);
52
+ if (!el)
53
+ continue;
54
+ cache.invalidateRect(getElementWorldBounds(el));
55
+ }
56
+ lastHideByCache.set(cache, new Set(hide));
57
+ }
25
58
  // 1) Invalidate cached tiles per patch (covers add / remove / move).
26
59
  if (changedElements) {
27
60
  for (const [id, record] of changedElements) {
@@ -43,7 +76,7 @@ export const renderViaTiles = (scene, mainTarget, options) => {
43
76
  const key = { col, row, zoom: zoomBucket };
44
77
  let entry = cache.get(key);
45
78
  if (!entry) {
46
- const fresh = rasteriseTile(scene, col, row, zoomBucket, index, drawOrder);
79
+ const fresh = rasteriseTile(scene, col, row, zoomBucket, index, drawOrder, hide);
47
80
  if (!fresh)
48
81
  continue;
49
82
  cache.set(fresh);
@@ -60,7 +93,7 @@ export const renderViaTiles = (scene, mainTarget, options) => {
60
93
  * sized at `TILE_SIZE * zoomBucket` device pixels per side. Returns
61
94
  * `null` when the tile contains no shapes.
62
95
  */
63
- const rasteriseTile = (scene, col, row, zoomBucket, index, drawOrder) => {
96
+ const rasteriseTile = (scene, col, row, zoomBucket, index, drawOrder, hide) => {
64
97
  if (typeof OffscreenCanvas === "undefined")
65
98
  return null;
66
99
  const worldX = col * TILE_SIZE;
@@ -71,9 +104,10 @@ const rasteriseTile = (scene, col, row, zoomBucket, index, drawOrder) => {
71
104
  width: TILE_SIZE,
72
105
  height: TILE_SIZE,
73
106
  };
74
- const shapes = index && drawOrder
107
+ const visible = index && drawOrder
75
108
  ? elementsIntersectingTileIndexed(index, drawOrder, worldBounds)
76
109
  : elementsIntersectingTile(scene, worldBounds);
110
+ const shapes = hide.size > 0 ? visible.filter((sh) => !hide.has(sh.id)) : visible;
77
111
  if (shapes.length === 0)
78
112
  return null;
79
113
  // Bitmap size — `TILE_SIZE * zoomBucket` device pixels so the tile