@flighthq/shape 0.3.0 → 0.3.1-next.1041.35b950c

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 (38) hide show
  1. package/dist/contract.d.ts +4 -0
  2. package/dist/contract.d.ts.map +1 -1
  3. package/dist/contract.js +4 -0
  4. package/dist/contract.js.map +1 -1
  5. package/dist/enableShapeBoundsGuards.d.ts +4 -0
  6. package/dist/enableShapeBoundsGuards.d.ts.map +1 -0
  7. package/dist/enableShapeBoundsGuards.js +25 -0
  8. package/dist/enableShapeBoundsGuards.js.map +1 -0
  9. package/dist/index.d.ts +1 -1
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +1 -1
  12. package/dist/index.js.map +1 -1
  13. package/dist/registerDefaultShapeBoundsCommands.d.ts +2 -0
  14. package/dist/registerDefaultShapeBoundsCommands.d.ts.map +1 -0
  15. package/dist/registerDefaultShapeBoundsCommands.js +80 -0
  16. package/dist/registerDefaultShapeBoundsCommands.js.map +1 -0
  17. package/dist/shape.d.ts +2 -2
  18. package/dist/shape.d.ts.map +1 -1
  19. package/dist/shape.js +27 -245
  20. package/dist/shape.js.map +1 -1
  21. package/dist/shapeBounds.d.ts +18 -0
  22. package/dist/shapeBounds.d.ts.map +1 -0
  23. package/dist/shapeBounds.js +527 -0
  24. package/dist/shapeBounds.js.map +1 -0
  25. package/dist/shapeBoundsRegistry.d.ts +6 -0
  26. package/dist/shapeBoundsRegistry.d.ts.map +1 -0
  27. package/dist/shapeBoundsRegistry.js +24 -0
  28. package/dist/shapeBoundsRegistry.js.map +1 -0
  29. package/dist/shapeFill.d.ts.map +1 -1
  30. package/dist/shapeFill.js +3 -3
  31. package/dist/shapeFill.js.map +1 -1
  32. package/package.json +9 -7
  33. package/src/enableShapeBoundsGuards.test.ts +64 -0
  34. package/src/morphShape.test.ts +10 -0
  35. package/src/registerDefaultShapeBoundsCommands.test.ts +64 -0
  36. package/src/shape.test.ts +44 -7
  37. package/src/shapeBounds.test.ts +270 -0
  38. package/src/shapeBoundsRegistry.test.ts +76 -0
@@ -1 +1 @@
1
- {"version":3,"file":"shapeFill.js","sourceRoot":"","sources":["../src/shapeFill.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"shapeFill.js","sourceRoot":"","sources":["../src/shapeFill.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flighthq/shape",
3
- "version": "0.3.0",
3
+ "version": "0.3.1-next.1041.35b950c",
4
4
  "author": "Joshua Granick and other contributors",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -38,12 +38,14 @@
38
38
  "clean:dist": "tsx ../../scripts/clean-package-dist.ts"
39
39
  },
40
40
  "dependencies": {
41
- "@flighthq/animation": "0.3.0",
42
- "@flighthq/scene2d": "0.3.0",
43
- "@flighthq/geometry": "0.3.0",
44
- "@flighthq/node": "0.3.0",
45
- "@flighthq/path": "0.3.0",
46
- "@flighthq/types": "0.3.0"
41
+ "@flighthq/animation": "0.3.1-next.1041.35b950c",
42
+ "@flighthq/geometry": "0.3.1-next.1041.35b950c",
43
+ "@flighthq/log": "0.3.1-next.1041.35b950c",
44
+ "@flighthq/math": "0.3.1-next.1041.35b950c",
45
+ "@flighthq/node": "0.3.1-next.1041.35b950c",
46
+ "@flighthq/path": "0.3.1-next.1041.35b950c",
47
+ "@flighthq/scene2d": "0.3.1-next.1041.35b950c",
48
+ "@flighthq/types": "0.3.1-next.1041.35b950c"
47
49
  },
48
50
  "devDependencies": {
49
51
  "typescript": "^5.3.0"
@@ -0,0 +1,64 @@
1
+ import { createRectangle } from '@flighthq/geometry/contract';
2
+ import { addLogSink, createMemoryLogSink, getMemoryLogSinkEntries, removeLogSink } from '@flighthq/log/contract';
3
+ import type { LogEntry } from '@flighthq/types/contract';
4
+
5
+ import {
6
+ areShapeBoundsGuardsEnabled,
7
+ disableShapeBoundsGuards,
8
+ enableShapeBoundsGuards,
9
+ } from './enableShapeBoundsGuards';
10
+ import { createShape } from './shape';
11
+ import { computeShapeBoundsRectangle } from './shapeBounds';
12
+
13
+ afterEach(() => {
14
+ disableShapeBoundsGuards();
15
+ });
16
+
17
+ describe('areShapeBoundsGuardsEnabled', () => {
18
+ it('reports whether the module guard is installed', () => {
19
+ expect(areShapeBoundsGuardsEnabled()).toBe(false);
20
+ enableShapeBoundsGuards();
21
+ expect(areShapeBoundsGuardsEnabled()).toBe(true);
22
+ });
23
+ });
24
+
25
+ describe('disableShapeBoundsGuards', () => {
26
+ it('restores the silent production default', () => {
27
+ enableShapeBoundsGuards();
28
+ disableShapeBoundsGuards();
29
+
30
+ expect(captureLog(() => computeMissingBounds())).toHaveLength(0);
31
+ });
32
+ });
33
+
34
+ describe('enableShapeBoundsGuards', () => {
35
+ it('names a missing key once and points to the plain explanation query', () => {
36
+ enableShapeBoundsGuards();
37
+
38
+ const entries = captureLog(() => {
39
+ computeMissingBounds();
40
+ computeMissingBounds();
41
+ });
42
+
43
+ expect(entries).toHaveLength(1);
44
+ expect(entries[0].channel).toBe('shape');
45
+ expect(entries[0].data).toMatchObject({ missingCommandKey: '__test.guard-miss__', mode: 'ink' });
46
+ expect(String((entries[0].data as Record<string, unknown>).message)).toContain('explainShapeBounds');
47
+ });
48
+ });
49
+
50
+ function captureLog(run: () => void): readonly LogEntry[] {
51
+ const sink = createMemoryLogSink(8);
52
+ addLogSink(sink.sink);
53
+ try {
54
+ run();
55
+ return getMemoryLogSinkEntries(sink);
56
+ } finally {
57
+ removeLogSink(sink.sink);
58
+ }
59
+ }
60
+
61
+ function computeMissingBounds(): void {
62
+ const shape = createShape({ data: { commands: ['__test.guard-miss__', 0] } });
63
+ computeShapeBoundsRectangle(createRectangle(), shape);
64
+ }
@@ -18,8 +18,18 @@ import {
18
18
  setMorphShapeProgress,
19
19
  } from './morphShape';
20
20
  import { getShapeBounds } from './shape';
21
+ import { defaultShapeBoundsDrawPath } from './shapeBounds';
22
+ import { registerShapeBoundsCommand } from './shapeBoundsRegistry';
21
23
  import { appendShapeBeginFill, appendShapeEndFill } from './shapeCommands';
22
24
 
25
+ beforeAll(() => {
26
+ registerShapeBoundsCommand({
27
+ fillBounds: defaultShapeBoundsDrawPath,
28
+ key: 'drawPath',
29
+ strokeBounds: defaultShapeBoundsDrawPath,
30
+ });
31
+ });
32
+
23
33
  describe('appendMorphShapePath', () => {
24
34
  it('inserts the live path between ordinary Shape styling commands', () => {
25
35
  const shape = createMorphShape(createTestMorph());
@@ -0,0 +1,64 @@
1
+ import { registerDefaultShapeBoundsCommands } from './registerDefaultShapeBoundsCommands';
2
+ import {
3
+ defaultShapeBoundsCubicCurveTo,
4
+ defaultShapeBoundsCurveTo,
5
+ defaultShapeBoundsDrawCircle,
6
+ defaultShapeBoundsDrawEllipse,
7
+ defaultShapeBoundsDrawPath,
8
+ defaultShapeBoundsDrawRectangle,
9
+ defaultShapeBoundsFlush,
10
+ defaultShapeBoundsLineStyle,
11
+ defaultShapeBoundsLineTo,
12
+ defaultShapeBoundsMoveTo,
13
+ } from './shapeBounds';
14
+ import { getShapeBoundsCommand, getShapeBoundsCommandRegistryRevision } from './shapeBoundsRegistry';
15
+
16
+ // ★ THIS FILE RUNS ISOLATED — scripts/registryIsolatedTests.ts lists it with reason
17
+ // `process-global-registry`, and that routing is LOAD-BEARING. Do not demote it to the shared tier.
18
+ // What it guards: importing @flighthq/shape registers NOTHING. That side-effect-free-import property is
19
+ // the entire reason `registerDefaultShapeBoundsCommands` exists as an explicit entry point instead of a
20
+ // module-scope call, so the pre-install assertion below is the only thing holding that guarantee.
21
+ // Why isolation rather than a beforeEach that clears the registry: the registry is process-global, so
22
+ // "nothing is registered" is a claim about a PROCESS and can only be asserted in one nobody else has
23
+ // touched. Clearing first would change the claim to "nothing is registered after I cleared it" — which
24
+ // passes identically in a world where importing this package registered forty commands, and so retires
25
+ // the guarantee while turning the suite green. Five sibling files register deliberately and assert
26
+ // nothing about emptiness; they are correct in the shared tier and only this file needs its own process.
27
+ // The list is keyed by MECHANISM (needs a private module registry), not by cause, so this entry is an
28
+ // ordinary member whose reason is not mocking — not an escape from a rule about mocking.
29
+ describe('registerDefaultShapeBoundsCommands', () => {
30
+ it('does nothing on import, then explicitly installs every standard command idempotently', () => {
31
+ const bindings = [
32
+ ['beginTextureFill', defaultShapeBoundsFlush, defaultShapeBoundsFlush],
33
+ ['beginFill', defaultShapeBoundsFlush, defaultShapeBoundsFlush],
34
+ ['beginGradientFill', defaultShapeBoundsFlush, defaultShapeBoundsFlush],
35
+ ['cubicCurveTo', defaultShapeBoundsCubicCurveTo, defaultShapeBoundsCubicCurveTo],
36
+ ['curveTo', defaultShapeBoundsCurveTo, defaultShapeBoundsCurveTo],
37
+ ['drawCircle', defaultShapeBoundsDrawCircle, defaultShapeBoundsDrawCircle],
38
+ ['drawEllipse', defaultShapeBoundsDrawEllipse, defaultShapeBoundsDrawEllipse],
39
+ ['drawPath', defaultShapeBoundsDrawPath, defaultShapeBoundsDrawPath],
40
+ ['drawRectangle', defaultShapeBoundsDrawRectangle, defaultShapeBoundsDrawRectangle],
41
+ ['drawRoundRectangle', defaultShapeBoundsDrawRectangle, defaultShapeBoundsDrawRectangle],
42
+ ['endFill', defaultShapeBoundsFlush, defaultShapeBoundsFlush],
43
+ ['lineTextureStyle', null, null],
44
+ ['lineGradientStyle', null, null],
45
+ ['lineStyle', defaultShapeBoundsFlush, defaultShapeBoundsLineStyle],
46
+ ['lineTo', defaultShapeBoundsLineTo, defaultShapeBoundsLineTo],
47
+ ['moveTo', defaultShapeBoundsMoveTo, defaultShapeBoundsMoveTo],
48
+ ] as const;
49
+ // Importing the module must be side-effect-free: the explicit installer is the only door through
50
+ // which standard bounds commands enter the registry.
51
+ for (const [key] of bindings) expect(getShapeBoundsCommand(key)).toBeNull();
52
+
53
+ registerDefaultShapeBoundsCommands();
54
+
55
+ for (const [key, fillBounds, strokeBounds] of bindings) {
56
+ expect(getShapeBoundsCommand(key)).toMatchObject({ fillBounds, key, strokeBounds });
57
+ }
58
+ const revision = getShapeBoundsCommandRegistryRevision();
59
+
60
+ registerDefaultShapeBoundsCommands();
61
+
62
+ expect(getShapeBoundsCommandRegistryRevision()).toBe(revision);
63
+ });
64
+ });
package/src/shape.test.ts CHANGED
@@ -10,6 +10,7 @@ import { ShapeKind } from '@flighthq/types/contract';
10
10
 
11
11
  import { createMorphShape, setMorphShapeProgress } from './morphShape';
12
12
  import { appendMorphShapeBeginFill } from './morphShapePaint';
13
+ import { registerDefaultShapeBoundsCommands } from './registerDefaultShapeBoundsCommands';
13
14
  import {
14
15
  clearShapeCommands,
15
16
  computeShapeLocalBoundsRectangle,
@@ -27,9 +28,16 @@ import {
27
28
  appendShapeCubicCurveTo,
28
29
  appendShapeCurveTo,
29
30
  appendShapeEllipse,
31
+ appendShapeLineStyle,
32
+ appendShapeLineTo,
30
33
  appendShapeMoveTo,
34
+ appendShapeRectangle,
31
35
  } from './shapeCommands';
32
36
 
37
+ beforeAll(() => {
38
+ registerDefaultShapeBoundsCommands();
39
+ });
40
+
33
41
  describe('clearShapeCommands', () => {
34
42
  it('empties the commands array and bumps the content revision', () => {
35
43
  const shape = createShape();
@@ -83,21 +91,16 @@ describe('computeShapeLocalBoundsRectangle', () => {
83
91
  // c = -0 + 0 = 0
84
92
  // One root at t = 0, excluded (not in open interval). Other: t = -b/a = -300/-450 = 2/3.
85
93
  // y at t=2/3: u=1/3, u^3*0 + 3*(1/9)*(2/3)*0 + 3*(1/3)*(4/9)*150 + (8/27)*0 = 200/3 ~ 66.667.
86
- // expandCubicAxis for Y-axis extrema calls expand(yAtT, xAtT) which is swapped vs expand(x,y).
87
- // yAtT = cubicPoint(2/3, 0, 0, 150, 0) = 200/3. xAtT = cubicPoint(2/3, 0, 0, 200, 200) ~ 148.15.
88
- // So expand(200/3, 148.15), treating 200/3 as x-extent and 148.15 as y-extent.
89
- // Final bounds include endpoints (0,0) and (200,0), plus the extremum expansion.
94
+ // Final bounds include endpoints (0,0) and (200,0), plus the exact Y extremum at 200/3.
90
95
  const shape = createShape();
91
96
  appendShapeMoveTo(shape, 0, 0);
92
97
  appendShapeCubicCurveTo(shape, 0, 0, 200, 150, 200, 0);
93
98
  const out = createRectangle();
94
99
  computeShapeLocalBoundsRectangle(out, shape as any);
95
- // Bounds encompass at least the two endpoints.
96
100
  expect(out.x).toBe(0);
97
101
  expect(out.y).toBe(0);
98
102
  expect(out.width).toBe(200);
99
- // The curve bulges above y=0; the extremum expansion contributes a y-extent of ~148.15.
100
- expect(out.height).toBeGreaterThan(100);
103
+ expect(out.height).toBeCloseTo(200 / 3, 5);
101
104
  });
102
105
 
103
106
  it('computes bounds from a cubic bezier with a simple horizontal S-curve', () => {
@@ -139,6 +142,30 @@ describe('computeShapeLocalBoundsRectangle', () => {
139
142
  expect(out.height).toBe(60);
140
143
  });
141
144
 
145
+ it('includes a miter point beyond the half-width endpoint envelope', () => {
146
+ const shape = createShape();
147
+ appendShapeLineStyle(shape, 30, 0xffffff, 1, false, 'normal', 'none', 'miter', 6);
148
+ appendShapeMoveTo(shape, -110, -110);
149
+ appendShapeLineTo(shape, 0, 0);
150
+ appendShapeLineTo(shape, 110, -110);
151
+ const out = createRectangle();
152
+
153
+ computeShapeLocalBoundsRectangle(out, shape as any);
154
+
155
+ expect(out.y + out.height).toBeGreaterThan(18);
156
+ });
157
+
158
+ it('bounds a closed rectangle stroke without applying the miter limit to every axis', () => {
159
+ const shape = createShape();
160
+ appendShapeLineStyle(shape, 30, 0xffffff, 1, false, 'normal', 'none', 'miter', 6);
161
+ appendShapeRectangle(shape, 0, 0, 100, 100);
162
+ const out = createRectangle();
163
+
164
+ computeShapeLocalBoundsRectangle(out, shape as any);
165
+
166
+ expect(out).toMatchObject({ height: 130, width: 130, x: -15, y: -15 });
167
+ });
168
+
142
169
  it('computes bounds from a quadratic bezier with an interior extremum', () => {
143
170
  // Quadratic from (0,0) to (100,0) with control point at (50,100).
144
171
  // The extremum in Y is at t = (p0 - p1) / (p0 - 2*p1 + p2) = (0 - 100) / (0 - 200 + 0) = 0.5.
@@ -291,6 +318,16 @@ describe('getShapeBounds', () => {
291
318
  expect(out.width).toBe(0);
292
319
  expect(out.height).toBe(0);
293
320
  });
321
+
322
+ it('rejects a partial result when any command has no bounds contribution', () => {
323
+ const shape = createShape({
324
+ data: { commands: ['drawRectangle', 4, 5, 10, 200, 80, '__test.incomplete-public-bounds__', 0] },
325
+ });
326
+ const out = createRectangle(1, 2, 3, 4);
327
+
328
+ expect(getShapeBounds(out, shape)).toBe(false);
329
+ expect(out).toMatchObject({ height: 0, width: 0, x: 0, y: 0 });
330
+ });
294
331
  });
295
332
 
296
333
  describe('getShapeCommandCount', () => {
@@ -0,0 +1,270 @@
1
+ import { createRectangle } from '@flighthq/geometry/contract';
2
+ import { PathCommand } from '@flighthq/types/contract';
3
+
4
+ import { registerDefaultShapeBoundsCommands } from './registerDefaultShapeBoundsCommands';
5
+ import { createShape } from './shape';
6
+ import {
7
+ computeShapeBoundsRectangle,
8
+ defaultShapeBoundsCubicCurveTo,
9
+ defaultShapeBoundsCurveTo,
10
+ defaultShapeBoundsDrawCircle,
11
+ defaultShapeBoundsDrawEllipse,
12
+ defaultShapeBoundsDrawPath,
13
+ defaultShapeBoundsDrawRectangle,
14
+ defaultShapeBoundsExpandPointPairs,
15
+ defaultShapeBoundsFlush,
16
+ defaultShapeBoundsLineStyle,
17
+ defaultShapeBoundsLineTo,
18
+ defaultShapeBoundsMoveTo,
19
+ explainShapeBounds,
20
+ normalizeShapeStrokeMiterLimit,
21
+ normalizeShapeStrokeWidth,
22
+ setShapeBoundsGuard,
23
+ } from './shapeBounds';
24
+ import { registerShapeBoundsCommand } from './shapeBoundsRegistry';
25
+ import {
26
+ appendShapeBeginFill,
27
+ appendShapeCubicCurveTo,
28
+ appendShapeLineStyle,
29
+ appendShapeLineTo,
30
+ appendShapeMoveTo,
31
+ appendShapePath,
32
+ appendShapeRectangle,
33
+ } from './shapeCommands';
34
+
35
+ beforeAll(() => {
36
+ registerDefaultShapeBoundsCommands();
37
+ });
38
+
39
+ describe('computeShapeBoundsRectangle', () => {
40
+ it('returns false for an unknown command without inventing geometry', () => {
41
+ const shape = createShape({ data: { commands: ['__test.missing__', 2, 1, 2] } });
42
+ const out = createRectangle(10, 20, 30, 40);
43
+
44
+ expect(computeShapeBoundsRectangle(out, shape)).toBe(false);
45
+ expect(out).toMatchObject({ height: 0, width: 0, x: 0, y: 0 });
46
+ });
47
+
48
+ it('keeps known contributions while reporting an incomplete stream', () => {
49
+ const shape = createShape();
50
+ appendShapeRectangle(shape, 10, 20, 30, 40);
51
+ shape.data.commands.push('__test.missing-after-known__', 0);
52
+ const out = createRectangle();
53
+
54
+ expect(computeShapeBoundsRectangle(out, shape)).toBe(false);
55
+ expect(out).toMatchObject({ height: 40, width: 30, x: 10, y: 20 });
56
+ });
57
+
58
+ it('selects fill-only or ink-inclusive contributions from the same command binding', () => {
59
+ const shape = createShape();
60
+ appendShapeLineStyle(shape, 10);
61
+ appendShapeRectangle(shape, 0, 0, 100, 50);
62
+ const fill = createRectangle();
63
+ const ink = createRectangle();
64
+
65
+ expect(computeShapeBoundsRectangle(fill, shape, 'fill')).toBe(true);
66
+ expect(computeShapeBoundsRectangle(ink, shape, 'ink')).toBe(true);
67
+
68
+ expect(fill).toMatchObject({ height: 50, width: 100, x: 0, y: 0 });
69
+ expect(ink).toMatchObject({ height: 60, width: 110, x: -5, y: -5 });
70
+ });
71
+
72
+ it('resolves a miter from adjacent segment summaries', () => {
73
+ const shape = createShape();
74
+ appendShapeLineStyle(shape, 30, 0, 1, false, 'normal', 'none', 'miter', 6);
75
+ appendShapeMoveTo(shape, -110, -110);
76
+ appendShapeLineTo(shape, 0, 0);
77
+ appendShapeLineTo(shape, 110, -110);
78
+ const out = createRectangle();
79
+
80
+ computeShapeBoundsRectangle(out, shape);
81
+
82
+ expect(out.y + out.height).toBeGreaterThan(18);
83
+ });
84
+
85
+ it('falls back to the half-width bevel envelope beyond the authored miter limit', () => {
86
+ const shape = createShape();
87
+ appendShapeLineStyle(shape, 30, 0, 1, false, 'normal', 'none', 'miter', 1);
88
+ appendShapeMoveTo(shape, -110, -110);
89
+ appendShapeLineTo(shape, 0, 0);
90
+ appendShapeLineTo(shape, 110, -110);
91
+ const out = createRectangle();
92
+
93
+ computeShapeBoundsRectangle(out, shape);
94
+
95
+ expect(out.y + out.height).toBeCloseTo(15);
96
+ });
97
+
98
+ it('includes square cap extension for an open stroke', () => {
99
+ const shape = createShape();
100
+ appendShapeLineStyle(shape, 10, 0, 1, false, 'normal', 'square');
101
+ appendShapeMoveTo(shape, 0, 0);
102
+ appendShapeLineTo(shape, 100, 0);
103
+ const out = createRectangle();
104
+
105
+ computeShapeBoundsRectangle(out, shape);
106
+
107
+ expect(out).toMatchObject({ height: 10, width: 110, x: -5, y: -5 });
108
+ });
109
+
110
+ it('tracks CLOSE as the final segment and last-to-first join', () => {
111
+ const shape = createShape();
112
+ appendShapeLineStyle(shape, 10, 0, 1, false, 'normal', 'none', 'miter', 4);
113
+ appendShapePath(
114
+ shape,
115
+ [PathCommand.MOVE_TO, PathCommand.LINE_TO, PathCommand.LINE_TO, PathCommand.CLOSE],
116
+ [0, 0, 100, 0, 50, 100],
117
+ );
118
+ const out = createRectangle();
119
+
120
+ computeShapeBoundsRectangle(out, shape);
121
+
122
+ expect(out.x).toBeLessThan(0);
123
+ expect(out.y + out.height).toBeGreaterThan(100);
124
+ });
125
+
126
+ it('uses the correct axes for cubic extrema', () => {
127
+ const shape = createShape();
128
+ appendShapeMoveTo(shape, 0, 0);
129
+ appendShapeCubicCurveTo(shape, 0, 0, 200, 150, 200, 0);
130
+ const out = createRectangle();
131
+
132
+ computeShapeBoundsRectangle(out, shape, 'fill');
133
+
134
+ expect(out).toMatchObject({ width: 200, x: 0, y: 0 });
135
+ expect(out.height).toBeCloseTo(200 / 3, 5);
136
+ });
137
+
138
+ it('passes only the registered command arguments through the reusable cursor', () => {
139
+ const key = '__test.cursor__';
140
+ const seen: unknown[] = [];
141
+ registerShapeBoundsCommand({
142
+ fillBounds: (context, command) => {
143
+ seen.push(command.length, command.getArgument(-1), command.getArgument(0), command.getArgument(2));
144
+ context.expandPoint(command.getArgument(0) as number, command.getArgument(1) as number);
145
+ },
146
+ key: key as never,
147
+ strokeBounds: null,
148
+ });
149
+ const shape = createShape({ data: { commands: [key, 2, 7, 9, 'drawRectangle', 4, 0, 0, 1, 1] } });
150
+ const out = createRectangle();
151
+
152
+ computeShapeBoundsRectangle(out, shape, 'fill');
153
+
154
+ expect(seen).toEqual([2, undefined, 7, undefined]);
155
+ expect(out).toMatchObject({ height: 9, width: 7, x: 0, y: 0 });
156
+ });
157
+ });
158
+
159
+ describe('defaultShapeBoundsCubicCurveTo', () => {
160
+ it('is available for paired command registration', () => {
161
+ expect(defaultShapeBoundsCubicCurveTo).toBeTypeOf('function');
162
+ });
163
+ });
164
+
165
+ describe('defaultShapeBoundsCurveTo', () => {
166
+ it('is available for paired command registration', () => {
167
+ expect(defaultShapeBoundsCurveTo).toBeTypeOf('function');
168
+ });
169
+ });
170
+
171
+ describe('defaultShapeBoundsDrawCircle', () => {
172
+ it('is available for paired command registration', () => {
173
+ expect(defaultShapeBoundsDrawCircle).toBeTypeOf('function');
174
+ });
175
+ });
176
+
177
+ describe('defaultShapeBoundsDrawEllipse', () => {
178
+ it('is available for paired command registration', () => {
179
+ expect(defaultShapeBoundsDrawEllipse).toBeTypeOf('function');
180
+ });
181
+ });
182
+
183
+ describe('defaultShapeBoundsDrawPath', () => {
184
+ it('is available for paired command registration', () => {
185
+ expect(defaultShapeBoundsDrawPath).toBeTypeOf('function');
186
+ });
187
+ });
188
+
189
+ describe('defaultShapeBoundsDrawRectangle', () => {
190
+ it('is available for paired command registration', () => {
191
+ expect(defaultShapeBoundsDrawRectangle).toBeTypeOf('function');
192
+ });
193
+ });
194
+
195
+ describe('defaultShapeBoundsExpandPointPairs', () => {
196
+ it('is available for paired command registration', () => {
197
+ expect(defaultShapeBoundsExpandPointPairs).toBeTypeOf('function');
198
+ });
199
+ });
200
+
201
+ describe('defaultShapeBoundsFlush', () => {
202
+ it('is available for paired command registration', () => {
203
+ expect(defaultShapeBoundsFlush).toBeTypeOf('function');
204
+ });
205
+ });
206
+
207
+ describe('defaultShapeBoundsLineStyle', () => {
208
+ it('is available for paired command registration', () => {
209
+ expect(defaultShapeBoundsLineStyle).toBeTypeOf('function');
210
+ });
211
+ });
212
+
213
+ describe('defaultShapeBoundsLineTo', () => {
214
+ it('is available for paired command registration', () => {
215
+ expect(defaultShapeBoundsLineTo).toBeTypeOf('function');
216
+ });
217
+ });
218
+
219
+ describe('defaultShapeBoundsMoveTo', () => {
220
+ it('is available for paired command registration', () => {
221
+ expect(defaultShapeBoundsMoveTo).toBeTypeOf('function');
222
+ });
223
+ });
224
+
225
+ describe('explainShapeBounds', () => {
226
+ it('reports each missing key once without diagnostic prose in the core traversal', () => {
227
+ const shape = createShape({
228
+ data: { commands: ['__test.a__', 0, '__test.b__', 0, '__test.a__', 0] },
229
+ });
230
+
231
+ expect(explainShapeBounds(shape, 'fill')).toEqual({
232
+ complete: false,
233
+ missingCommandKeys: ['__test.a__', '__test.b__'],
234
+ mode: 'fill',
235
+ });
236
+ });
237
+ });
238
+
239
+ describe('normalizeShapeStrokeMiterLimit', () => {
240
+ it('uses Canvas default 10 for nonpositive or nonfinite values', () => {
241
+ expect(normalizeShapeStrokeMiterLimit(0)).toBe(10);
242
+ expect(normalizeShapeStrokeMiterLimit(-2)).toBe(10);
243
+ expect(normalizeShapeStrokeMiterLimit(Infinity)).toBe(10);
244
+ expect(normalizeShapeStrokeMiterLimit(Number.NaN)).toBe(10);
245
+ expect(normalizeShapeStrokeMiterLimit(3)).toBe(3);
246
+ });
247
+ });
248
+
249
+ describe('normalizeShapeStrokeWidth', () => {
250
+ it('preserves zero as stroke-off and uses Canvas default 1 for other invalid values', () => {
251
+ expect(normalizeShapeStrokeWidth(0)).toBe(0);
252
+ expect(normalizeShapeStrokeWidth(-2)).toBe(1);
253
+ expect(normalizeShapeStrokeWidth(Infinity)).toBe(1);
254
+ expect(normalizeShapeStrokeWidth(Number.NaN)).toBe(1);
255
+ expect(normalizeShapeStrokeWidth(3)).toBe(3);
256
+ });
257
+ });
258
+
259
+ describe('setShapeBoundsGuard', () => {
260
+ afterEach(() => setShapeBoundsGuard(null));
261
+
262
+ it('exposes missing commands to a separately installed diagnostic policy', () => {
263
+ const misses: string[] = [];
264
+ setShapeBoundsGuard((_shape, _mode, key) => misses.push(key));
265
+
266
+ computeShapeBoundsRectangle(createRectangle(), createShape({ data: { commands: ['__test.guard-callback__', 0] } }));
267
+
268
+ expect(misses).toEqual(['__test.guard-callback__']);
269
+ });
270
+ });
@@ -0,0 +1,76 @@
1
+ import { getNodeLocalBoundsRectangle } from '@flighthq/node/contract';
2
+
3
+ import { createShape } from './shape';
4
+ import {
5
+ getShapeBoundsCommand,
6
+ getShapeBoundsCommandRegistryRevision,
7
+ registerShapeBoundsCommand,
8
+ unregisterShapeBoundsCommand,
9
+ } from './shapeBoundsRegistry';
10
+
11
+ describe('getShapeBoundsCommand', () => {
12
+ it('distinguishes an absent key from an explicitly geometry-free command', () => {
13
+ const key = '__test.null-bounds__';
14
+ expect(getShapeBoundsCommand(key)).toBeNull();
15
+
16
+ registerShapeBoundsCommand({ fillBounds: null, key: key as never, strokeBounds: null });
17
+
18
+ expect(getShapeBoundsCommand(key)).toMatchObject({ fillBounds: null, key, strokeBounds: null });
19
+ });
20
+ });
21
+
22
+ describe('getShapeBoundsCommandRegistryRevision', () => {
23
+ it('invalidates an already-cached Shape when a missing key becomes bound', () => {
24
+ const key = '__test.late-bounds__';
25
+ const shape = createShape({ data: { commands: [key, 2, 10, 20] } });
26
+ const before = getNodeLocalBoundsRectangle(shape);
27
+ expect(before).toMatchObject({ height: 0, width: 0, x: 0, y: 0 });
28
+
29
+ registerShapeBoundsCommand({
30
+ fillBounds: (context, command) =>
31
+ context.expandPoint(command.getArgument(0) as number, command.getArgument(1) as number),
32
+ key: key as never,
33
+ strokeBounds: null,
34
+ });
35
+
36
+ expect(getNodeLocalBoundsRectangle(shape)).toMatchObject({ height: 0, width: 0, x: 10, y: 20 });
37
+ });
38
+
39
+ it('does not bump when the same key is rebound to the same callbacks', () => {
40
+ const key = '__test.stable-bounds__';
41
+ const fillBounds = vi.fn();
42
+ const command = { fillBounds, key: key as never, strokeBounds: null };
43
+ registerShapeBoundsCommand(command);
44
+ const revision = getShapeBoundsCommandRegistryRevision();
45
+
46
+ registerShapeBoundsCommand(command);
47
+
48
+ expect(getShapeBoundsCommandRegistryRevision()).toBe(revision);
49
+ });
50
+ });
51
+
52
+ describe('registerShapeBoundsCommand', () => {
53
+ it('bumps the revision when the callbacks bound to a key change', () => {
54
+ const key = '__test.replace-bounds__';
55
+ registerShapeBoundsCommand({ fillBounds: vi.fn(), key: key as never, strokeBounds: null });
56
+ const revision = getShapeBoundsCommandRegistryRevision();
57
+
58
+ registerShapeBoundsCommand({ fillBounds: vi.fn(), key: key as never, strokeBounds: null });
59
+
60
+ expect(getShapeBoundsCommandRegistryRevision()).toBe(revision + 1);
61
+ });
62
+ });
63
+
64
+ describe('unregisterShapeBoundsCommand', () => {
65
+ it('bumps only when a binding was removed', () => {
66
+ const key = '__test.unregister-bounds__';
67
+ registerShapeBoundsCommand({ fillBounds: null, key: key as never, strokeBounds: null });
68
+ const revision = getShapeBoundsCommandRegistryRevision();
69
+
70
+ unregisterShapeBoundsCommand(key);
71
+ expect(getShapeBoundsCommandRegistryRevision()).toBe(revision + 1);
72
+
73
+ unregisterShapeBoundsCommand(key);
74
+ expect(getShapeBoundsCommandRegistryRevision()).toBe(revision + 1);
75
+ });
76
+ });