@weasel-js/core 1.0.2 → 1.0.4

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 (51) hide show
  1. package/CHANGELOG.md +208 -0
  2. package/dist/{DrawCommand-DCmiNkBj.d.ts → DrawCommand-BbPrSTra.d.ts} +24 -0
  3. package/dist/{chunk-6SHZHXXR.js → chunk-4Z6J4IVH.js} +43 -27
  4. package/dist/chunk-4Z6J4IVH.js.map +1 -0
  5. package/dist/{chunk-PI56ORHE.js → chunk-AYGSXNY3.js} +540 -263
  6. package/dist/chunk-AYGSXNY3.js.map +1 -0
  7. package/dist/{chunk-UB6A6L77.js → chunk-CSMF654J.js} +3 -3
  8. package/dist/{chunk-UB6A6L77.js.map → chunk-CSMF654J.js.map} +1 -1
  9. package/dist/{chunk-IO5Z75X4.js → chunk-HGF5X6MZ.js} +2 -2
  10. package/dist/chunk-HGF5X6MZ.js.map +1 -0
  11. package/dist/{chunk-W2WB4352.js → chunk-J3YC3GVF.js} +5 -4
  12. package/dist/chunk-J3YC3GVF.js.map +1 -0
  13. package/dist/{chunk-Z3KNFTTS.js → chunk-J7LUY47N.js} +3 -3
  14. package/dist/chunk-J7LUY47N.js.map +1 -0
  15. package/dist/{chunk-775XXAHR.js → chunk-JOSUVS6C.js} +2 -2
  16. package/dist/{chunk-775XXAHR.js.map → chunk-JOSUVS6C.js.map} +1 -1
  17. package/dist/clipboard.d.ts +5 -2
  18. package/dist/clipboard.js +1 -1
  19. package/dist/clone.d.ts +2 -2
  20. package/dist/{geometry-CnISZ11w.d.ts → geometry-5X6TrAkX.d.ts} +1 -1
  21. package/dist/{grid-CBiLBnyc.d.ts → grid-sfilv5HP.d.ts} +7 -2
  22. package/dist/index.d.ts +552 -56
  23. package/dist/index.js +7 -7
  24. package/dist/insert.d.ts +6 -3
  25. package/dist/insert.js +1 -1
  26. package/dist/insert.js.map +1 -1
  27. package/dist/move.d.ts +26 -5
  28. package/dist/move.js +3 -3
  29. package/dist/move.js.map +1 -1
  30. package/dist/{options-DoOvx50U.d.ts → options-CbsIgQci.d.ts} +3 -1
  31. package/dist/patterns-builtin.d.ts +8 -0
  32. package/dist/patterns-builtin.js +1 -1
  33. package/dist/{pointSnapToGrid-Bj4r_lEQ.d.ts → pointSnapToGrid-C3wowsQy.d.ts} +9 -3
  34. package/dist/{registry-BQL4oyTg.d.ts → registry-QRg8KiNM.d.ts} +91 -7
  35. package/dist/renderer.d.ts +54 -17
  36. package/dist/renderer.js +7 -7
  37. package/dist/resize.d.ts +12 -5
  38. package/dist/resize.js +2 -2
  39. package/dist/routing.d.ts +7 -7
  40. package/dist/routing.js +1 -1
  41. package/dist/{types-Dtxe7jTS.d.ts → types-BHK2dkMu.d.ts} +23 -0
  42. package/dist/{types-Ct4n0Z38.d.ts → types-ByZxoD6P.d.ts} +1 -1
  43. package/dist/{types-Ch0Goo-j.d.ts → types-DpQ0cWYC.d.ts} +20 -0
  44. package/dist/{types-Kh_osAq9.d.ts → types-vqxpCFVp.d.ts} +31 -0
  45. package/dist/{viewToMat3-BvaWCN99.d.ts → viewToMat3-CQW_YqDw.d.ts} +1 -1
  46. package/package.json +6 -6
  47. package/dist/chunk-6SHZHXXR.js.map +0 -1
  48. package/dist/chunk-IO5Z75X4.js.map +0 -1
  49. package/dist/chunk-PI56ORHE.js.map +0 -1
  50. package/dist/chunk-W2WB4352.js.map +0 -1
  51. package/dist/chunk-Z3KNFTTS.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,213 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.0.4
4
+
5
+ ### Patch Changes
6
+
7
+ - da7c150: The solid batch stops re-sending index data a ring slot already holds, and
8
+ `u_color` / `u_alpha` join the per-frame uniform cache.
9
+
10
+ A run of rects has indices that are a pure function of the rect count, so a
11
+ slot coming round to the same count already holds the right bytes. A mesh's
12
+ indices are rebased onto the staged vertices and a respecified buffer keeps
13
+ nothing, so both mark the slot as holding no pattern and the next flush writes.
14
+
15
+ `u_color` and `u_alpha` were excluded from `UploadedUniforms` because several
16
+ places wrote them directly. All of those now go through `setColorUniform` /
17
+ `setAlphaUniform`, which makes the cache correct per program rather than
18
+ dependent on knowing which caller uses which — the batch holds `u_color` at
19
+ white forever and was re-sending it once per flush.
20
+
21
+ Measured together on an M2 Max via ANGLE (`tests/perf/clip-cost.spec.ts`): a
22
+ flush 5.39 -> 3.22 us, entering a clip 12.47 -> 9.53. Read the difference, not
23
+ the absolutes — the same spec measured a 4.35 us flush earlier on a cooler
24
+ machine, and only the two halves of one A/B are comparable.
25
+
26
+ - f7df982: Path booleans keep holes, and Bezier flattening terminates on degenerate input
27
+
28
+ `pathToMultiPolygon` emitted every contour of a path as its own polygon.
29
+ `polygon-clipping` unions the polygons of a MultiPolygon, so a donut lost its
30
+ hole the moment it entered any boolean op — `pathUnion`, `pathIntersect`,
31
+ `pathSubtract`, `pathExclude`, `pathDivide` and `pathCrop` all returned a
32
+ filled disc. The path's `fillRule` was never read. Contours are now resolved
33
+ into outer + hole rings by nesting depth, honoring both `nonzero` and
34
+ `evenodd`, before the clipper sees them.
35
+
36
+ Results of a boolean op on a path with holes change shape, so this can move
37
+ pixels.
38
+
39
+ `flattenCubic`, `flattenQuadratic` and their arc-length variants recursed
40
+ forever on a non-finite control point and on a tolerance of `0`, `NaN`, or a
41
+ negative number — the flatness test can never be satisfied, so a stroke or a
42
+ hit-test on a path carrying a `NaN` coordinate blew the stack. Non-finite
43
+ input now emits the segment endpoint and stops; a non-positive tolerance is
44
+ floored at `1e-6`.
45
+
46
+ - 85be764: Fix four renderer bugs found in a review of `packages/core/src/renderer`.
47
+
48
+ - A stroke carrying per-anchor `vertexColors` never set the stencil test
49
+ before its draw. Inside a clipped group it ignored the clip and wrote clip
50
+ bits of its own; drawn after a clipped group it was tested against a bit
51
+ that had just been cleared and disappeared entirely.
52
+ - `GroupState` was never reset between frames, so a frame that threw part-way
53
+ down the tree (the max-7 clip nesting error, for one) left every enclosing
54
+ group's transform, alpha and color matrix on the stack and shifted every
55
+ later frame.
56
+ - `dispose()` never deleted the pattern-fill program.
57
+ - `GLTextureCache` applied a texture's wrap mode on first upload only, so a
58
+ registered image used as both a clamped shader texture and a repeating
59
+ pattern tile got whichever mode reached it first.
60
+
61
+ Also: re-registering a custom shader program on a renderer now deletes the
62
+ program it replaces instead of orphaning it.
63
+
64
+ - a3db906: Correctness pass over the tools, canvas, interactions and affordances layers.
65
+
66
+ Fixed, each with a test: a UI-driven ongoing action (color/opacity pickers)
67
+ committed a second time when `cancelAll` had already ended its handle; the
68
+ `align.*` and `distribute.*` descriptors reported themselves permanently
69
+ disabled, greying out every `<ActionBar>` entry; `reorder.backward`,
70
+ `align.*`, `distribute.*` and `pathfinder.*` read deps they never declared in
71
+ `requires`, which throws in dev builds and silently bypasses a consumer's
72
+ history in production; `ActionsRegistry.begin` ignored `requires` and so never
73
+ passed the paint actions their `applyOps`; `Canvas.hitTestExtras` handed
74
+ registered layers `undefined` where `draw` gets live data, making
75
+ `composeAffordanceLayer`'s hit-test throw; `<Canvas>` never disposed its GL
76
+ renderer on unmount; `useTools` returned a stale registry when a tool was
77
+ added after mount; an `actions` prop override deleted the default action it
78
+ merged onto when the prop object was rebuilt; picking and marquee selected
79
+ nodes on hidden layers; a throwing drop-zone `onDrop` stranded every later
80
+ pointer drag; `snapBackOrDelete`'s `'snap-back'` policy left the node where it
81
+ was dropped; a cancelled pen handle-drag left the anchor it placed; and anchor
82
+ affordances on a second selected path routed their drag into the path actually
83
+ being edited.
84
+
85
+ Removed as unreachable: `useViewportTools`, `Canvas.previewBoundsExtra`,
86
+ `marqueeDrawCommands`, `applyHitExistingGate`, and the `enableKeyboard` options
87
+ on `useAlign` / `useDistribute`, which documented a registration those hooks do
88
+ not perform — `useStandardActions` owns it. The public `InsertOverlayStyle`
89
+ type `marqueeDrawCommands` carried is unchanged and still exported.
90
+
91
+ - 12303bc: The solid batch no longer rewrites one pair of GL buffers on every flush. It
92
+ cycles a ring of buffer sets instead — 64 slot-sized ones, plus 4 growable ones
93
+ for a flush too big for a slot — so a write lands that many draws behind the
94
+ draw that read the same buffer. On an M2 Max via ANGLE a flush goes from ~54 us
95
+ to ~4.4, which is the cost anything that breaks a run of solid geometry was
96
+ paying: entering a clip is 64.9 us -> 10.2, and a boundary between solid and any
97
+ other command kind is 28.4 us -> 2.5. Measured by `tests/perf/clip-cost.spec.ts`
98
+ and `tests/perf/transition-matrix.spec.ts`.
99
+
100
+ The driver tracks a write hazard per buffer object, so a flush that overwrote
101
+ its buffers from offset 0 waited on the draw still reading them. Writing
102
+ disjoint ranges of one buffer does not escape that — the hazard is per object,
103
+ not per range.
104
+
105
+ Nothing about the API or the pixels changes. Buffers are taken on first use
106
+ rather than at construction, so a renderer that never draws solid geometry
107
+ allocates none, and every set is freed in `WeaselRenderer.dispose`.
108
+
109
+ - d36953e: SVG import and export lose less on the way through, and installed fonts pick
110
+ one face per variant slot.
111
+
112
+ Paint servers are now found wherever they are declared, not just as direct
113
+ children of `<defs>`, and a gradient that inherits another's stops or geometry
114
+ through `href` / `xlink:href` resolves instead of coming back empty.
115
+ Percentages are read as ratios, so `x2="100%"` no longer means 100 bounds
116
+ units, and `gradientTransform` warns rather than silently painting elsewhere.
117
+
118
+ Three fidelity bugs in the round trip itself. A leaf's own `transform` was
119
+ decomposed against bounds that had already been through the inherited matrix,
120
+ so a rotation inside a translated `<g>` lost its rotation and moved. Any
121
+ stroke carrying `stroke-opacity` re-serialized with the attribute written
122
+ twice, which is not well-formed XML. And the computed `viewBox` was taken from
123
+ unrotated, untransformed geometry, cropping rotated content out of the export.
124
+
125
+ `<text>` now follows SVG's whitespace rules, so importing a pretty-printed
126
+ file no longer drags the source indentation into the document text; weasel's
127
+ own `<text>` carries `xml:space="preserve"` to keep real line breaks. A nested
128
+ `<svg x= y=>` places its children at that origin.
129
+
130
+ In the shared `d=` grammar, exponent coordinates (`M1e2 1e2`) no longer read
131
+ the `e` as a command, and arc flags written without separators
132
+ (`A5 5 0 0110 0`) no longer drop the arc.
133
+
134
+ `enableLocalFontOutlines` picks the least-qualified face when several installed
135
+ faces reduce to one (weight, style) slot, so "Helvetica Neue Condensed Bold"
136
+ stops displacing "Helvetica Neue Bold" depending on query order.
137
+
138
+ **Exported SVG bytes change**: `<text>` gains `xml:space="preserve"`, a stroke
139
+ writes `stroke-opacity` once, and a document containing rotated or
140
+ group-transformed content gets a larger computed `viewBox`.
141
+
142
+ - Updated dependencies [bd42540]
143
+ - Updated dependencies [d36953e]
144
+ - @weasel-js/geom@1.0.4
145
+ - @weasel-js/history@1.0.4
146
+ - @weasel-js/gestures@1.0.4
147
+ - @weasel-js/font@1.0.4
148
+ - @weasel-js/modes@1.0.4
149
+
150
+ ## 1.0.3
151
+
152
+ ### Patch Changes
153
+
154
+ - 5d25a40: `@weasel-js/font`'s six reset seams — `_resetFontRegistryForTests`,
155
+ `_resetFallbackForTests`, `_getPagesForTests`, `_resetDynamicFontsForTests`,
156
+ `__setGlyphRasterizerForTests` and `_resetFontOutlinesForTests` — are no longer
157
+ exported from the package barrel. They now live at a new
158
+ `@weasel-js/font/test-seams` entry point.
159
+
160
+ Nothing loses the ability to reach them. They exist because font registration,
161
+ the fallback policy, the dynamic atlas and the outline registry are global
162
+ module state that changes what renders, so a test in another package that sets
163
+ one has to be able to put it back — which is why they were on the barrel in the
164
+ first place. A named test-seam entry serves that need without an application
165
+ finding a `_resetFontOutlinesForTests` by autocompleting the barrel. Both
166
+ entries share one chunk, so the registries remain single instances.
167
+
168
+ This is a breaking change for anything importing those six names from
169
+ `@weasel-js/font`; the import specifier is the only edit.
170
+
171
+ `evaluateEnabled` in `@weasel-js/core` is now marked `@experimental` at its
172
+ definition. An `@internal` block intended for it had come detached and sat above
173
+ three unrelated constants, so the function read as undocumented public API while
174
+ a stale marker said otherwise. It is genuinely public — `@weasel-js/ui`'s
175
+ `ActionBar` calls it — and `@experimental` matches the rest of the `enabled`
176
+ predicate surface.
177
+
178
+ - f7077f6: An image quad no longer mints and frees a vertex array and two buffers on every
179
+ draw. The renderer keeps a ring of quad geometry per image program instead, and
180
+ a draw writes its four corners into the next slot. On an M2 Max via ANGLE this
181
+ takes an image command from ~7.0 us to ~3.9 us, measured by
182
+ `tests/perf/image-quad.spec.ts`; nothing about the API or the pixels changes.
183
+
184
+ A ring rather than one buffer, because one is the worst of the three shapes. The
185
+ driver tracks a write hazard per buffer object, so rewriting a single quad
186
+ buffer before each draw waits on the draw still reading it — 40–80 us per quad
187
+ against 5.4 for the per-draw allocation this replaced and 0.3 for the ring.
188
+ Sixty-four slots put that many draws between one write of a buffer and the next.
189
+
190
+ The remaining gap to a pattern-filled rect of the same size (~2.3 us) is texture
191
+ state, not geometry: an image binds a different texture and sets its filter per
192
+ draw.
193
+
194
+ - 514c34a: Document every public export at its definition site
195
+
196
+ A JSDoc string now sits on each symbol reachable through a package's published
197
+ entry points, in every package except `@weasel-js/ui`. Documentation only — no
198
+ export was added, removed, renamed or reordered, and no behavior changed.
199
+
200
+ `npm run audit:jsdoc` enumerates the public exports and reports which lack a
201
+ docstring, so the claim can be re-derived rather than trusted.
202
+
203
+ - Updated dependencies [5d25a40]
204
+ - Updated dependencies [514c34a]
205
+ - @weasel-js/font@1.0.3
206
+ - @weasel-js/geom@1.0.3
207
+ - @weasel-js/gestures@1.0.3
208
+ - @weasel-js/history@1.0.3
209
+ - @weasel-js/modes@1.0.3
210
+
3
211
  ## 1.0.2
4
212
 
5
213
  ### Patch Changes
@@ -33,6 +33,10 @@ declare function apply(m: Mat3, x: number, y: number): [number, number];
33
33
  * matches clip-down).
34
34
  */
35
35
  declare function screenToClip(width: number, height: number): Mat3;
36
+ /** The renderer's 3x3 matrix operations, as one namespace. These work on the
37
+ * 9-element `Float32Array` form the GL uniform upload wants — distinct from
38
+ * `@weasel-js/geom`'s 6-element affine `Mat3`, though the logical element
39
+ * order is the same. */
36
40
  declare const mat3: {
37
41
  identity: typeof identity;
38
42
  multiply: typeof multiply;
@@ -140,6 +144,9 @@ declare function fontString(s: ResolvedTextStyle): string;
140
144
  * (300/500/900) are out of scope for slice 1.
141
145
  */
142
146
 
147
+ /** A span of text with its own styling, as authored. Fields left absent
148
+ * inherit from the node's text style — this is the difference between a run
149
+ * and a fully resolved one. */
143
150
  interface StyledRun {
144
151
  text: string;
145
152
  bold?: boolean;
@@ -155,8 +162,13 @@ interface StyledRun {
155
162
  underline?: boolean;
156
163
  strikethrough?: boolean;
157
164
  }
165
+ /** Normalize the two accepted spellings of text content — a plain string or
166
+ * an array of runs — to runs. Throws on a run with no string `text`. */
158
167
  declare function toRuns(input: string | StyledRun[]): StyledRun[];
168
+ /** Concatenate runs, dropping all styling. */
159
169
  declare function runsToPlainText(runs: readonly StyledRun[]): string;
170
+ /** Render runs as Markdown, preserving bold and italic. The flavor written to
171
+ * the clipboard alongside the plain-text one. */
160
172
  declare function runsToMarkdown(runs: readonly StyledRun[]): string;
161
173
  /**
162
174
  * Parse a small markdown subset (`**bold**`, `*italic*`, `***both***`) into
@@ -184,6 +196,8 @@ declare function markdownToRuns(input: string): StyledRun[];
184
196
  * `runs/rangeStyle.ts` for why the model collapses the tri-state.
185
197
  */
186
198
 
199
+ /** A run with every style resolved against the node's text style — no
200
+ * optional inheritance left. This is what layout and painting consume. */
187
201
  interface ResolvedRun {
188
202
  text: string;
189
203
  fontFamily: string;
@@ -201,6 +215,8 @@ interface ResolvedRun {
201
215
  /** Draw a rule through this run's x-height. Additive over the node style. */
202
216
  strikethrough: boolean;
203
217
  }
218
+ /** Resolve each run's styling against the node's text style, filling in
219
+ * everything the run left inherited. */
204
220
  declare function resolveRuns(runs: readonly StyledRun[], style: ResolvedTextStyle): ResolvedRun[];
205
221
 
206
222
  /**
@@ -210,6 +226,9 @@ declare function resolveRuns(runs: readonly StyledRun[], style: ResolvedTextStyl
210
226
  * `height`) is the legacy behavior: offset 0.
211
227
  */
212
228
  type TextVerticalAlign = 'top' | 'center' | 'bottom';
229
+ /** How far to shift laid-out text down inside a box of `boxHeight` to satisfy
230
+ * a vertical alignment. Zero when the box height is unknown or alignment is
231
+ * top. */
213
232
  declare function verticalAlignOffset(align: TextVerticalAlign | undefined, boxHeight: number | undefined, textHeight: number): number;
214
233
 
215
234
  /**
@@ -286,6 +305,8 @@ interface SolidPaint {
286
305
  }
287
306
  /** DrawCommand variants implemented through step 6. */
288
307
  type DrawCommand = PathDrawCommand | GroupDrawCommand | TextDrawCommand | ImageDrawCommand | ShaderDrawCommand;
308
+ /** Draw a path, filled and/or stroked. The workhorse command: every shape the
309
+ * kit draws that is not text, an image, or a custom shader is one of these. */
289
310
  interface PathDrawCommand {
290
311
  kind: 'path';
291
312
  path: Path;
@@ -308,6 +329,9 @@ interface PathDrawCommand {
308
329
  */
309
330
  vertexColors?: number[];
310
331
  }
332
+ /** Draw a list of commands under a shared transform, opacity, color matrix
333
+ * and clip. Groups nest, and their effects accumulate down the stack — this
334
+ * is how a container node's transform reaches its descendants. */
311
335
  interface GroupDrawCommand {
312
336
  kind: 'group';
313
337
  transform?: Mat3;
@@ -1,4 +1,4 @@
1
- import { elevateQuadraticToCubic, cubicBounds, transformCoords, boxToBox } from '@weasel-js/geom';
1
+ import { elevateQuadraticToCubic, cubicBounds, pointSegmentDist2, transformCoords, boxToBox } from '@weasel-js/geom';
2
2
 
3
3
  // src/core/units.ts
4
4
  function resolveUnit(v, unitSystem) {
@@ -119,6 +119,16 @@ function boundsOfPath(path) {
119
119
 
120
120
  // src/features/paths/flatten.ts
121
121
  var DEFAULT_FLATTEN_TOLERANCE = 0.5;
122
+ var MIN_FLATTEN_TOLERANCE = 1e-6;
123
+ function usableTolerance(tolerance) {
124
+ return tolerance > 0 ? tolerance : MIN_FLATTEN_TOLERANCE;
125
+ }
126
+ function finite6(a, b, c, d, e, f) {
127
+ return Number.isFinite(a) && Number.isFinite(b) && Number.isFinite(c) && Number.isFinite(d) && Number.isFinite(e) && Number.isFinite(f);
128
+ }
129
+ function finite8(a, b, c, d, e, f, g, h) {
130
+ return finite6(a, b, c, d, e, f) && Number.isFinite(g) && Number.isFinite(h);
131
+ }
122
132
  function distPointToLine(px, py, ax, ay, bx, by) {
123
133
  const dx = bx - ax;
124
134
  const dy = by - ay;
@@ -132,6 +142,13 @@ function distPointToLine(px, py, ax, ay, bx, by) {
132
142
  return Math.abs(cross) / Math.sqrt(len2);
133
143
  }
134
144
  function flattenCubic(x0, y0, x1, y1, x2, y2, x3, y3, tolerance, out) {
145
+ if (!finite8(x0, y0, x1, y1, x2, y2, x3, y3)) {
146
+ out.push(x3, y3);
147
+ return;
148
+ }
149
+ flattenCubicRec(x0, y0, x1, y1, x2, y2, x3, y3, usableTolerance(tolerance), out);
150
+ }
151
+ function flattenCubicRec(x0, y0, x1, y1, x2, y2, x3, y3, tolerance, out) {
135
152
  const d1 = distPointToLine(x1, y1, x0, y0, x3, y3);
136
153
  const d2 = distPointToLine(x2, y2, x0, y0, x3, y3);
137
154
  if (Math.max(d1, d2) <= tolerance) {
@@ -144,10 +161,17 @@ function flattenCubic(x0, y0, x1, y1, x2, y2, x3, y3, tolerance, out) {
144
161
  const x012 = (x01 + x12) * 0.5, y012 = (y01 + y12) * 0.5;
145
162
  const x123 = (x12 + x23) * 0.5, y123 = (y12 + y23) * 0.5;
146
163
  const x0123 = (x012 + x123) * 0.5, y0123 = (y012 + y123) * 0.5;
147
- flattenCubic(x0, y0, x01, y01, x012, y012, x0123, y0123, tolerance, out);
148
- flattenCubic(x0123, y0123, x123, y123, x23, y23, x3, y3, tolerance, out);
164
+ flattenCubicRec(x0, y0, x01, y01, x012, y012, x0123, y0123, tolerance, out);
165
+ flattenCubicRec(x0123, y0123, x123, y123, x23, y23, x3, y3, tolerance, out);
149
166
  }
150
167
  function flattenQuadratic(x0, y0, x1, y1, x2, y2, tolerance, out) {
168
+ if (!finite6(x0, y0, x1, y1, x2, y2)) {
169
+ out.push(x2, y2);
170
+ return;
171
+ }
172
+ flattenQuadraticRec(x0, y0, x1, y1, x2, y2, usableTolerance(tolerance), out);
173
+ }
174
+ function flattenQuadraticRec(x0, y0, x1, y1, x2, y2, tolerance, out) {
151
175
  const d = distPointToLine(x1, y1, x0, y0, x2, y2);
152
176
  if (d <= tolerance) {
153
177
  out.push(x2, y2);
@@ -156,11 +180,16 @@ function flattenQuadratic(x0, y0, x1, y1, x2, y2, tolerance, out) {
156
180
  const x01 = (x0 + x1) * 0.5, y01 = (y0 + y1) * 0.5;
157
181
  const x12 = (x1 + x2) * 0.5, y12 = (y1 + y2) * 0.5;
158
182
  const x012 = (x01 + x12) * 0.5, y012 = (y01 + y12) * 0.5;
159
- flattenQuadratic(x0, y0, x01, y01, x012, y012, tolerance, out);
160
- flattenQuadratic(x012, y012, x12, y12, x2, y2, tolerance, out);
183
+ flattenQuadraticRec(x0, y0, x01, y01, x012, y012, tolerance, out);
184
+ flattenQuadraticRec(x012, y012, x12, y12, x2, y2, tolerance, out);
161
185
  }
162
186
  function flattenCubicWithArcLen(x0, y0, x1, y1, x2, y2, x3, y3, tolerance, out, arcOut) {
163
- return flattenCubicArcRec(x0, y0, x1, y1, x2, y2, x3, y3, tolerance, out, arcOut, 0);
187
+ if (!finite8(x0, y0, x1, y1, x2, y2, x3, y3)) {
188
+ out.push(x3, y3);
189
+ arcOut.push(0);
190
+ return 0;
191
+ }
192
+ return flattenCubicArcRec(x0, y0, x1, y1, x2, y2, x3, y3, usableTolerance(tolerance), out, arcOut, 0);
164
193
  }
165
194
  function flattenCubicArcRec(x0, y0, x1, y1, x2, y2, x3, y3, tolerance, out, arcOut, accum) {
166
195
  const d1 = distPointToLine(x1, y1, x0, y0, x3, y3);
@@ -185,7 +214,12 @@ function flattenCubicArcRec(x0, y0, x1, y1, x2, y2, x3, y3, tolerance, out, arcO
185
214
  return accum;
186
215
  }
187
216
  function flattenQuadraticWithArcLen(x0, y0, x1, y1, x2, y2, tolerance, out, arcOut) {
188
- return flattenQuadraticArcRec(x0, y0, x1, y1, x2, y2, tolerance, out, arcOut, 0);
217
+ if (!finite6(x0, y0, x1, y1, x2, y2)) {
218
+ out.push(x2, y2);
219
+ arcOut.push(0);
220
+ return 0;
221
+ }
222
+ return flattenQuadraticArcRec(x0, y0, x1, y1, x2, y2, usableTolerance(tolerance), out, arcOut, 0);
189
223
  }
190
224
  function flattenQuadraticArcRec(x0, y0, x1, y1, x2, y2, tolerance, out, arcOut, accum) {
191
225
  const d = distPointToLine(x1, y1, x0, y0, x2, y2);
@@ -205,8 +239,6 @@ function flattenQuadraticArcRec(x0, y0, x1, y1, x2, y2, tolerance, out, arcOut,
205
239
  accum = flattenQuadraticArcRec(x012, y012, x12, y12, x2, y2, tolerance, out, arcOut, accum);
206
240
  return accum;
207
241
  }
208
-
209
- // src/features/paths/hitTest.ts
210
242
  function pointInPath(path, x, y, opts = {}) {
211
243
  if (path.kind === "rect") {
212
244
  return x >= path.x && x <= path.x + path.width && y >= path.y && y <= path.y + path.height;
@@ -380,22 +412,6 @@ function polylineWithinThreshold(path, px, py, t2, tolerance) {
380
412
  if (subOpen && checkSegments(false)) return true;
381
413
  return false;
382
414
  }
383
- function pointSegmentDist2(px, py, ax, ay, bx, by) {
384
- const dx = bx - ax;
385
- const dy = by - ay;
386
- const len2 = dx * dx + dy * dy;
387
- if (len2 === 0) {
388
- const ex2 = px - ax, ey2 = py - ay;
389
- return ex2 * ex2 + ey2 * ey2;
390
- }
391
- let t = ((px - ax) * dx + (py - ay) * dy) / len2;
392
- if (t < 0) t = 0;
393
- else if (t > 1) t = 1;
394
- const cx = ax + t * dx;
395
- const cy = ay + t * dy;
396
- const ex = px - cx, ey = py - cy;
397
- return ex * ex + ey * ey;
398
- }
399
415
 
400
416
  // src/features/paths/builder.ts
401
417
  var PathBuilder = class _PathBuilder {
@@ -864,5 +880,5 @@ function guideSnapStrategy(getGuides, options = {}) {
864
880
  }
865
881
 
866
882
  export { AUTO_POSE_DESCRIPTOR, DEFAULT_FLATTEN_TOLERANCE, DEFAULT_GUIDE_TOLERANCE_PX, IMPERIAL_INCHES, METRIC_MM, PATH_C, PATH_CMD_LENGTHS, PATH_L, PATH_M, PATH_Q, PATH_Z, PIXELS, PathBuilder, RECT_ORIGIN_PROJECTION, RECT_POSE_DESCRIPTOR, ROTATED_POSE_DESCRIPTOR, boundsOfPath, ellipsePath, flattenCubic, flattenCubicWithArcLen, flattenQuadratic, flattenQuadraticWithArcLen, formatUnit, gridSnapStrategy, guideSnapStrategy, linePath, pathPoseDescriptor, pointInPath, pointToGridCell, polygonFromPoints, pxExtent, rectPath, regularPolygonPath, remapRotatedLeaf, resolveUnit, scaleDelta, scalePathToBounds, starPath, strokeHitTest, transformPath, translatePath, translatePolygonInPlace, withinPxBox, withinPxRadius };
867
- //# sourceMappingURL=chunk-6SHZHXXR.js.map
868
- //# sourceMappingURL=chunk-6SHZHXXR.js.map
883
+ //# sourceMappingURL=chunk-4Z6J4IVH.js.map
884
+ //# sourceMappingURL=chunk-4Z6J4IVH.js.map