@kgdiff/renderer 0.0.0-stage → 0.2.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 (143) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +53 -2
  3. package/dist/atlas.d.ts +55 -0
  4. package/dist/atlas.d.ts.map +1 -0
  5. package/dist/atlas.js +132 -0
  6. package/dist/atlas.js.map +1 -0
  7. package/dist/camera.d.ts +116 -0
  8. package/dist/camera.d.ts.map +1 -0
  9. package/dist/camera.js +368 -0
  10. package/dist/camera.js.map +1 -0
  11. package/dist/color.d.ts +12 -0
  12. package/dist/color.d.ts.map +1 -0
  13. package/dist/color.js +51 -0
  14. package/dist/color.js.map +1 -0
  15. package/dist/ctx.d.ts +57 -0
  16. package/dist/ctx.d.ts.map +1 -0
  17. package/dist/ctx.js +28 -0
  18. package/dist/ctx.js.map +1 -0
  19. package/dist/draw/background.d.ts +33 -0
  20. package/dist/draw/background.d.ts.map +1 -0
  21. package/dist/draw/background.js +105 -0
  22. package/dist/draw/background.js.map +1 -0
  23. package/dist/draw/badges.d.ts +26 -0
  24. package/dist/draw/badges.d.ts.map +1 -0
  25. package/dist/draw/badges.js +82 -0
  26. package/dist/draw/badges.js.map +1 -0
  27. package/dist/draw/collapsed.d.ts +15 -0
  28. package/dist/draw/collapsed.d.ts.map +1 -0
  29. package/dist/draw/collapsed.js +67 -0
  30. package/dist/draw/collapsed.js.map +1 -0
  31. package/dist/draw/edges.d.ts +14 -0
  32. package/dist/draw/edges.d.ts.map +1 -0
  33. package/dist/draw/edges.js +115 -0
  34. package/dist/draw/edges.js.map +1 -0
  35. package/dist/draw/glyphs.d.ts +31 -0
  36. package/dist/draw/glyphs.d.ts.map +1 -0
  37. package/dist/draw/glyphs.js +114 -0
  38. package/dist/draw/glyphs.js.map +1 -0
  39. package/dist/draw/halos.d.ts +19 -0
  40. package/dist/draw/halos.d.ts.map +1 -0
  41. package/dist/draw/halos.js +91 -0
  42. package/dist/draw/halos.js.map +1 -0
  43. package/dist/draw/labels.d.ts +55 -0
  44. package/dist/draw/labels.d.ts.map +1 -0
  45. package/dist/draw/labels.js +300 -0
  46. package/dist/draw/labels.js.map +1 -0
  47. package/dist/draw/link.d.ts +25 -0
  48. package/dist/draw/link.d.ts.map +1 -0
  49. package/dist/draw/link.js +122 -0
  50. package/dist/draw/link.js.map +1 -0
  51. package/dist/draw/nodes.d.ts +13 -0
  52. package/dist/draw/nodes.d.ts.map +1 -0
  53. package/dist/draw/nodes.js +165 -0
  54. package/dist/draw/nodes.js.map +1 -0
  55. package/dist/draw/shapes.d.ts +7 -0
  56. package/dist/draw/shapes.d.ts.map +1 -0
  57. package/dist/draw/shapes.js +26 -0
  58. package/dist/draw/shapes.js.map +1 -0
  59. package/dist/draw/view.d.ts +36 -0
  60. package/dist/draw/view.d.ts.map +1 -0
  61. package/dist/draw/view.js +16 -0
  62. package/dist/draw/view.js.map +1 -0
  63. package/dist/frame-cache.d.ts +103 -0
  64. package/dist/frame-cache.d.ts.map +1 -0
  65. package/dist/frame-cache.js +349 -0
  66. package/dist/frame-cache.js.map +1 -0
  67. package/dist/index.d.ts +162 -0
  68. package/dist/index.d.ts.map +1 -0
  69. package/dist/index.js +19 -0
  70. package/dist/index.js.map +1 -0
  71. package/dist/input.d.ts +81 -0
  72. package/dist/input.d.ts.map +1 -0
  73. package/dist/input.js +329 -0
  74. package/dist/input.js.map +1 -0
  75. package/dist/labels.d.ts +103 -0
  76. package/dist/labels.d.ts.map +1 -0
  77. package/dist/labels.js +203 -0
  78. package/dist/labels.js.map +1 -0
  79. package/dist/math.d.ts +33 -0
  80. package/dist/math.d.ts.map +1 -0
  81. package/dist/math.js +138 -0
  82. package/dist/math.js.map +1 -0
  83. package/dist/minimap.d.ts +56 -0
  84. package/dist/minimap.d.ts.map +1 -0
  85. package/dist/minimap.js +501 -0
  86. package/dist/minimap.js.map +1 -0
  87. package/dist/paint-stats.d.ts +17 -0
  88. package/dist/paint-stats.d.ts.map +1 -0
  89. package/dist/paint-stats.js +23 -0
  90. package/dist/paint-stats.js.map +1 -0
  91. package/dist/paint.d.ts +64 -0
  92. package/dist/paint.d.ts.map +1 -0
  93. package/dist/paint.js +197 -0
  94. package/dist/paint.js.map +1 -0
  95. package/dist/pick.d.ts +26 -0
  96. package/dist/pick.d.ts.map +1 -0
  97. package/dist/pick.js +125 -0
  98. package/dist/pick.js.map +1 -0
  99. package/dist/renderer.d.ts +28 -0
  100. package/dist/renderer.d.ts.map +1 -0
  101. package/dist/renderer.js +470 -0
  102. package/dist/renderer.js.map +1 -0
  103. package/dist/smooth-zoom.d.ts +21 -0
  104. package/dist/smooth-zoom.d.ts.map +1 -0
  105. package/dist/smooth-zoom.js +52 -0
  106. package/dist/smooth-zoom.js.map +1 -0
  107. package/dist/spatial.d.ts +26 -0
  108. package/dist/spatial.d.ts.map +1 -0
  109. package/dist/spatial.js +103 -0
  110. package/dist/spatial.js.map +1 -0
  111. package/dist/text.d.ts +36 -0
  112. package/dist/text.d.ts.map +1 -0
  113. package/dist/text.js +123 -0
  114. package/dist/text.js.map +1 -0
  115. package/package.json +47 -3
  116. package/src/atlas.ts +171 -0
  117. package/src/camera.ts +482 -0
  118. package/src/color.ts +58 -0
  119. package/src/ctx.ts +102 -0
  120. package/src/draw/background.ts +139 -0
  121. package/src/draw/badges.ts +93 -0
  122. package/src/draw/collapsed.ts +86 -0
  123. package/src/draw/edges.ts +135 -0
  124. package/src/draw/glyphs.ts +168 -0
  125. package/src/draw/halos.ts +101 -0
  126. package/src/draw/labels.ts +399 -0
  127. package/src/draw/link.ts +157 -0
  128. package/src/draw/nodes.ts +184 -0
  129. package/src/draw/shapes.ts +36 -0
  130. package/src/draw/view.ts +37 -0
  131. package/src/frame-cache.ts +382 -0
  132. package/src/index.ts +161 -0
  133. package/src/input.ts +370 -0
  134. package/src/labels.ts +269 -0
  135. package/src/math.ts +185 -0
  136. package/src/minimap.ts +545 -0
  137. package/src/paint-stats.ts +38 -0
  138. package/src/paint.ts +235 -0
  139. package/src/pick.ts +173 -0
  140. package/src/renderer.ts +539 -0
  141. package/src/smooth-zoom.ts +65 -0
  142. package/src/spatial.ts +94 -0
  143. package/src/text.ts +130 -0
package/dist/paint.js ADDED
@@ -0,0 +1,197 @@
1
+ /**
2
+ * Paints one frame (or a swipe pair) into a `Ctx2D`. Pass order (docs/visual-language.md):
3
+ * background + grid → collapsed pills → edges → glyph arcs → halos → nodes (+ rings, pulses)
4
+ * → pivots → badges → labels. Swipe draws the background once, then each side clipped to its
5
+ * half with its own label placement.
6
+ */
7
+ import { LabelAtlas } from './atlas.js';
8
+ import { drawBackground, GridTiles } from './draw/background.js';
9
+ import { BadgePass } from './draw/badges.js';
10
+ import { drawCollapsed } from './draw/collapsed.js';
11
+ import { drawEdges } from './draw/edges.js';
12
+ import { drawGlyphArcs, drawPivots } from './draw/glyphs.js';
13
+ import { drawHalos, HaloSprites } from './draw/halos.js';
14
+ import { LabelPass } from './draw/labels.js';
15
+ import { drawNodes } from './draw/nodes.js';
16
+ import { Interner } from './frame-cache.js';
17
+ import { CollisionGrid } from './labels.js';
18
+ import { clamp, snap } from './math.js';
19
+ import { createStats, resetStats } from './paint-stats.js';
20
+ import { Fonts, TextMeasurer } from './text.js';
21
+ export function isSplit(frame) {
22
+ return 'before' in frame && 'after' in frame && 'split' in frame;
23
+ }
24
+ /** Divider position (css px, on the device-pixel grid) for a split fraction. */
25
+ export function splitX(split, width, dpr) {
26
+ return snap(clamp(Number.isFinite(split) ? split : 0.5, 0, 1) * width, dpr);
27
+ }
28
+ /** Caches that live as long as a renderer: fonts, text metrics, sprites, atlas, tiles. */
29
+ export class Resources {
30
+ factory;
31
+ fonts;
32
+ measurer;
33
+ atlas;
34
+ halos;
35
+ tiles;
36
+ interner = new Interner();
37
+ dpr = 0;
38
+ theme;
39
+ constructor(factory, theme, fallbackMeasureCtx) {
40
+ this.factory = factory;
41
+ this.theme = theme;
42
+ this.fonts = new Fonts(theme);
43
+ // A private context for measuring, so measuring never disturbs drawing state.
44
+ this.measurer = new TextMeasurer(factory(1, 1)?.ctx ?? fallbackMeasureCtx);
45
+ this.atlas = new LabelAtlas(factory);
46
+ this.halos = new HaloSprites(factory);
47
+ this.tiles = new GridTiles(factory);
48
+ }
49
+ setTheme(theme) {
50
+ if (theme === this.theme)
51
+ return;
52
+ this.theme = theme;
53
+ this.fonts.setTheme(theme);
54
+ this.measurer.clear();
55
+ this.halos.clear();
56
+ this.tiles.clear();
57
+ this.atlas?.configure(this.dpr || 1, theme.canvas.background);
58
+ }
59
+ /** Called before painting: re-keys pixel-ratio dependent caches. */
60
+ prepare(dpr) {
61
+ if (dpr === this.dpr)
62
+ return;
63
+ this.dpr = dpr;
64
+ this.tiles.clear();
65
+ this.atlas?.configure(dpr, this.theme.canvas.background);
66
+ }
67
+ /** Web fonts finished loading: metrics and rasterized labels are stale. */
68
+ fontsChanged() {
69
+ this.measurer.clear();
70
+ this.atlas?.wipe();
71
+ }
72
+ }
73
+ /** New label rasterizations per frame (≈ 3–5 ms of text rendering on mid-range hardware). */
74
+ export const LABEL_RASTER_BUDGET = 160;
75
+ export class Painter {
76
+ res;
77
+ stats = createStats();
78
+ /** Override for exports, which must contain every label in one paint. */
79
+ rasterBudget = LABEL_RASTER_BUDGET;
80
+ labels = new LabelPass();
81
+ badges = new BadgePass();
82
+ grid = new CollisionGrid();
83
+ view = {
84
+ k: 1,
85
+ ox: 0,
86
+ oy: 0,
87
+ width: 0,
88
+ height: 0,
89
+ dpr: 1,
90
+ x0: 0,
91
+ x1: 0,
92
+ y0: 0,
93
+ y1: 0,
94
+ strictX: false,
95
+ stats: this.stats,
96
+ };
97
+ constructor(res) {
98
+ this.res = res;
99
+ }
100
+ paint(target, cam, frame, caches, version, theme, grid) {
101
+ const { ctx, width, height, dpr } = target;
102
+ const v = this.view;
103
+ resetStats(this.stats);
104
+ this.res.prepare(dpr);
105
+ this.res.atlas?.beginFrame(this.rasterBudget);
106
+ v.k = cam.k;
107
+ v.ox = width / 2 - cam.x * cam.k;
108
+ v.oy = height / 2 - cam.y * cam.k;
109
+ v.width = width;
110
+ v.height = height;
111
+ v.dpr = dpr;
112
+ v.x0 = 0;
113
+ v.x1 = width;
114
+ v.y0 = 0;
115
+ v.y1 = height;
116
+ v.strictX = false;
117
+ ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
118
+ ctx.imageSmoothingEnabled = true;
119
+ const split = frame !== null && isSplit(frame);
120
+ const spotlight = frame === null
121
+ ? 0
122
+ : split
123
+ ? Math.max(frame.before.spotlight, frame.after.spotlight)
124
+ : frame.spotlight;
125
+ drawBackground(ctx, v, theme, grid ? this.res.tiles : null, spotlight);
126
+ this.stats.phases.push('background');
127
+ if (frame === null)
128
+ return this.stats;
129
+ if (!split) {
130
+ caches.main.sync(frame, version, this.res.interner);
131
+ this.layers(ctx, frame, caches.main, theme);
132
+ return this.stats;
133
+ }
134
+ const sx = splitX(frame.split, width, dpr);
135
+ caches.before.sync(frame.before, version, this.res.interner);
136
+ caches.after.sync(frame.after, version, this.res.interner);
137
+ if (sx > 0) {
138
+ v.x0 = 0;
139
+ v.x1 = sx;
140
+ v.strictX = true;
141
+ ctx.save();
142
+ ctx.beginPath();
143
+ ctx.rect(0, 0, sx, height);
144
+ ctx.clip();
145
+ this.layers(ctx, frame.before, caches.before, theme);
146
+ ctx.restore();
147
+ }
148
+ if (sx < width) {
149
+ v.x0 = sx;
150
+ v.x1 = width;
151
+ v.strictX = true;
152
+ ctx.save();
153
+ ctx.beginPath();
154
+ ctx.rect(sx, 0, width - sx, height);
155
+ ctx.clip();
156
+ this.layers(ctx, frame.after, caches.after, theme);
157
+ ctx.restore();
158
+ }
159
+ if (sx > 0 && sx < width) {
160
+ // 1 css px divider on whole device pixels.
161
+ const w = Math.max(1, Math.round(dpr));
162
+ ctx.globalAlpha = 1;
163
+ ctx.fillStyle = theme.surface.borderStrong;
164
+ ctx.fillRect(Math.round(sx * dpr - w / 2) / dpr, 0, w / dpr, height);
165
+ }
166
+ this.stats.phases.push('divider');
167
+ return this.stats;
168
+ }
169
+ layers(ctx, frame, cache, theme) {
170
+ const v = this.view;
171
+ const res = this.res;
172
+ const phases = this.stats.phases;
173
+ // Screen-space layout first: node discs and badges are obstacles; labels and pills compete
174
+ // for the rest by priority. Drawing then follows the documented pass order.
175
+ this.labels.begin(frame, cache, v, this.grid);
176
+ this.badges.layout(frame, cache, v, res.fonts, res.measurer, this.grid);
177
+ this.labels.place(frame, cache, v, res, this.grid);
178
+ drawCollapsed(ctx, frame.collapsed, cache.pillShown, v, theme, res.fonts, res.measurer);
179
+ phases.push('collapsed');
180
+ drawEdges(ctx, frame, cache, v);
181
+ phases.push('edges');
182
+ drawGlyphArcs(ctx, frame, cache, v, theme, res.fonts);
183
+ phases.push('glyphs');
184
+ drawHalos(ctx, frame, cache, v, theme, res.halos);
185
+ phases.push('halos');
186
+ drawNodes(ctx, frame, cache, v, theme);
187
+ phases.push('nodes');
188
+ drawPivots(ctx, frame, cache, v, theme);
189
+ phases.push('pivots');
190
+ this.badges.draw(ctx, frame, theme);
191
+ phases.push('badges');
192
+ this.stats.labels += this.labels.draw(ctx, v, theme, res);
193
+ this.stats.deferredLabels = res.atlas?.deferred ?? 0;
194
+ phases.push('labels');
195
+ }
196
+ }
197
+ //# sourceMappingURL=paint.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paint.js","sourceRoot":"","sources":["../src/paint.ts"],"names":[],"mappings":"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"}
package/dist/pick.d.ts ADDED
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Hit testing at a screen point, topmost first: nodes (grid lookup; a point inside a disc beats
3
+ * the tolerance ring, then higher z), then edges (distance to the segment / curve / loop, higher
4
+ * z first), then collapsed pills. Invisible and fully transparent elements, and pills hidden by
5
+ * label collision, are never picked.
6
+ */
7
+ import type { FrameVisuals } from '@kgdiff/scene';
8
+ import type { FrameCache } from './frame-cache.js';
9
+ import type { PickResult } from './index.js';
10
+ import type { Fonts, TextMeasurer } from './text.js';
11
+ /** Extra reach (px) around node discs. */
12
+ export declare const NODE_PICK_TOLERANCE = 3;
13
+ /** Extra reach (px) beyond half an edge's width. */
14
+ export declare const EDGE_PICK_TOLERANCE = 4;
15
+ export interface PickView {
16
+ readonly k: number;
17
+ readonly ox: number;
18
+ readonly oy: number;
19
+ readonly dpr: number;
20
+ }
21
+ export declare function pickNode(frame: FrameVisuals, cache: FrameCache, v: PickView, sx: number, sy: number): number;
22
+ export declare function pickEdge(frame: FrameVisuals, cache: FrameCache, v: PickView, sx: number, sy: number): number;
23
+ export declare function pickCollapsed(frame: FrameVisuals, cache: FrameCache, v: PickView, sx: number, sy: number, fonts: Fonts, measurer: TextMeasurer): number;
24
+ /** Topmost element at screen point (sx, sy), or null. */
25
+ export declare function pickAt(frame: FrameVisuals, cache: FrameCache, v: PickView, sx: number, sy: number, fonts: Fonts, measurer: TextMeasurer): PickResult | null;
26
+ //# sourceMappingURL=pick.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pick.d.ts","sourceRoot":"","sources":["../src/pick.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAKlD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,OAAO,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAErD,0CAA0C;AAC1C,eAAO,MAAM,mBAAmB,IAAI,CAAC;AACrC,oDAAoD;AACpD,eAAO,MAAM,mBAAmB,IAAI,CAAC;AAErC,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AAKD,wBAAgB,QAAQ,CACtB,KAAK,EAAE,YAAY,EACnB,KAAK,EAAE,UAAU,EACjB,CAAC,EAAE,QAAQ,EACX,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,GACT,MAAM,CA+BR;AAED,wBAAgB,QAAQ,CACtB,KAAK,EAAE,YAAY,EACnB,KAAK,EAAE,UAAU,EACjB,CAAC,EAAE,QAAQ,EACX,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,GACT,MAAM,CAmDR;AAED,wBAAgB,aAAa,CAC3B,KAAK,EAAE,YAAY,EACnB,KAAK,EAAE,UAAU,EACjB,CAAC,EAAE,QAAQ,EACX,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,YAAY,GACrB,MAAM,CAgBR;AAED,yDAAyD;AACzD,wBAAgB,MAAM,CACpB,KAAK,EAAE,YAAY,EACnB,KAAK,EAAE,UAAU,EACjB,CAAC,EAAE,QAAQ,EACX,EAAE,EAAE,MAAM,EACV,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,YAAY,GACrB,UAAU,GAAG,IAAI,CAQnB"}
package/dist/pick.js ADDED
@@ -0,0 +1,125 @@
1
+ import { pillRect } from './draw/collapsed.js';
2
+ import { isLoop } from './draw/edges.js';
3
+ import { loopCenterY, loopRadius } from './draw/link.js';
4
+ import { NODE_MIN_R } from './draw/view.js';
5
+ import { distToQuadSq, distToSegmentSq } from './math.js';
6
+ /** Extra reach (px) around node discs. */
7
+ export const NODE_PICK_TOLERANCE = 3;
8
+ /** Extra reach (px) beyond half an edge's width. */
9
+ export const EDGE_PICK_TOLERANCE = 4;
10
+ const candidates = [];
11
+ const rect = new Float64Array(4);
12
+ export function pickNode(frame, cache, v, sx, sy) {
13
+ if (cache.nodeCount === 0)
14
+ return -1;
15
+ const { k } = v;
16
+ const wx = (sx - v.ox) / k;
17
+ const wy = (sy - v.oy) / k;
18
+ const grid = cache.nodeGrid();
19
+ const reach = Math.max(grid.maxR, NODE_MIN_R / k) + NODE_PICK_TOLERANCE / k;
20
+ grid.query(wx - reach, wy - reach, wx + reach, wy + reach, candidates);
21
+ let best = -1;
22
+ let bestInside = false;
23
+ let bestZ = Number.NEGATIVE_INFINITY;
24
+ let bestD = Number.POSITIVE_INFINITY;
25
+ for (const i of candidates) {
26
+ const n = frame.nodes[i];
27
+ const r = Math.max(n.r, NODE_MIN_R / k);
28
+ const d = Math.hypot(n.x - wx, n.y - wy);
29
+ if (d > r + NODE_PICK_TOLERANCE / k)
30
+ continue;
31
+ const inside = d <= r;
32
+ const better = best < 0 ||
33
+ (inside && !bestInside) ||
34
+ (inside === bestInside &&
35
+ (n.z > bestZ || (n.z === bestZ && (inside ? i > best : d < bestD))));
36
+ if (better) {
37
+ best = i;
38
+ bestInside = inside;
39
+ bestZ = n.z;
40
+ bestD = d;
41
+ }
42
+ }
43
+ return best;
44
+ }
45
+ export function pickEdge(frame, cache, v, sx, sy) {
46
+ const { k } = v;
47
+ const wx = (sx - v.ox) / k;
48
+ const wy = (sy - v.oy) / k;
49
+ let best = -1;
50
+ let bestZ = Number.NEGATIVE_INFINITY;
51
+ let bestD = Number.POSITIVE_INFINITY;
52
+ for (const b of cache.edgeBuckets) {
53
+ const tol = (b.width / 2 + EDGE_PICK_TOLERANCE) / k;
54
+ const tol2 = tol * tol;
55
+ for (const i of b.members) {
56
+ const e = frame.edges[i];
57
+ let d2;
58
+ if (isLoop(e.x1, e.y1, e.x2, e.y2)) {
59
+ const r = Math.max(e.r1 * k, NODE_MIN_R);
60
+ const rho = loopRadius(r, e.curvature) / k;
61
+ const cy = loopCenterY(e.y1 * k, r, rho * k) / k;
62
+ const d = Math.abs(Math.hypot(wx - e.x1, wy - cy) - rho);
63
+ d2 = d * d;
64
+ }
65
+ else if (e.curvature === 0) {
66
+ if (wx < Math.min(e.x1, e.x2) - tol ||
67
+ wx > Math.max(e.x1, e.x2) + tol ||
68
+ wy < Math.min(e.y1, e.y2) - tol ||
69
+ wy > Math.max(e.y1, e.y2) + tol) {
70
+ continue;
71
+ }
72
+ d2 = distToSegmentSq(wx, wy, e.x1, e.y1, e.x2, e.y2);
73
+ }
74
+ else {
75
+ const cx = (e.x1 + e.x2) / 2 - (e.y2 - e.y1) * e.curvature;
76
+ const cy = (e.y1 + e.y2) / 2 + (e.x2 - e.x1) * e.curvature;
77
+ if (wx < Math.min(e.x1, e.x2, cx) - tol ||
78
+ wx > Math.max(e.x1, e.x2, cx) + tol ||
79
+ wy < Math.min(e.y1, e.y2, cy) - tol ||
80
+ wy > Math.max(e.y1, e.y2, cy) + tol) {
81
+ continue;
82
+ }
83
+ d2 = distToQuadSq(wx, wy, e.x1, e.y1, cx, cy, e.x2, e.y2);
84
+ }
85
+ if (d2 > tol2)
86
+ continue;
87
+ if (b.z > bestZ || (b.z === bestZ && d2 < bestD)) {
88
+ best = i;
89
+ bestZ = b.z;
90
+ bestD = d2;
91
+ }
92
+ }
93
+ }
94
+ return best;
95
+ }
96
+ export function pickCollapsed(frame, cache, v, sx, sy, fonts, measurer) {
97
+ const groups = frame.collapsed;
98
+ for (let i = groups.length - 1; i >= 0; i--) {
99
+ const g = groups[i];
100
+ if (!(g.count > 0) || !Number.isFinite(g.x + g.y) || !cache.pillPickable(i))
101
+ continue;
102
+ pillRect(g, v, fonts, measurer, rect);
103
+ if (sx >= rect[0] &&
104
+ sx <= rect[0] + rect[2] &&
105
+ sy >= rect[1] &&
106
+ sy <= rect[1] + rect[3]) {
107
+ return i;
108
+ }
109
+ }
110
+ return -1;
111
+ }
112
+ /** Topmost element at screen point (sx, sy), or null. */
113
+ export function pickAt(frame, cache, v, sx, sy, fonts, measurer) {
114
+ const node = pickNode(frame, cache, v, sx, sy);
115
+ if (node >= 0)
116
+ return { type: 'node', index: node };
117
+ const edge = pickEdge(frame, cache, v, sx, sy);
118
+ if (edge >= 0)
119
+ return { type: 'edge', index: edge };
120
+ const group = pickCollapsed(frame, cache, v, sx, sy, fonts, measurer);
121
+ if (group >= 0)
122
+ return { type: 'collapsed', index: group };
123
+ return null;
124
+ }
125
+ //# sourceMappingURL=pick.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pick.js","sourceRoot":"","sources":["../src/pick.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAG5C,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAG1D,0CAA0C;AAC1C,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC;AACrC,oDAAoD;AACpD,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC;AASrC,MAAM,UAAU,GAAa,EAAE,CAAC;AAChC,MAAM,IAAI,GAAG,IAAI,YAAY,CAAC,CAAC,CAAC,CAAC;AAEjC,MAAM,UAAU,QAAQ,CACtB,KAAmB,EACnB,KAAiB,EACjB,CAAW,EACX,EAAU,EACV,EAAU;IAEV,IAAI,KAAK,CAAC,SAAS,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC,CAAC;IACrC,MAAM,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC;IAChB,MAAM,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;IAC3B,MAAM,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;IAC3B,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC;IAC9B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,UAAU,GAAG,CAAC,CAAC,GAAG,mBAAmB,GAAG,CAAC,CAAC;IAC5E,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,KAAK,EAAE,EAAE,GAAG,KAAK,EAAE,EAAE,GAAG,KAAK,EAAE,EAAE,GAAG,KAAK,EAAE,UAAU,CAAC,CAAC;IACvE,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC;IACd,IAAI,UAAU,GAAG,KAAK,CAAC;IACvB,IAAI,KAAK,GAAG,MAAM,CAAC,iBAAiB,CAAC;IACrC,IAAI,KAAK,GAAG,MAAM,CAAC,iBAAiB,CAAC;IACrC,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;QAC3B,MAAM,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC;QAC1B,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,UAAU,GAAG,CAAC,CAAC,CAAC;QACxC,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;QACzC,IAAI,CAAC,GAAG,CAAC,GAAG,mBAAmB,GAAG,CAAC;YAAE,SAAS;QAC9C,MAAM,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC;QACtB,MAAM,MAAM,GACV,IAAI,GAAG,CAAC;YACR,CAAC,MAAM,IAAI,CAAC,UAAU,CAAC;YACvB,CAAC,MAAM,KAAK,UAAU;gBACpB,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,KAAK,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACzE,IAAI,MAAM,EAAE,CAAC;YACX,IAAI,GAAG,CAAC,CAAC;YACT,UAAU,GAAG,MAAM,CAAC;YACpB,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC;YACZ,KAAK,GAAG,CAAC,CAAC;QACZ,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,QAAQ,CACtB,KAAmB,EACnB,KAAiB,EACjB,CAAW,EACX,EAAU,EACV,EAAU;IAEV,MAAM,EAAE,CAAC,EAAE,GAAG,CAAC,CAAC;IAChB,MAAM,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;IAC3B,MAAM,EAAE,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;IAC3B,IAAI,IAAI,GAAG,CAAC,CAAC,CAAC;IACd,IAAI,KAAK,GAAG,MAAM,CAAC,iBAAiB,CAAC;IACrC,IAAI,KAAK,GAAG,MAAM,CAAC,iBAAiB,CAAC;IACrC,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC;QAClC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,GAAG,mBAAmB,CAAC,GAAG,CAAC,CAAC;QACpD,MAAM,IAAI,GAAG,GAAG,GAAG,GAAG,CAAC;QACvB,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC;YAC1B,MAAM,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC;YAC1B,IAAI,EAAU,CAAC;YACf,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;gBACnC,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,UAAU,CAAC,CAAC;gBACzC,MAAM,GAAG,GAAG,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;gBAC3C,MAAM,EAAE,GAAG,WAAW,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;gBACjD,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC;gBACzD,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC;YACb,CAAC;iBAAM,IAAI,CAAC,CAAC,SAAS,KAAK,CAAC,EAAE,CAAC;gBAC7B,IACE,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,GAAG,GAAG;oBAC/B,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,GAAG,GAAG;oBAC/B,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,GAAG,GAAG;oBAC/B,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,GAAG,GAAG,EAC/B,CAAC;oBACD,SAAS;gBACX,CAAC;gBACD,EAAE,GAAG,eAAe,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;YACvD,CAAC;iBAAM,CAAC;gBACN,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC;gBAC3D,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC;gBAC3D,IACE,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,GAAG;oBACnC,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,GAAG;oBACnC,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,GAAG;oBACnC,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,GAAG,GAAG,EACnC,CAAC;oBACD,SAAS;gBACX,CAAC;gBACD,EAAE,GAAG,YAAY,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;YAC5D,CAAC;YACD,IAAI,EAAE,GAAG,IAAI;gBAAE,SAAS;YACxB,IAAI,CAAC,CAAC,CAAC,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,KAAK,IAAI,EAAE,GAAG,KAAK,CAAC,EAAE,CAAC;gBACjD,IAAI,GAAG,CAAC,CAAC;gBACT,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC;gBACZ,KAAK,GAAG,EAAE,CAAC;YACb,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,aAAa,CAC3B,KAAmB,EACnB,KAAiB,EACjB,CAAW,EACX,EAAU,EACV,EAAU,EACV,KAAY,EACZ,QAAsB;IAEtB,MAAM,MAAM,GAAG,KAAK,CAAC,SAAS,CAAC;IAC/B,KAAK,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5C,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAE,CAAC;QACrB,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC;YAAE,SAAS;QACtF,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,IAAI,CAAC,CAAC;QACtC,IACE,EAAE,IAAI,IAAI,CAAC,CAAC,CAAE;YACd,EAAE,IAAI,IAAI,CAAC,CAAC,CAAE,GAAG,IAAI,CAAC,CAAC,CAAE;YACzB,EAAE,IAAI,IAAI,CAAC,CAAC,CAAE;YACd,EAAE,IAAI,IAAI,CAAC,CAAC,CAAE,GAAG,IAAI,CAAC,CAAC,CAAE,EACzB,CAAC;YACD,OAAO,CAAC,CAAC;QACX,CAAC;IACH,CAAC;IACD,OAAO,CAAC,CAAC,CAAC;AACZ,CAAC;AAED,yDAAyD;AACzD,MAAM,UAAU,MAAM,CACpB,KAAmB,EACnB,KAAiB,EACjB,CAAW,EACX,EAAU,EACV,EAAU,EACV,KAAY,EACZ,QAAsB;IAEtB,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;IAC/C,IAAI,IAAI,IAAI,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IACpD,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;IAC/C,IAAI,IAAI,IAAI,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IACpD,MAAM,KAAK,GAAG,aAAa,CAAC,KAAK,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;IACtE,IAAI,KAAK,IAAI,CAAC;QAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;IAC3D,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,28 @@
1
+ import type { Theme } from '@kgdiff/scene';
2
+ import { type Size } from './camera.js';
3
+ import { type Ctx2D, type SurfaceFactory } from './ctx.js';
4
+ import type { CameraState, Renderer, RendererOptions } from './index.js';
5
+ /** Test seams and platform overrides (not part of the public API). */
6
+ export interface RendererDeps {
7
+ /** Context to draw into instead of `canvas.getContext('2d')` (null = no drawing). */
8
+ readonly context?: Ctx2D | null;
9
+ readonly surfaceFactory?: SurfaceFactory;
10
+ readonly now?: () => number;
11
+ readonly requestFrame?: (cb: (time: number) => void) => number;
12
+ readonly cancelFrame?: (id: number) => void;
13
+ }
14
+ /** What the minimap needs from its renderer beyond the public API. */
15
+ export interface RendererInternals {
16
+ theme(): Theme;
17
+ pixelRatio(): number;
18
+ size(): Size;
19
+ onTheme(listener: (theme: Theme) => void): () => void;
20
+ /** Move the camera on behalf of the user (minimap drags): `camera` reports source 'user'. */
21
+ userSet(state: CameraState): void;
22
+ readonly requestFrame: (cb: (time: number) => void) => number;
23
+ readonly cancelFrame: (id: number) => void;
24
+ }
25
+ export declare const internals: WeakMap<Renderer, RendererInternals>;
26
+ /** Implementation of `createRenderer` with optional test seams. */
27
+ export declare function createRendererImpl(container: HTMLElement, options: RendererOptions, deps?: RendererDeps): Renderer;
28
+ //# sourceMappingURL=renderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../src/renderer.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAgB,KAAK,EAAE,MAAM,eAAe,CAAC;AACzD,OAAO,EAA4C,KAAK,IAAI,EAAE,MAAM,aAAa,CAAC;AAClF,OAAO,EAAE,KAAK,KAAK,EAAqB,KAAK,cAAc,EAAE,MAAM,UAAU,CAAC;AAE9E,OAAO,KAAK,EACV,WAAW,EAEX,QAAQ,EAER,eAAe,EAEhB,MAAM,YAAY,CAAC;AAMpB,sEAAsE;AACtE,MAAM,WAAW,YAAY;IAC3B,qFAAqF;IACrF,QAAQ,CAAC,OAAO,CAAC,EAAE,KAAK,GAAG,IAAI,CAAC;IAChC,QAAQ,CAAC,cAAc,CAAC,EAAE,cAAc,CAAC;IACzC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IAC5B,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,KAAK,MAAM,CAAC;IAC/D,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7C;AAED,sEAAsE;AACtE,MAAM,WAAW,iBAAiB;IAChC,KAAK,IAAI,KAAK,CAAC;IACf,UAAU,IAAI,MAAM,CAAC;IACrB,IAAI,IAAI,IAAI,CAAC;IACb,OAAO,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IACtD,6FAA6F;IAC7F,OAAO,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,CAAC;IAClC,QAAQ,CAAC,YAAY,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,KAAK,MAAM,CAAC;IAC9D,QAAQ,CAAC,WAAW,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;CAC5C;AAED,eAAO,MAAM,SAAS,sCAA6C,CAAC;AA8dpE,mEAAmE;AACnE,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,WAAW,EACtB,OAAO,EAAE,eAAe,EACxB,IAAI,GAAE,YAAiB,GACtB,QAAQ,CAKV"}