@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,554 @@
1
+ import { flattenSegments, getLinkCurveSegments, getLinkPath, getLinksInLayer, getLayersInOrder, getWorldToScreen, } from "@oh-just-another/scene";
2
+ import { bounds as B } from "@oh-just-another/math";
3
+ import { sharedLinkBoundsCache } from "./edge-cache.js";
4
+ import { zoomBucket as bucketFor } from "./shape-cache-bitmap.js";
5
+ import { LINK_CORNER_RADIUS } from "./constants.js";
6
+ const req = (v) => {
7
+ if (v === undefined)
8
+ throw new Error("packages/renderer-core: index out of range");
9
+ return v;
10
+ };
11
+ /**
12
+ * Draws every edge in the scene, in layer-then-z order. Resolves endpoints
13
+ * through `getLinkPath` (which honours anchor refs and explicit waypoints)
14
+ * and emits the appropriate primitive sequence for the edge's routing.
15
+ *
16
+ * Call this *after* `renderScene` so edges sit on top of shapes. Both
17
+ * functions write to the same `RenderTarget` under the same scene-level
18
+ * viewport transform, so coordinates align.
19
+ */
20
+ export const renderLinks = (scene, target, options = {}) => {
21
+ // Self-contained transform setup so callers can do `renderScene(...);
22
+ // renderLinks(...)` without repeating the world-to-screen step. We
23
+ // never clear here — edges should land on top of an already-rendered
24
+ // shape pass.
25
+ target.save();
26
+ target.setTransform(getWorldToScreen(scene.viewport));
27
+ const cache = options.edgeBoundsCache ?? sharedLinkBoundsCache;
28
+ const cull = options.viewportWorld;
29
+ const dirty = options.dirtyWorld;
30
+ const bitmapCache = options.edgeBitmapCache;
31
+ const rasteriseLink = options.rasteriseLink;
32
+ const zoomBucket = bucketFor(options.zoom ?? scene.viewport.zoom);
33
+ for (const layer of getLayersInOrder(scene)) {
34
+ if (!layer.visible)
35
+ continue;
36
+ for (const edge of getLinksInLayer(scene, layer.id)) {
37
+ let bounds = null;
38
+ if (cull || dirty || (bitmapCache && rasteriseLink)) {
39
+ bounds = cache.getOrCompute(scene, edge);
40
+ if (bounds === null) {
41
+ options.onMissingEndpoint?.(edge);
42
+ continue;
43
+ }
44
+ if (cull && !B.intersects(bounds, cull))
45
+ continue;
46
+ if (dirty && !B.intersects(bounds, dirty))
47
+ continue;
48
+ }
49
+ // Bitmap-cache fast path. Only fires when the host plugged
50
+ // both a cache and a rasteriser — the kernel doesn't know how
51
+ // to make ImageBitmaps without OffscreenCanvas import. Falls
52
+ // through to the regular drawLink on cache miss + null
53
+ // rasteriser result (e.g. host opted out for tiny edges).
54
+ if (bitmapCache && rasteriseLink && bounds) {
55
+ let bitmap = bitmapCache.get(edge, zoomBucket);
56
+ if (bitmap === undefined) {
57
+ const fresh = rasteriseLink(edge, bounds, scene, zoomBucket);
58
+ if (fresh !== null) {
59
+ bitmapCache.set(edge, zoomBucket, fresh);
60
+ bitmap = fresh;
61
+ }
62
+ }
63
+ if (bitmap !== undefined) {
64
+ target.drawImage(bitmap, bounds.x, bounds.y, bounds.width, bounds.height);
65
+ continue;
66
+ }
67
+ }
68
+ drawLink(scene, edge, target, options);
69
+ }
70
+ }
71
+ target.restore();
72
+ };
73
+ const drawLink = (scene, edge, target, options) => {
74
+ const path = getLinkPath(scene, edge);
75
+ if (!path || path.length < 2) {
76
+ options.onMissingEndpoint?.(edge);
77
+ return;
78
+ }
79
+ target.save();
80
+ if ((edge.lineKind ?? "line") === "block-arrow") {
81
+ drawBlockArrowLink(edge, path, target);
82
+ }
83
+ else {
84
+ applyStrokeStyle(edge, target);
85
+ // Curved (bezier): draw the cubic-bezier curve resolved by scene — a
86
+ // no-waypoint span exits/enters perpendicular to the element edges
87
+ // (flowchart look); a waypointed span splines through the bends. The
88
+ // flattened curve feeds the arrowhead so its tangent matches.
89
+ const curve = (edge.routing ?? "straight") === "bezier" ? getLinkCurveSegments(scene, edge) : null;
90
+ target.beginPath();
91
+ if (curve) {
92
+ target.moveTo(curve.start.x, curve.start.y);
93
+ for (const s of curve.segments) {
94
+ target.bezierCurveTo(s.c1.x, s.c1.y, s.c2.x, s.c2.y, s.to.x, s.to.y);
95
+ }
96
+ // LINK_CORNER_RADIUS is a tunable constant; guard stays valid if retuned to 0.
97
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
98
+ }
99
+ else if (path.length >= 3 && LINK_CORNER_RADIUS > 0) {
100
+ // Rounded bends for elbow / waypointed-straight connectors.
101
+ strokeRoundedPolyline(target, path, LINK_CORNER_RADIUS);
102
+ }
103
+ else {
104
+ const first = req(path[0]);
105
+ target.moveTo(first.x, first.y);
106
+ for (let i = 1; i < path.length; i++) {
107
+ const p = req(path[i]);
108
+ target.lineTo(p.x, p.y);
109
+ }
110
+ }
111
+ target.stroke();
112
+ if (edge.arrowheads) {
113
+ const headPath = curve ? flattenSegments(curve.start, curve.segments) : path;
114
+ drawArrowheads(headPath, edge.arrowheads, target, edge.style.stroke ?? "#000");
115
+ }
116
+ }
117
+ if (edge.label) {
118
+ drawLabel(path, edge.label, target);
119
+ }
120
+ target.restore();
121
+ };
122
+ /**
123
+ * Filled block-arrow edge: thickens the entire routed path into a
124
+ * polygon by offsetting each segment perpendicularly by `thickness/2`
125
+ * on both sides, then replaces the last `headLength` units with a
126
+ * triangle pointing at `to`.
127
+ *
128
+ * Designed for orthogonal / straight routing — bezier-routed edges
129
+ * still get block-arrow rendering but the head sits at the last
130
+ * segment endpoint regardless of curve direction.
131
+ */
132
+ const drawBlockArrowLink = (edge, path, target) => {
133
+ const headLength = edge.blockArrow?.headLength ?? 18;
134
+ const thickness = edge.blockArrow?.bodyThickness ?? 12;
135
+ const fill = edge.style.fill ?? edge.style.stroke ?? "#444";
136
+ const stroke = edge.style.stroke ?? "#222";
137
+ const strokeWidth = edge.style.strokeWidth ?? 1;
138
+ if (edge.style.opacity !== undefined)
139
+ target.setOpacity(edge.style.opacity);
140
+ // Shorten the path so the body terminates `headLength` units
141
+ // before `to`; the head triangle fills the gap with a sharper
142
+ // tip on the original endpoint.
143
+ const shortened = shortenPathFromEnd(path, headLength);
144
+ if (shortened.length < 2)
145
+ return;
146
+ // Offset the shortened polyline on both sides by `thickness/2`
147
+ // to build the body polygon (manual one-segment offset; mitre
148
+ // joins on orthogonal routes look fine).
149
+ const left = offsetPolyline(shortened, thickness / 2);
150
+ const right = offsetPolyline(shortened, -thickness / 2);
151
+ const headBaseLeft = req(left[left.length - 1]);
152
+ const headBaseRight = req(right[right.length - 1]);
153
+ const tip = req(path[path.length - 1]);
154
+ target.setFill(fill);
155
+ target.setStroke(stroke);
156
+ target.setStrokeWidth(strokeWidth);
157
+ target.beginPath();
158
+ // Body upper edge — left[0] → left[last] (head base).
159
+ const leftFirst = req(left[0]);
160
+ target.moveTo(leftFirst.x, leftFirst.y);
161
+ for (let i = 1; i < left.length; i++) {
162
+ const p = req(left[i]);
163
+ target.lineTo(p.x, p.y);
164
+ }
165
+ // Head triangle: head base (left) → tip → head base (right).
166
+ // The "barbs" make the head wider than the body so it reads as a
167
+ // proper block-arrow head, not just a continuation.
168
+ const barbExtra = Math.max(0, thickness * 0.5);
169
+ const barbLeft = perpendicularOffset(headBaseLeft, tip, barbExtra);
170
+ const barbRight = perpendicularOffset(headBaseRight, tip, -barbExtra);
171
+ target.lineTo(barbLeft.x, barbLeft.y);
172
+ target.lineTo(tip.x, tip.y);
173
+ target.lineTo(barbRight.x, barbRight.y);
174
+ // Body lower edge back — right[last] → right[0].
175
+ for (let i = right.length - 1; i >= 0; i--) {
176
+ const p = req(right[i]);
177
+ target.lineTo(p.x, p.y);
178
+ }
179
+ target.closePath();
180
+ target.fill();
181
+ if (strokeWidth > 0)
182
+ target.stroke();
183
+ };
184
+ /**
185
+ * Walk the path from the start; drop the final `amount` world
186
+ * units so the head triangle can fill that section. Returns at
187
+ * least one segment (the original first segment) when the path
188
+ * is shorter than `amount`.
189
+ */
190
+ const shortenPathFromEnd = (path, amount) => {
191
+ if (path.length < 2)
192
+ return path;
193
+ let remaining = amount;
194
+ const reversed = [...path].reverse();
195
+ const out = [req(reversed[0])];
196
+ for (let i = 1; i < reversed.length; i++) {
197
+ const a = req(out[out.length - 1]);
198
+ const b = req(reversed[i]);
199
+ const dx = b.x - a.x;
200
+ const dy = b.y - a.y;
201
+ const len = Math.hypot(dx, dy);
202
+ if (len > remaining) {
203
+ const t = remaining / len;
204
+ const cut = { x: a.x + dx * t, y: a.y + dy * t };
205
+ out[out.length - 1] = cut;
206
+ // Push everything after the cut in original order.
207
+ out.push(...reversed.slice(i));
208
+ return out.reverse();
209
+ }
210
+ remaining -= len;
211
+ out[out.length - 1] = b;
212
+ }
213
+ // amount > path length — degenerate; return original.
214
+ return path;
215
+ };
216
+ /**
217
+ * Per-vertex perpendicular offset of a polyline. Works well for
218
+ * orthogonal / straight routing; bezier-routed paths get piecewise
219
+ * approximations.
220
+ */
221
+ const offsetPolyline = (path, offset) => {
222
+ if (path.length < 2)
223
+ return path;
224
+ const out = [];
225
+ for (let i = 0; i < path.length; i++) {
226
+ const prev = req(path[Math.max(0, i - 1)]);
227
+ const next = req(path[Math.min(path.length - 1, i + 1)]);
228
+ const cur = req(path[i]);
229
+ const dx = next.x - prev.x;
230
+ const dy = next.y - prev.y;
231
+ const len = Math.hypot(dx, dy) || 1;
232
+ const nx = -dy / len;
233
+ const ny = dx / len;
234
+ out.push({ x: cur.x + nx * offset, y: cur.y + ny * offset });
235
+ }
236
+ return out;
237
+ };
238
+ /**
239
+ * Move `from` perpendicular to the `from→tip` direction by
240
+ * `amount` world units. Positive amount → left of the direction
241
+ * vector, negative → right.
242
+ */
243
+ const perpendicularOffset = (from, tip, amount) => {
244
+ const dx = tip.x - from.x;
245
+ const dy = tip.y - from.y;
246
+ const len = Math.hypot(dx, dy) || 1;
247
+ const nx = -dy / len;
248
+ const ny = dx / len;
249
+ return { x: from.x + nx * amount, y: from.y + ny * amount };
250
+ };
251
+ /**
252
+ * Drop colinear / near-coincident interior points so only real corners
253
+ * remain — keeps the uniform radius from being tanked by a redundant tiny
254
+ * straight segment (e.g. a buffer joint colinear with the run). Render-only;
255
+ * the stored geometry keeps its points.
256
+ */
257
+ const cornersOnly = (pts) => {
258
+ if (pts.length <= 2)
259
+ return pts;
260
+ const out = [req(pts[0])];
261
+ for (let i = 1; i < pts.length - 1; i++) {
262
+ const prev = req(out[out.length - 1]);
263
+ const cur = req(pts[i]);
264
+ const next = req(pts[i + 1]);
265
+ const horiz = Math.abs(prev.y - cur.y) < 1e-6 && Math.abs(cur.y - next.y) < 1e-6;
266
+ const vert = Math.abs(prev.x - cur.x) < 1e-6 && Math.abs(cur.x - next.x) < 1e-6;
267
+ const coincident = Math.abs(prev.x - cur.x) < 1e-6 && Math.abs(prev.y - cur.y) < 1e-6;
268
+ if (horiz || vert || coincident)
269
+ continue;
270
+ out.push(cur);
271
+ }
272
+ out.push(req(pts[pts.length - 1]));
273
+ return out;
274
+ };
275
+ /**
276
+ * Stroke a polyline with rounded corners: each interior vertex is replaced
277
+ * by a quadratic arc of `radius` (clamped to half the shorter adjacent
278
+ * segment). Works for 90° elbow bends and arbitrary-angle waypoint bends.
279
+ * Caller has already `beginPath()`.
280
+ */
281
+ export const strokeRoundedPolyline = (target, raw, radius) => {
282
+ const pts = cornersOnly(raw);
283
+ if (pts.length < 3) {
284
+ const first = req(pts[0]);
285
+ target.moveTo(first.x, first.y);
286
+ for (let i = 1; i < pts.length; i++) {
287
+ const p = req(pts[i]);
288
+ target.lineTo(p.x, p.y);
289
+ }
290
+ return;
291
+ }
292
+ // Per-corner radius: each corner rounds to the requested radius, clamped to
293
+ // half of EACH adjacent segment (so two corners sharing a short segment meet
294
+ // without overlapping). With spurious tiny segments already removed
295
+ // (cornersOnly + the router's symmetric buffer clamp), every normal corner
296
+ // gets the full radius — stable, no global "jump" — while a deliberately
297
+ // short jog (tight-gap overlap step) rounds smoothly to its own size.
298
+ const ptsFirst = req(pts[0]);
299
+ target.moveTo(ptsFirst.x, ptsFirst.y);
300
+ for (let i = 1; i < pts.length - 1; i++) {
301
+ const prev = req(pts[i - 1]);
302
+ const cur = req(pts[i]);
303
+ const next = req(pts[i + 1]);
304
+ const l1 = Math.hypot(prev.x - cur.x, prev.y - cur.y);
305
+ const l2 = Math.hypot(next.x - cur.x, next.y - cur.y);
306
+ if (l1 < 1e-6 || l2 < 1e-6) {
307
+ target.lineTo(cur.x, cur.y);
308
+ continue;
309
+ }
310
+ const r = Math.min(radius, l1 / 2, l2 / 2);
311
+ const a = { x: cur.x + ((prev.x - cur.x) / l1) * r, y: cur.y + ((prev.y - cur.y) / l1) * r };
312
+ const b = { x: cur.x + ((next.x - cur.x) / l2) * r, y: cur.y + ((next.y - cur.y) / l2) * r };
313
+ target.lineTo(a.x, a.y);
314
+ target.quadraticCurveTo(cur.x, cur.y, b.x, b.y);
315
+ }
316
+ const ptsLast = req(pts[pts.length - 1]);
317
+ target.lineTo(ptsLast.x, ptsLast.y);
318
+ };
319
+ const applyStrokeStyle = (edge, target) => {
320
+ const stroke = edge.style.stroke ?? "#000";
321
+ target.setStroke(stroke);
322
+ target.setFill(null);
323
+ target.setStrokeWidth(edge.style.strokeWidth ?? 1);
324
+ if (edge.style.opacity !== undefined)
325
+ target.setOpacity(edge.style.opacity);
326
+ if (edge.style.lineCap !== undefined)
327
+ target.setLineCap(edge.style.lineCap);
328
+ if (edge.style.lineJoin !== undefined)
329
+ target.setLineJoin(edge.style.lineJoin);
330
+ target.setDashArray(edge.style.dashArray ?? null);
331
+ };
332
+ const drawArrowheads = (path, heads, target, color) => {
333
+ const size = heads.size ?? 10;
334
+ if (heads.from && heads.from !== "none") {
335
+ const tip = path[0];
336
+ const next = path[1];
337
+ if (tip !== undefined && next !== undefined) {
338
+ drawArrowhead(tip, next, heads.from, size, target, color);
339
+ }
340
+ }
341
+ if (heads.to && heads.to !== "none") {
342
+ const tip = path[path.length - 1];
343
+ const prev = path[path.length - 2];
344
+ if (tip !== undefined && prev !== undefined) {
345
+ drawArrowhead(tip, prev, heads.to, size, target, color);
346
+ }
347
+ }
348
+ };
349
+ const drawArrowhead = (tip, fromPoint, style, size, target, color) => {
350
+ // Unit vector pointing away from the tip toward the previous point.
351
+ const dx = fromPoint.x - tip.x;
352
+ const dy = fromPoint.y - tip.y;
353
+ const len = Math.hypot(dx, dy) || 1;
354
+ const ux = dx / len;
355
+ const uy = dy / len;
356
+ // Perpendicular.
357
+ const px = -uy;
358
+ const py = ux;
359
+ const half = size * 0.5;
360
+ // Point `d` along the line from the tip; `o` adds a perpendicular offset.
361
+ const along = (d) => ({ x: tip.x + ux * d, y: tip.y + uy * d });
362
+ const at = (d, o) => ({
363
+ x: tip.x + ux * d + px * o,
364
+ y: tip.y + uy * d + py * o,
365
+ });
366
+ const fillShape = () => {
367
+ target.setFill(color);
368
+ target.fill();
369
+ target.setFill(null);
370
+ target.stroke();
371
+ };
372
+ switch (style) {
373
+ // --- open line heads ---
374
+ case "arrow":
375
+ case "openArrow":
376
+ case "roundedArrow": {
377
+ const wing = style === "openArrow" ? size * 0.65 : half;
378
+ const back = style === "openArrow" ? size * 1.1 : size;
379
+ if (style === "roundedArrow")
380
+ target.setLineCap("round");
381
+ target.beginPath();
382
+ target.moveTo(tip.x, tip.y);
383
+ target.lineTo(tip.x + ux * back + px * wing, tip.y + uy * back + py * wing);
384
+ target.moveTo(tip.x, tip.y);
385
+ target.lineTo(tip.x + ux * back - px * wing, tip.y + uy * back - py * wing);
386
+ target.stroke();
387
+ if (style === "roundedArrow")
388
+ target.setLineCap("butt");
389
+ break;
390
+ }
391
+ case "arcArrow": {
392
+ // Open V with a concave back (quadratic curve between the wings).
393
+ const w1 = at(size, half);
394
+ const w2 = at(size, -half);
395
+ const ctrl = along(size * 0.45);
396
+ target.beginPath();
397
+ target.moveTo(w1.x, w1.y);
398
+ target.lineTo(tip.x, tip.y);
399
+ target.lineTo(w2.x, w2.y);
400
+ target.quadraticCurveTo(ctrl.x, ctrl.y, w1.x, w1.y);
401
+ target.stroke();
402
+ break;
403
+ }
404
+ // --- triangles ---
405
+ case "triangle": {
406
+ // Outlined triangle.
407
+ target.beginPath();
408
+ target.moveTo(tip.x, tip.y);
409
+ target.lineTo(...xy(at(size, half)));
410
+ target.lineTo(...xy(at(size, -half)));
411
+ target.closePath();
412
+ target.stroke();
413
+ break;
414
+ }
415
+ case "filledArrow": {
416
+ target.beginPath();
417
+ target.moveTo(tip.x, tip.y);
418
+ target.lineTo(...xy(at(size, half)));
419
+ target.lineTo(...xy(at(size, -half)));
420
+ target.closePath();
421
+ fillShape();
422
+ break;
423
+ }
424
+ // --- circles ---
425
+ case "circle":
426
+ case "filledCircle": {
427
+ const r = half;
428
+ const c = along(r);
429
+ target.beginPath();
430
+ target.ellipse(c.x, c.y, r, r);
431
+ if (style === "filledCircle")
432
+ fillShape();
433
+ else
434
+ target.stroke();
435
+ break;
436
+ }
437
+ // --- rhombus / diamond ---
438
+ case "diamond":
439
+ case "rhombus":
440
+ case "filledRhombus": {
441
+ target.beginPath();
442
+ target.moveTo(tip.x, tip.y);
443
+ target.lineTo(...xy(at(size, half)));
444
+ target.lineTo(...xy(along(size * 2)));
445
+ target.lineTo(...xy(at(size, -half)));
446
+ target.closePath();
447
+ if (style === "filledRhombus")
448
+ fillShape();
449
+ else
450
+ target.stroke();
451
+ break;
452
+ }
453
+ // --- ERD crow's-foot notation ---
454
+ // A "bar" is a perpendicular tick; "many" is the three-pronged foot;
455
+ // "zero" prefixes a small circle. Distances are measured back from the
456
+ // tip so the foot opens toward the connected entity.
457
+ case "erdOne":
458
+ case "erdOnlyOne":
459
+ case "erdMany":
460
+ case "erdOneOrMany":
461
+ case "erdZeroOrOne":
462
+ case "erdZeroOrMany": {
463
+ const wantsMany = style === "erdMany" || style === "erdOneOrMany" || style === "erdZeroOrMany";
464
+ const wantsZero = style === "erdZeroOrOne" || style === "erdZeroOrMany";
465
+ const twoBars = style === "erdOnlyOne";
466
+ const oneBar = style === "erdOne" || style === "erdOnlyOne" || style === "erdOneOrMany" || style === "erdZeroOrOne";
467
+ // Crow's foot: three lines from a base point back to the tip's spread.
468
+ if (wantsMany) {
469
+ const base = along(size);
470
+ target.beginPath();
471
+ target.moveTo(base.x, base.y);
472
+ target.lineTo(tip.x, tip.y);
473
+ target.moveTo(base.x, base.y);
474
+ target.lineTo(...xy(at(0, half)));
475
+ target.moveTo(base.x, base.y);
476
+ target.lineTo(...xy(at(0, -half)));
477
+ target.stroke();
478
+ }
479
+ // Bars sit just behind the foot (or at the tip for pure one/only-one).
480
+ const barBase = wantsMany ? size * 1.15 : size * 0.55;
481
+ const drawBar = (d) => {
482
+ target.beginPath();
483
+ target.moveTo(...xy(at(d, half)));
484
+ target.lineTo(...xy(at(d, -half)));
485
+ target.stroke();
486
+ };
487
+ if (oneBar)
488
+ drawBar(barBase);
489
+ if (twoBars)
490
+ drawBar(barBase + size * 0.4);
491
+ if (wantsZero) {
492
+ const r = half * 0.6;
493
+ const c = along(size * (wantsMany ? 1.6 : 1.0) + r);
494
+ target.beginPath();
495
+ target.ellipse(c.x, c.y, r, r);
496
+ target.stroke();
497
+ }
498
+ break;
499
+ }
500
+ }
501
+ };
502
+ // Tuple helper so `target.lineTo(...xy(p))` reads cleanly.
503
+ const xy = (p) => [p.x, p.y];
504
+ const drawLabel = (path, label, target) => {
505
+ const t = label.position ?? 0.5;
506
+ const fontSize = label.fontSize ?? 12;
507
+ const fill = label.fill ?? "#222";
508
+ const bg = label.background ?? "#fff";
509
+ const point = pointAlongPath(path, t);
510
+ const halfWidth = label.text.length * fontSize * 0.3 + 4; // rough estimate
511
+ const halfHeight = fontSize * 0.7;
512
+ // Pill background so the label is readable over the line.
513
+ target.beginPath();
514
+ target.setFill(bg);
515
+ target.setStroke(null);
516
+ target.rect(point.x - halfWidth, point.y - halfHeight, halfWidth * 2, halfHeight * 2);
517
+ target.fill();
518
+ target.setFill(fill);
519
+ target.setFont("system-ui, sans-serif", fontSize);
520
+ target.setTextAlign("center");
521
+ target.setTextBaseline("middle");
522
+ target.fillText(label.text, point.x, point.y);
523
+ };
524
+ const pointAlongPath = (path, t) => {
525
+ if (path.length === 2) {
526
+ const [a, b] = path;
527
+ return { x: a.x + (b.x - a.x) * t, y: a.y + (b.y - a.y) * t };
528
+ }
529
+ // Walk segments by cumulative length and find the point at `t * total`.
530
+ const lengths = [];
531
+ let total = 0;
532
+ for (let i = 1; i < path.length; i++) {
533
+ const cur = req(path[i]);
534
+ const prev = req(path[i - 1]);
535
+ const dx = cur.x - prev.x;
536
+ const dy = cur.y - prev.y;
537
+ const len = Math.hypot(dx, dy);
538
+ lengths.push(len);
539
+ total += len;
540
+ }
541
+ let remaining = total * t;
542
+ for (let i = 0; i < lengths.length; i++) {
543
+ const segLen = req(lengths[i]);
544
+ if (remaining <= segLen) {
545
+ const ratio = segLen === 0 ? 0 : remaining / segLen;
546
+ const a = req(path[i]);
547
+ const b = req(path[i + 1]);
548
+ return { x: a.x + (b.x - a.x) * ratio, y: a.y + (b.y - a.y) * ratio };
549
+ }
550
+ remaining -= segLen;
551
+ }
552
+ return req(path[path.length - 1]);
553
+ };
554
+ //# sourceMappingURL=edge-renderer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"edge-renderer.js","sourceRoot":"","sources":["../src/edge-renderer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,55 @@
1
+ import { type Scene } from "@oh-just-another/scene";
2
+ import type { RenderTarget } from "./render-target.js";
3
+ export interface RenderGridOptions {
4
+ /** Stroke / fill colour for the grid primitives. Defaults to `GRID_COLOR` from `@oh-just-another/tokens`. */
5
+ readonly color?: string;
6
+ /** Skip the implicit `target.clear()` before drawing. Default `false`. */
7
+ readonly skipClear?: boolean;
8
+ /**
9
+ * Fixed multi-level step ladder. Each entry says "this `step` (in
10
+ * `gridSize` units) is fully visible once the zoom reaches `mid`, fades
11
+ * in from `min` to `mid`, and hides below `min`". When omitted the grid
12
+ * uses the default DYNAMIC (infinite) ladder — see {@link computeGridRungs}
13
+ * — which keeps subdividing at every zoom instead of bottoming out at the
14
+ * ladder's finest rung.
15
+ */
16
+ readonly levels?: readonly GridLevel[];
17
+ }
18
+ export interface GridLevel {
19
+ /** Below this zoom the level paints nothing. */
20
+ readonly min: number;
21
+ /** At and above this zoom the level paints at full opacity. */
22
+ readonly mid: number;
23
+ /** Step in `gridSize` units (1 = the user's base grid, 4 = every 4th, …). */
24
+ readonly step: number;
25
+ }
26
+ /** One rung of the dynamic ladder: a world-space step and its opacity. */
27
+ export interface GridRung {
28
+ /** Spacing between lines / dots, in world units. */
29
+ readonly step: number;
30
+ /** Paint opacity in [0, 1]. */
31
+ readonly opacity: number;
32
+ }
33
+ /**
34
+ * Compute the dynamic, self-similar grid ladder for a given zoom. The
35
+ * rungs are anchored to the current zoom — the finest rung is the
36
+ * smallest `gridSize · SUBDIV^k` (k ∈ ℤ, possibly negative → finer than
37
+ * `gridSize`) whose on-screen spacing is at least `fadeFromPx` — so as
38
+ * the zoom changes the whole ladder slides and a new rung always fades
39
+ * in. Each rung's opacity ramps from `fadeFromPx` (0) to `fadeFullPx`
40
+ * (1) of on-screen spacing. Pure / allocation-light; exported for tests.
41
+ */
42
+ export declare const computeGridRungs: (gridSize: number, zoom: number, fadeFromPx: number, fadeFullPx: number, subdiv?: number, rungs?: number) => GridRung[];
43
+ /**
44
+ * Self-similar background grid. By default it paints a DYNAMIC ladder
45
+ * (see {@link computeGridRungs}): a handful of zoom-anchored rungs, each
46
+ * `GRID_LEVEL_SUBDIV`× the previous, so new lines / dots fade in at every
47
+ * zoom — there's no fixed finest rung to bottom out on. Pass
48
+ * `options.levels` for the fixed-ladder behaviour.
49
+ *
50
+ * Designed for a dedicated background layer (`target.clear()` ed before
51
+ * painting unless `skipClear` is set). The fill / stroke colour is one
52
+ * constant — opacity carries the level distinction.
53
+ */
54
+ export declare const renderGrid: (scene: Scene, target: RenderTarget, options?: RenderGridOptions) => void;
55
+ //# sourceMappingURL=grid-renderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grid-renderer.d.ts","sourceRoot":"","sources":["../src/grid-renderer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsC,KAAK,KAAK,EAAE,MAAM,wBAAwB,CAAC;AAGxF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAevD,MAAM,WAAW,iBAAiB;IAChC,6GAA6G;IAC7G,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,0EAA0E;IAC1E,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAC7B;;;;;;;OAOG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,SAAS,EAAE,CAAC;CACxC;AAED,MAAM,WAAW,SAAS;IACxB,gDAAgD;IAChD,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,+DAA+D;IAC/D,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,6EAA6E;IAC7E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,0EAA0E;AAC1E,MAAM,WAAW,QAAQ;IACvB,oDAAoD;IACpD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,+BAA+B;IAC/B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,gBAAgB,GAC3B,UAAU,MAAM,EAChB,MAAM,MAAM,EACZ,YAAY,MAAM,EAClB,YAAY,MAAM,EAClB,eAA0B,EAC1B,cAAwB,KACvB,QAAQ,EAmBV,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,UAAU,GACrB,OAAO,KAAK,EACZ,QAAQ,YAAY,EACpB,UAAS,iBAAsB,KAC9B,IAkDF,CAAC"}