@oh-just-another/renderer-core 0.57.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 (93) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/LICENSE +21 -0
  3. package/README.md +40 -0
  4. package/dist/.tsbuildinfo +1 -0
  5. package/dist/animation-adapter.d.ts +91 -0
  6. package/dist/animation-adapter.d.ts.map +1 -0
  7. package/dist/animation-adapter.js +90 -0
  8. package/dist/animation-adapter.js.map +1 -0
  9. package/dist/built-in-renderers.d.ts +6 -0
  10. package/dist/built-in-renderers.d.ts.map +1 -0
  11. package/dist/built-in-renderers.js +517 -0
  12. package/dist/built-in-renderers.js.map +1 -0
  13. package/dist/constants.d.ts +97 -0
  14. package/dist/constants.d.ts.map +1 -0
  15. package/dist/constants.js +115 -0
  16. package/dist/constants.js.map +1 -0
  17. package/dist/edge-cache-bitmap.d.ts +34 -0
  18. package/dist/edge-cache-bitmap.d.ts.map +1 -0
  19. package/dist/edge-cache-bitmap.js +42 -0
  20. package/dist/edge-cache-bitmap.js.map +1 -0
  21. package/dist/edge-cache.d.ts +32 -0
  22. package/dist/edge-cache.d.ts.map +1 -0
  23. package/dist/edge-cache.js +90 -0
  24. package/dist/edge-cache.js.map +1 -0
  25. package/dist/edge-renderer.d.ts +73 -0
  26. package/dist/edge-renderer.d.ts.map +1 -0
  27. package/dist/edge-renderer.js +554 -0
  28. package/dist/edge-renderer.js.map +1 -0
  29. package/dist/grid-renderer.d.ts +55 -0
  30. package/dist/grid-renderer.d.ts.map +1 -0
  31. package/dist/grid-renderer.js +173 -0
  32. package/dist/grid-renderer.js.map +1 -0
  33. package/dist/index.d.ts +37 -0
  34. package/dist/index.d.ts.map +1 -0
  35. package/dist/index.js +24 -0
  36. package/dist/index.js.map +1 -0
  37. package/dist/js-rasterizer.d.ts +8 -0
  38. package/dist/js-rasterizer.d.ts.map +1 -0
  39. package/dist/js-rasterizer.js +86 -0
  40. package/dist/js-rasterizer.js.map +1 -0
  41. package/dist/layer-cache-composite.d.ts +39 -0
  42. package/dist/layer-cache-composite.d.ts.map +1 -0
  43. package/dist/layer-cache-composite.js +47 -0
  44. package/dist/layer-cache-composite.js.map +1 -0
  45. package/dist/layers.d.ts +14 -0
  46. package/dist/layers.d.ts.map +1 -0
  47. package/dist/layers.js +2 -0
  48. package/dist/layers.js.map +1 -0
  49. package/dist/rasterizer.d.ts +27 -0
  50. package/dist/rasterizer.d.ts.map +1 -0
  51. package/dist/rasterizer.js +10 -0
  52. package/dist/rasterizer.js.map +1 -0
  53. package/dist/render-target.d.ts +94 -0
  54. package/dist/render-target.d.ts.map +1 -0
  55. package/dist/render-target.js +2 -0
  56. package/dist/render-target.js.map +1 -0
  57. package/dist/scene-renderer.d.ts +126 -0
  58. package/dist/scene-renderer.d.ts.map +1 -0
  59. package/dist/scene-renderer.js +149 -0
  60. package/dist/scene-renderer.js.map +1 -0
  61. package/dist/shape-cache-bitmap.d.ts +42 -0
  62. package/dist/shape-cache-bitmap.d.ts.map +1 -0
  63. package/dist/shape-cache-bitmap.js +61 -0
  64. package/dist/shape-cache-bitmap.js.map +1 -0
  65. package/dist/shape-cache.d.ts +40 -0
  66. package/dist/shape-cache.d.ts.map +1 -0
  67. package/dist/shape-cache.js +67 -0
  68. package/dist/shape-cache.js.map +1 -0
  69. package/dist/shape-renderer.d.ts +36 -0
  70. package/dist/shape-renderer.d.ts.map +1 -0
  71. package/dist/shape-renderer.js +15 -0
  72. package/dist/shape-renderer.js.map +1 -0
  73. package/dist/text-editing.d.ts +81 -0
  74. package/dist/text-editing.d.ts.map +1 -0
  75. package/dist/text-editing.js +191 -0
  76. package/dist/text-editing.js.map +1 -0
  77. package/dist/text-layout.d.ts +44 -0
  78. package/dist/text-layout.d.ts.map +1 -0
  79. package/dist/text-layout.js +57 -0
  80. package/dist/text-layout.js.map +1 -0
  81. package/dist/text-shaper.d.ts +53 -0
  82. package/dist/text-shaper.d.ts.map +1 -0
  83. package/dist/text-shaper.js +19 -0
  84. package/dist/text-shaper.js.map +1 -0
  85. package/dist/tile-renderer.d.ts +126 -0
  86. package/dist/tile-renderer.d.ts.map +1 -0
  87. package/dist/tile-renderer.js +192 -0
  88. package/dist/tile-renderer.js.map +1 -0
  89. package/dist/worker-render.d.ts +54 -0
  90. package/dist/worker-render.d.ts.map +1 -0
  91. package/dist/worker-render.js +8 -0
  92. package/dist/worker-render.js.map +1 -0
  93. package/package.json +56 -0
@@ -0,0 +1,517 @@
1
+ import { polygon as polygonMath } from "@oh-just-another/math";
2
+ import { getCornerRadius, registerRenderOverflow, FRAME_HEADER_HEIGHT, FRAME_HEADER_PADDING_X, FRAME_HEADER_FONT_SIZE, } from "@oh-just-another/scene";
3
+ import { registerElementRenderer } from "./shape-renderer.js";
4
+ import { layoutText } from "./text-editing.js";
5
+ import { resolveImageSource } from "./animation-adapter.js";
6
+ import { TEXT_DECORATION_THICKNESS, TEXT_UNDERLINE_OFFSET, TEXT_STRIKETHROUGH_OFFSET, } from "./constants.js";
7
+ const req = (v) => {
8
+ if (v === undefined)
9
+ throw new Error("packages/renderer-core: index out of range");
10
+ return v;
11
+ };
12
+ /**
13
+ * Applies common style fields to a target. Returns whether any fill or stroke
14
+ * was configured — shape renderers use the result to decide which paint call
15
+ * to issue.
16
+ */
17
+ const applyStyle = (style, target) => {
18
+ const hasFill = style.fill !== undefined && style.fill !== "transparent";
19
+ const hasStroke = style.stroke !== undefined && style.stroke !== "transparent" && (style.strokeWidth ?? 1) > 0;
20
+ if (hasFill)
21
+ target.setFill(style.fill);
22
+ if (hasStroke) {
23
+ target.setStroke(style.stroke);
24
+ target.setStrokeWidth(style.strokeWidth ?? 1);
25
+ if (style.lineCap)
26
+ target.setLineCap(style.lineCap);
27
+ if (style.lineJoin)
28
+ target.setLineJoin(style.lineJoin);
29
+ if (style.dashArray)
30
+ target.setDashArray(style.dashArray);
31
+ }
32
+ if (style.opacity !== undefined)
33
+ target.setOpacity(style.opacity);
34
+ return { fill: hasFill, stroke: hasStroke };
35
+ };
36
+ const drawRectangle = (shape, target) => {
37
+ const { fill, stroke } = applyStyle(shape.style, target);
38
+ if (!fill && !stroke)
39
+ return;
40
+ const r = getCornerRadius(shape.style.roundness, shape.width, shape.height);
41
+ // Fill path — always uses the original shape geometry.
42
+ if (fill) {
43
+ target.beginPath();
44
+ if (r > 0) {
45
+ buildRoundedRectPath(target, 0, 0, shape.width, shape.height, r);
46
+ }
47
+ else {
48
+ target.rect(0, 0, shape.width, shape.height);
49
+ }
50
+ target.fill();
51
+ }
52
+ // Stroke path — offset by `strokeAlign` so the stroke sits inside
53
+ // / centred-on / outside the fill region. The default (omitted /
54
+ // `center`) reuses the fill geometry. Implemented at this layer so
55
+ // every backend (Canvas2D, WebGL2, SVG) honours strokeAlign without
56
+ // backend-specific work — the math is purely on the rect bounds.
57
+ if (stroke) {
58
+ const offset = strokeAlignOffset(shape.style);
59
+ const sx = offset;
60
+ const sy = offset;
61
+ const sw = shape.width - 2 * offset;
62
+ const sh = shape.height - 2 * offset;
63
+ if (sw <= 0 || sh <= 0)
64
+ return; // degenerate offset — skip
65
+ const sr = r > 0 ? Math.max(0, r - offset) : 0;
66
+ target.beginPath();
67
+ if (sr > 0) {
68
+ buildRoundedRectPath(target, sx, sy, sw, sh, sr);
69
+ }
70
+ else {
71
+ target.rect(sx, sy, sw, sh);
72
+ }
73
+ target.stroke();
74
+ }
75
+ };
76
+ /**
77
+ * Translate `Style.strokeAlign` into a path-offset distance in world
78
+ * units. The rendered stroke geometry shifts by `±half-width` along
79
+ * the inward / outward normal:
80
+ * center → 0 (path centred — Canvas2D / SVG default).
81
+ * inside → +half-width (path moves inward so the stroke's outer
82
+ * edge sits on the original fill boundary).
83
+ * outside → -half-width (path moves outward so the stroke's inner
84
+ * edge sits on the boundary).
85
+ *
86
+ * Only used by axis-aligned primitives (rectangle, container) where
87
+ * "inward" reduces to "subtract from bbox".
88
+ */
89
+ const strokeAlignOffset = (style) => {
90
+ const align = style.strokeAlign ?? "center";
91
+ if (align === "center")
92
+ return 0;
93
+ const half = (style.strokeWidth ?? 1) / 2;
94
+ return align === "inside" ? half : -half;
95
+ };
96
+ /**
97
+ * Build a rounded-rect path via the standard "4 corners with
98
+ * quadratic Bezier arcs" pattern — same shape every backend
99
+ * understands without a special `roundRect()` API:
100
+ *
101
+ * ┌───arc───┐
102
+ * │ │
103
+ * arc arc
104
+ * │ │
105
+ * └───arc───┘
106
+ *
107
+ * Quadratic control points sit at each corner of the rect; the
108
+ * curve goes from `r` units along one side to `r` units along the
109
+ * adjacent side. WebGL2Target's zoom-aware flattener turns this
110
+ * into enough chord segments to stay sub-pixel smooth at any zoom.
111
+ *
112
+ * Radius `r` is pre-clamped by `getCornerRadius` to half the
113
+ * smaller side, so no overlap-handling is needed here.
114
+ */
115
+ const buildRoundedRectPath = (target, x, y, w, h, r) => {
116
+ target.moveTo(x + r, y);
117
+ target.lineTo(x + w - r, y);
118
+ target.quadraticCurveTo(x + w, y, x + w, y + r);
119
+ target.lineTo(x + w, y + h - r);
120
+ target.quadraticCurveTo(x + w, y + h, x + w - r, y + h);
121
+ target.lineTo(x + r, y + h);
122
+ target.quadraticCurveTo(x, y + h, x, y + h - r);
123
+ target.lineTo(x, y + r);
124
+ target.quadraticCurveTo(x, y, x + r, y);
125
+ target.closePath();
126
+ };
127
+ const drawEllipse = (shape, target) => {
128
+ const { fill, stroke } = applyStyle(shape.style, target);
129
+ if (!fill && !stroke)
130
+ return;
131
+ const rx = shape.width / 2;
132
+ const ry = shape.height / 2;
133
+ if (fill) {
134
+ target.beginPath();
135
+ target.ellipse(rx, ry, rx, ry);
136
+ target.fill();
137
+ }
138
+ if (stroke) {
139
+ // Inset / outset radii by `strokeAlignOffset` so the stroke
140
+ // sits inside / centred-on / outside the fill ellipse. Centre
141
+ // stays the same; radii shift uniformly. Degenerate (radius ≤ 0)
142
+ // skips the pass.
143
+ const offset = strokeAlignOffset(shape.style);
144
+ const srx = rx - offset;
145
+ const sry = ry - offset;
146
+ if (srx <= 0 || sry <= 0)
147
+ return;
148
+ target.beginPath();
149
+ target.ellipse(rx, ry, srx, sry);
150
+ target.stroke();
151
+ }
152
+ };
153
+ const drawPolygon = (shape, target) => {
154
+ if (shape.points.length < 2)
155
+ return;
156
+ const { fill, stroke } = applyStyle(shape.style, target);
157
+ if (!fill && !stroke)
158
+ return;
159
+ if (fill) {
160
+ target.beginPath();
161
+ polygonPath(target, shape.points);
162
+ target.fill();
163
+ }
164
+ if (stroke) {
165
+ const offset = strokeAlignOffset(shape.style);
166
+ const pts = offset !== 0 ? polygonMath.offsetClosedPath(shape.points, offset) : shape.points;
167
+ target.beginPath();
168
+ polygonPath(target, pts);
169
+ target.stroke();
170
+ }
171
+ };
172
+ /** Emit a closed polygon outline as `moveTo` + `lineTo`s + `closePath`. */
173
+ const polygonPath = (target, pts) => {
174
+ const first = pts[0];
175
+ if (first === undefined)
176
+ return;
177
+ target.moveTo(first.x, first.y);
178
+ for (let i = 1; i < pts.length; i++) {
179
+ const p = pts[i];
180
+ if (p === undefined)
181
+ continue;
182
+ target.lineTo(p.x, p.y);
183
+ }
184
+ target.closePath();
185
+ };
186
+ const drawPath = (shape, target) => {
187
+ if (shape.commands.length === 0)
188
+ return;
189
+ const { fill, stroke } = applyStyle(shape.style, target);
190
+ if (!fill && !stroke)
191
+ return;
192
+ target.beginPath();
193
+ for (const cmd of shape.commands) {
194
+ switch (cmd.kind) {
195
+ case "M":
196
+ target.moveTo(cmd.to.x, cmd.to.y);
197
+ break;
198
+ case "L":
199
+ target.lineTo(cmd.to.x, cmd.to.y);
200
+ break;
201
+ case "Q":
202
+ target.quadraticCurveTo(cmd.control.x, cmd.control.y, cmd.to.x, cmd.to.y);
203
+ break;
204
+ case "C":
205
+ target.bezierCurveTo(cmd.control1.x, cmd.control1.y, cmd.control2.x, cmd.control2.y, cmd.to.x, cmd.to.y);
206
+ break;
207
+ case "Z":
208
+ target.closePath();
209
+ break;
210
+ }
211
+ }
212
+ if (fill)
213
+ target.fill();
214
+ if (stroke)
215
+ target.stroke();
216
+ };
217
+ const drawText = (shape, target) => {
218
+ const align = shape.style.textAlign ?? "left";
219
+ const weight = shape.style.fontWeight;
220
+ const fontStyle = shape.style.fontStyle;
221
+ target.setFont(shape.fontFamily, shape.fontSize, {
222
+ ...(weight ? { weight } : {}),
223
+ ...(fontStyle ? { style: fontStyle } : {}),
224
+ });
225
+ // Lines are positioned manually (per-line x below) so the caret
226
+ // geometry computed from the same `layoutText` lines up exactly, so
227
+ // the target always draws left-anchored.
228
+ target.setTextAlign("left");
229
+ target.setTextBaseline(shape.style.textBaseline ?? "top");
230
+ // Color: use fill if specified, otherwise default to black.
231
+ const color = shape.style.fill ?? "#000";
232
+ target.setFill(color);
233
+ if (shape.style.opacity !== undefined)
234
+ target.setOpacity(shape.style.opacity);
235
+ // Resolve per-line geometry once (x = align offset, top = i ×
236
+ // lineHeight). Single-line text skips the wrap engine.
237
+ const fontSize = shape.fontSize;
238
+ let lines;
239
+ if (shape.maxWidth === undefined && !shape.text.includes("\n")) {
240
+ lines = [{ text: shape.text, x: 0, width: target.measureText(shape.text).width, top: 0 }];
241
+ }
242
+ else {
243
+ // Measure with the target's own `measureText` so wrapping matches
244
+ // exactly what this backend draws (WebGL2 reports MSDF advances; the
245
+ // selection-box bounder + caret use the same source).
246
+ const measure = (s) => target.measureText(s).width;
247
+ const layout = layoutText(shape.text, measure, {
248
+ fontSize,
249
+ ...(shape.maxWidth !== undefined ? { maxWidth: shape.maxWidth } : {}),
250
+ });
251
+ lines = layout.lines.map((line, i) => ({
252
+ text: line.text,
253
+ x: align === "center"
254
+ ? layout.blockWidth / 2 - line.width / 2
255
+ : align === "right"
256
+ ? layout.blockWidth - line.width
257
+ : 0,
258
+ width: line.width,
259
+ top: i * layout.lineHeight,
260
+ }));
261
+ }
262
+ for (const l of lines)
263
+ target.fillText(l.text, l.x, l.top);
264
+ // Underline / strikethrough — thin filled rects per line, same on
265
+ // Canvas2D and WebGL2 (uses the current text fill colour).
266
+ const deco = shape.style.textDecoration;
267
+ if (deco?.underline || deco?.strikethrough) {
268
+ const thickness = Math.max(1, fontSize * TEXT_DECORATION_THICKNESS);
269
+ for (const l of lines) {
270
+ if (l.width <= 0)
271
+ continue;
272
+ if (deco.underline) {
273
+ target.beginPath();
274
+ target.rect(l.x, l.top + fontSize * TEXT_UNDERLINE_OFFSET, l.width, thickness);
275
+ target.fill();
276
+ }
277
+ if (deco.strikethrough) {
278
+ target.beginPath();
279
+ target.rect(l.x, l.top + fontSize * TEXT_STRIKETHROUGH_OFFSET - thickness / 2, l.width, thickness);
280
+ target.fill();
281
+ }
282
+ }
283
+ }
284
+ };
285
+ /**
286
+ * Variable-width brush stroke. Each segment between two `BrushPoint`s
287
+ * is drawn as a quad (two triangles) — its width interpolates from
288
+ * `p.width` at the head to `q.width` at the tail. Renders
289
+ * pressure-sensitive ink that gets thicker / thinner along the path
290
+ * without needing per-segment `setStrokeWidth` calls (which most 2D
291
+ * APIs treat as a single line width).
292
+ */
293
+ const drawBrush = (shape, target) => {
294
+ const pts = shape.points;
295
+ if (pts.length === 0)
296
+ return;
297
+ const fill = shape.style.fill ?? shape.style.stroke ?? "#000";
298
+ target.setFill(fill);
299
+ target.setStroke(null);
300
+ // Single dot for one-point strokes — degenerate quad would be invisible.
301
+ if (pts.length === 1) {
302
+ const p = req(pts[0]);
303
+ target.beginPath();
304
+ target.ellipse(p.x, p.y, p.width, p.width);
305
+ target.fill();
306
+ return;
307
+ }
308
+ for (let i = 0; i < pts.length - 1; i++) {
309
+ const a = req(pts[i]);
310
+ const b = req(pts[i + 1]);
311
+ const dx = b.x - a.x;
312
+ const dy = b.y - a.y;
313
+ const len = Math.hypot(dx, dy) || 1;
314
+ const nx = -dy / len;
315
+ const ny = dx / len;
316
+ target.beginPath();
317
+ target.moveTo(a.x + nx * a.width, a.y + ny * a.width);
318
+ target.lineTo(b.x + nx * b.width, b.y + ny * b.width);
319
+ target.lineTo(b.x - nx * b.width, b.y - ny * b.width);
320
+ target.lineTo(a.x - nx * a.width, a.y - ny * a.width);
321
+ target.closePath();
322
+ target.fill();
323
+ // End-cap as a disk at the joint — smooths the kink between segments.
324
+ target.beginPath();
325
+ target.ellipse(b.x, b.y, b.width, b.width);
326
+ target.fill();
327
+ }
328
+ };
329
+ const drawImage = (shape, target) => {
330
+ // Priority: preloaded handle in metadata.image → animation-adapter
331
+ // frame (when `animationKind` is set and a matching adapter is
332
+ // registered) → static `src` fallback.
333
+ // For an animated source (GIF) prefer the per-frame image the
334
+ // registered adapter returns over `metadata.image` (a static
335
+ // first-frame `<img>`). `resolveImageSource` consults the adapter
336
+ // with `performance.now()`; it returns `null` while the async
337
+ // decode is still in flight — the backend's drawImage guard skips
338
+ // a null handle and the next AnimationTick frame picks it up.
339
+ const handle = shape.animationKind
340
+ ? resolveImageSource(shape)
341
+ : (shape.metadata?.image ?? resolveImageSource(shape));
342
+ // `dynamic` → backends that cache the upload (WebGL2) re-upload the
343
+ // current frame. GIF / video sources flag `metadata.animated`, and
344
+ // any adapter-driven source is dynamic by definition.
345
+ const dynamic = shape.metadata?.animated === true || shape.animationKind !== undefined;
346
+ target.drawImage(handle, 0, 0, shape.width, shape.height, dynamic);
347
+ };
348
+ /**
349
+ * Registers renderers for every `BuiltinElement` type. Called by side-effect
350
+ * import of `@oh-just-another/renderer-canvas/setup` (see index).
351
+ */
352
+ export const installBuiltinRenderers = () => {
353
+ registerElementRenderer("rectangle", drawRectangle);
354
+ registerElementRenderer("ellipse", drawEllipse);
355
+ registerElementRenderer("polygon", drawPolygon);
356
+ registerElementRenderer("path", drawPath);
357
+ registerElementRenderer("text", drawText);
358
+ registerElementRenderer("image", drawImage);
359
+ // Group shapes are invisible containers — the editor's overlay draws
360
+ // a halo for selected groups, but the shape itself paints nothing.
361
+ registerElementRenderer("group", () => {
362
+ /* intentional no-op: group shapes are invisible containers and paint nothing */
363
+ });
364
+ registerElementRenderer("frame", drawFrame);
365
+ // The frame paints its header strip ABOVE the rectangle, so its dirty
366
+ // region must extend up by the header height — otherwise deleting a
367
+ // frame leaves the header behind.
368
+ registerRenderOverflow("frame", () => ({ top: FRAME_HEADER_HEIGHT }));
369
+ registerElementRenderer("block-arrow", drawBlockArrow);
370
+ registerElementRenderer("brush", drawBrush);
371
+ };
372
+ /**
373
+ * Block-arrow silhouette: a rectangle body whose tip is replaced
374
+ * by a triangle, oriented by `direction`. Path is closed and filled
375
+ * with `style.fill`; stroke applies to the outline.
376
+ *
377
+ * right → ┌────┐▶
378
+ * │ body │
379
+ * └────┘
380
+ *
381
+ * up ↑ ▲
382
+ * ┌──┐
383
+ * │ │
384
+ * └──┘
385
+ */
386
+ const drawBlockArrow = (shape, target) => {
387
+ const { fill, stroke } = applyStyle(shape.style, target);
388
+ const direction = shape.direction ?? "right";
389
+ const headRatio = Math.max(0.1, Math.min(0.9, shape.headRatio ?? 0.4));
390
+ const bodyT = Math.max(0.1, Math.min(0.9, shape.bodyThickness ?? 0.5));
391
+ const w = shape.width;
392
+ const h = shape.height;
393
+ // Compute the local path for a `right`-pointing arrow inside
394
+ // [0, w] × [0, h], then rotate the resulting points if the
395
+ // direction is different. Keeps the drawing primitives in one
396
+ // place.
397
+ const headW = w * headRatio;
398
+ const bodyW = w - headW;
399
+ const bodyHalfH = (h * bodyT) / 2;
400
+ const cy = h / 2;
401
+ let points = [
402
+ [0, cy - bodyHalfH],
403
+ [bodyW, cy - bodyHalfH],
404
+ [bodyW, 0],
405
+ [w, cy],
406
+ [bodyW, h],
407
+ [bodyW, cy + bodyHalfH],
408
+ [0, cy + bodyHalfH],
409
+ ];
410
+ if (direction !== "right") {
411
+ points = points.map(([x, y]) => rotateLocal([x, y], direction, w, h));
412
+ }
413
+ const ptObjs = points.map(([x, y]) => ({ x, y }));
414
+ if (fill) {
415
+ target.beginPath();
416
+ polygonPath(target, ptObjs);
417
+ target.fill();
418
+ }
419
+ if (stroke) {
420
+ const offset = strokeAlignOffset(shape.style);
421
+ const sPts = offset !== 0 ? polygonMath.offsetClosedPath(ptObjs, offset) : ptObjs;
422
+ target.beginPath();
423
+ polygonPath(target, sPts);
424
+ target.stroke();
425
+ }
426
+ };
427
+ const rotateLocal = ([x, y], direction, w, h) => {
428
+ switch (direction) {
429
+ case "left":
430
+ return [w - x, y];
431
+ case "up":
432
+ // Rotate 90° CCW around the box centre, then translate so the
433
+ // result still fits inside [0, w] × [0, h].
434
+ return [y * (w / h), h - x * (h / w)];
435
+ case "down":
436
+ return [(h - y) * (w / h), x * (h / w)];
437
+ }
438
+ };
439
+ /**
440
+ * Frame: dashed outline + header strip with the frame's name.
441
+ * Hit-testing intentionally passes through the body (handled
442
+ * editor-side) so clicks on children inside the frame still land on
443
+ * the child, not the frame chrome.
444
+ */
445
+ const FRAME_STROKE = "#888";
446
+ const FRAME_FILL = "#ffffff";
447
+ const FRAME_HEADER_ELLIPSIS = "…";
448
+ /**
449
+ * Trim `text` with a trailing ellipsis until it fits `maxWidth` (in the
450
+ * font already set on `target`). Returns the full text when it fits, the
451
+ * longest prefix + "…" otherwise, or just "…" when even one char can't
452
+ * fit. Binary-searches the prefix length to keep `measureText` calls ~log.
453
+ */
454
+ const ellipsizeToWidth = (text, maxWidth, target) => {
455
+ if (maxWidth <= 0)
456
+ return "";
457
+ if (target.measureText(text).width <= maxWidth)
458
+ return text;
459
+ let lo = 0;
460
+ let hi = text.length;
461
+ while (lo < hi) {
462
+ const mid = Math.ceil((lo + hi) / 2);
463
+ const w = target.measureText(text.slice(0, mid) + FRAME_HEADER_ELLIPSIS).width;
464
+ if (w <= maxWidth)
465
+ lo = mid;
466
+ else
467
+ hi = mid - 1;
468
+ }
469
+ return lo > 0 ? text.slice(0, lo) + FRAME_HEADER_ELLIPSIS : FRAME_HEADER_ELLIPSIS;
470
+ };
471
+ const drawFrame = (shape, target, ctx) => {
472
+ // Body — solid fill + thin solid outline. Frames sit at the bottom
473
+ // z-order, so the fill backs their members without covering them.
474
+ // Honours an explicit `style.fill`, else default white.
475
+ target.setFill(shape.style.fill ?? FRAME_FILL);
476
+ target.setStroke(null);
477
+ target.setDashArray(null);
478
+ target.beginPath();
479
+ target.rect(0, 0, shape.width, shape.height);
480
+ target.fill();
481
+ // Outline on top of the fill — a 1px SCREEN-constant hairline (doesn't scale
482
+ // with zoom). The renderer draws in local coords where 1 unit = zoom × scale
483
+ // device px, so divide to keep the stroke at one device pixel. Falls back to
484
+ // 1 world-px when no zoom context is supplied (preview / export at 1:1).
485
+ const screenScale = (ctx?.zoom ?? 1) * (shape.scale.x || 1);
486
+ target.setFill(null);
487
+ target.setStroke(FRAME_STROKE);
488
+ target.setStrokeWidth(1 / (screenScale || 1));
489
+ target.setDashArray(null);
490
+ target.beginPath();
491
+ target.rect(0, 0, shape.width, shape.height);
492
+ target.stroke();
493
+ // Header label: the strip hugs the text width but never exceeds the
494
+ // frame's right edge; a name too long for the frame is ellipsised.
495
+ const name = shape.name ?? "Frame";
496
+ target.setFont("system-ui, sans-serif", FRAME_HEADER_FONT_SIZE);
497
+ const avail = shape.width - FRAME_HEADER_PADDING_X * 2;
498
+ const fits = target.measureText(name).width <= avail;
499
+ // Fits → the strip hugs the text. Too long → ellipsise the text and
500
+ // stretch the strip to the frame's full width (the label runs to the
501
+ // right edge).
502
+ const label = fits ? name : ellipsizeToWidth(name, avail, target);
503
+ const headerWidth = fits
504
+ ? Math.min(target.measureText(name).width + FRAME_HEADER_PADDING_X * 2, shape.width)
505
+ : shape.width;
506
+ // Header label background — stretches to fit the (possibly truncated) text.
507
+ target.setFill("#222");
508
+ target.beginPath();
509
+ target.rect(0, -FRAME_HEADER_HEIGHT, headerWidth, FRAME_HEADER_HEIGHT);
510
+ target.fill();
511
+ // Header label text.
512
+ target.setFill("#ddd");
513
+ target.setTextBaseline("middle");
514
+ target.setTextAlign("left");
515
+ target.fillText(label, FRAME_HEADER_PADDING_X, -FRAME_HEADER_HEIGHT / 2);
516
+ };
517
+ //# sourceMappingURL=built-in-renderers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"built-in-renderers.js","sourceRoot":"","sources":["../src/built-in-renderers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Tunable constants for the renderer core. All "magic numbers" used by
3
+ * `renderScene` / `renderLinks` / `renderGrid` live here so there is one
4
+ * place to tweak performance / visual behaviour.
5
+ */
6
+ import type { LodOptions } from "./scene-renderer.js";
7
+ /**
8
+ * Default zoom thresholds for the level-of-detail pipeline. Tuned for
9
+ * a typical 1920×1080 viewport viewing a 10k-shape scene.
10
+ *
11
+ * - `placeholder: 0.15` — below 15% zoom (one screen ≈ 6.7× world),
12
+ * shapes degrade to flat AABB fills. Saves ~10× renderer cost per
13
+ * shape.
14
+ * - `hideText: 0.4` — below 40% zoom text glyphs are too small to read
15
+ * anyway; skipping the `wrapText` + `measureText` calls saves the
16
+ * bulk of text rendering cost.
17
+ *
18
+ * Hosts override per-render by passing `RenderSceneOptions.lod`.
19
+ */
20
+ export declare const DEFAULT_LOD: LodOptions;
21
+ /**
22
+ * Grey colour used for placeholder fills when LOD switches to the
23
+ * cheapest path. A mid-tone neutral that blends with most scene
24
+ * palettes; override via `RenderSceneOptions.placeholderFill`.
25
+ */
26
+ export declare const DEFAULT_PLACEHOLDER_FILL = "#bbb";
27
+ /**
28
+ * Viewport-rect inflation factor applied by hosts when computing the
29
+ * world-space culling rect. 0.05 = 5% padding on each side — enough
30
+ * to avoid flicker during a one-frame pan without keeping much
31
+ * off-screen geometry alive in the renderer.
32
+ */
33
+ export declare const VIEWPORT_CULL_PADDING_RATIO = 0.05;
34
+ /**
35
+ * Text-decoration geometry (underline / strikethrough), as fractions of
36
+ * font size, measured from the line's top (the renderer draws text with
37
+ * a top baseline).
38
+ *
39
+ * - `TEXT_DECORATION_THICKNESS` — line thickness ≈ 6% of font size
40
+ * (clamped to ≥1 px in the renderer).
41
+ * - `TEXT_UNDERLINE_OFFSET` — underline top, ~92% down (just below the
42
+ * glyph baseline).
43
+ * - `TEXT_STRIKETHROUGH_OFFSET` — strikethrough centre, ~50% (x-height).
44
+ */
45
+ export declare const TEXT_DECORATION_THICKNESS = 0.06;
46
+ export declare const TEXT_UNDERLINE_OFFSET = 0.92;
47
+ export declare const TEXT_STRIKETHROUGH_OFFSET = 0.5;
48
+ /**
49
+ * Corner radius (world px) for the rounded bends of an elbow (orthogonal)
50
+ * connector and of a straight connector broken by user waypoints. Each
51
+ * corner is replaced by a quadratic arc of this radius, clamped to half the
52
+ * shorter adjacent segment so short segments don't overshoot. 0 disables
53
+ * rounding (sharp corners). Range: 0–16.
54
+ */
55
+ export declare const LINK_CORNER_RADIUS = 10;
56
+ /** Stroke colour for the ruled (`"lines"`) grid. Neutral step-6 gray. */
57
+ export declare const GRID_LINE_COLOR: string;
58
+ /** Fill colour for the dotted (`"dots"`) grid — darker step-9 gray so the dots stay legible on a gray canvas. */
59
+ export declare const GRID_DOT_FILL: string;
60
+ /** On-screen stroke width (px) of a grid line. Divided by zoom at the use site so the line stays 1 px regardless of view scale. */
61
+ export declare const GRID_LINE_WIDTH_PX = 1;
62
+ /**
63
+ * Dot radius (screen px) for `gridStyle === "dots"`. Constant across
64
+ * zoom (divided by `zoom` at the use site). Reads as a crisp anchor on
65
+ * a gray surface. Range: 1.0–2.0.
66
+ */
67
+ export declare const GRID_DOT_RADIUS_PX = 1;
68
+ /**
69
+ * Below this on-screen spacing (px) a grid level paints nothing —
70
+ * denser rendering reads as a flat haze. Only used by the fixed-ladder
71
+ * path (`options.levels`); the default dynamic ladder uses the fade
72
+ * bands below instead.
73
+ */
74
+ export declare const GRID_MIN_SCREEN_SPACING_PX = 4;
75
+ /** Ratio between adjacent rungs. 4 keeps the 64/16/4/1 cadence. */
76
+ export declare const GRID_LEVEL_SUBDIV = 4;
77
+ /**
78
+ * How many self-similar rungs to paint at once (finest first). 3 keeps a
79
+ * stable fully-opaque coarse tier while the finest rung fades in/out.
80
+ */
81
+ export declare const GRID_LEVEL_RUNGS = 3;
82
+ /**
83
+ * Line grid fade band (on-screen px). A rung is invisible at/below
84
+ * `FROM`, ramps to full opacity by `FULL`, and stays full above. Tuned
85
+ * so at 100 % (gridSize 20) the 20 px rung reads faint and the 80 px rung
86
+ * is solid, while subdividing forever.
87
+ */
88
+ export declare const GRID_LINE_FADE_FROM_PX = 12;
89
+ export declare const GRID_LINE_FADE_FULL_PX = 56;
90
+ /**
91
+ * Dot grid fade band. Lower / tighter than lines so the base `gridSize`
92
+ * dot lattice is fully solid at 100 % (the denser dot field) yet still
93
+ * subdivides on zoom-in.
94
+ */
95
+ export declare const GRID_DOT_FADE_FROM_PX = 10;
96
+ export declare const GRID_DOT_FADE_FULL_PX = 20;
97
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAEtD;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,WAAW,EAAE,UAGzB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,SAAS,CAAC;AAE/C;;;;;GAKG;AACH,eAAO,MAAM,2BAA2B,OAAO,CAAC;AAEhD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,yBAAyB,OAAO,CAAC;AAC9C,eAAO,MAAM,qBAAqB,OAAO,CAAC;AAC1C,eAAO,MAAM,yBAAyB,MAAM,CAAC;AAE7C;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,KAAK,CAAC;AASrC,yEAAyE;AACzE,eAAO,MAAM,eAAe,QAAa,CAAC;AAE1C,iHAAiH;AACjH,eAAO,MAAM,aAAa,QAAiB,CAAC;AAE5C,mIAAmI;AACnI,eAAO,MAAM,kBAAkB,IAAM,CAAC;AAEtC;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,IAAI,CAAC;AAEpC;;;;;GAKG;AACH,eAAO,MAAM,0BAA0B,IAAI,CAAC;AAY5C,mEAAmE;AACnE,eAAO,MAAM,iBAAiB,IAAI,CAAC;AAEnC;;;GAGG;AACH,eAAO,MAAM,gBAAgB,IAAI,CAAC;AAElC;;;;;GAKG;AACH,eAAO,MAAM,sBAAsB,KAAK,CAAC;AACzC,eAAO,MAAM,sBAAsB,KAAK,CAAC;AAEzC;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,KAAK,CAAC;AACxC,eAAO,MAAM,qBAAqB,KAAK,CAAC"}