@weasel-js/geom 1.4.4 → 1.5.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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/booleans/adapter.ts","../../src/booleans/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Adapter between geom's path input shape and `polygon-clipping`'s\n * `MultiPolygon` format. Kept in a dedicated module so the dep is one\n * import away from being swappable. Ported from\n * `src/features/paths/booleans.adapter.ts`.\n *\n * `polygon-clipping` expects:\n * MultiPolygon = Polygon[]\n * Polygon = Ring[] (first ring outer, subsequent rings holes)\n * Ring = [x, y][] (closed — first vertex repeated as last)\n *\n * Bezier inputs are flattened (cubic; quadratics are degree-elevated to cubic\n * first) — v1 is straight-line only. Open contours are implicitly closed\n * because boolean ops are defined on closed regions; polylines have zero area\n * and would otherwise be silently dropped.\n *\n * The `[x,y][]` nested-array form here is the one place geom's flat-everywhere\n * rule is suspended — it is the third-party clipper's required API.\n */\nimport { PATH_M, PATH_L, PATH_C, PATH_Q, PATH_Z } from '../commands';\nimport { flattenCubic, elevateQuadraticToCubic } from '../curve';\n\n/** Minimal path input: a rect or a polygon command stream. geom does not\n * import @weasel-js/core's `Path`; the kit maps `Path` onto this shape. */\nexport type GeomPath =\n | { kind: 'rect'; x: number; y: number; width: number; height: number }\n | { kind: 'polygon'; commands: ArrayLike<number>; coords: ArrayLike<number>; fillRule?: 'nonzero' | 'evenodd' };\n\nconst DEFAULT_FLATTEN_TOLERANCE = 0.5;\n\n/** A `[x, y]` 2-tuple. */\nexport type Pair = [number, number];\n/** Closed ring (first vertex repeated as last). */\nexport type Ring = Pair[];\n/** Polygon: one outer ring optionally followed by hole rings. */\nexport type Polygon = Ring[];\n/** MultiPolygon: list of polygons (used for boolean op I/O). */\nexport type MultiPolygon = Polygon[];\n\nexport interface PathToMultiPolygonOptions {\n /** Flattening tolerance for bezier segments. Default: `DEFAULT_FLATTEN_TOLERANCE`. */\n tolerance?: number;\n}\n\n/** Polygon result shape emitted by `multiPolygonToPath`. */\nexport type GeomPolygonPath = { kind: 'polygon'; commands: Uint8Array; coords: Float32Array; fillRule: 'nonzero' };\n\n/** Convert a `GeomPath` to a `MultiPolygon` suitable for `polygon-clipping`. */\nexport function pathToMultiPolygon(\n path: GeomPath,\n opts: PathToMultiPolygonOptions = {},\n): MultiPolygon {\n if (path.kind === 'rect') {\n const { x, y, width, height } = path;\n const ring: Ring = [\n [x, y],\n [x + width, y],\n [x + width, y + height],\n [x, y + height],\n [x, y],\n ];\n return [[ring]];\n }\n\n const tolerance = opts.tolerance ?? DEFAULT_FLATTEN_TOLERANCE;\n const rings: Ring[] = [];\n let current: Ring | null = null;\n let cx = 0, cy = 0;\n let ci = 0;\n const { commands, coords } = path;\n\n const finalizeCurrent = () => {\n if (!current || current.length === 0) return;\n // Close the ring by repeating the first vertex if not already closed.\n const first = current[0];\n const last = current[current.length - 1];\n if (first[0] !== last[0] || first[1] !== last[1]) {\n current.push([first[0], first[1]]);\n }\n if (current.length >= 4) rings.push(current); // 3 unique + 1 closing\n current = null;\n };\n\n for (let i = 0; i < commands.length; i++) {\n const cmd = commands[i];\n switch (cmd) {\n case PATH_M: {\n finalizeCurrent();\n cx = coords[ci]; cy = coords[ci + 1];\n current = [[cx, cy]];\n ci += 2;\n break;\n }\n case PATH_L: {\n cx = coords[ci]; cy = coords[ci + 1];\n if (current) current.push([cx, cy]);\n ci += 2;\n break;\n }\n case PATH_C: {\n const x1 = coords[ci], y1 = coords[ci + 1];\n const x2 = coords[ci + 2], y2 = coords[ci + 3];\n const x3 = coords[ci + 4], y3 = coords[ci + 5];\n const out: number[] = [];\n flattenCubic(cx, cy, x1, y1, x2, y2, x3, y3, tolerance, out);\n if (current) for (let k = 0; k < out.length; k += 2) current.push([out[k], out[k + 1]]);\n cx = x3; cy = y3;\n ci += 6;\n break;\n }\n case PATH_Q: {\n const x1 = coords[ci], y1 = coords[ci + 1];\n const x2 = coords[ci + 2], y2 = coords[ci + 3];\n const [c1x, c1y, c2x, c2y] = elevateQuadraticToCubic(cx, cy, x1, y1, x2, y2);\n const out: number[] = [];\n flattenCubic(cx, cy, c1x, c1y, c2x, c2y, x2, y2, tolerance, out);\n if (current) for (let k = 0; k < out.length; k += 2) current.push([out[k], out[k + 1]]);\n cx = x2; cy = y2;\n ci += 4;\n break;\n }\n case PATH_Z: {\n finalizeCurrent();\n break;\n }\n default:\n throw new Error(`pathToMultiPolygon: unknown command ${cmd}`);\n }\n }\n finalizeCurrent();\n\n if (rings.length === 0) return [];\n return nestRings(rings, path.fillRule ?? 'nonzero');\n}\n\n/** Twice the signed area of a closed ring. Positive and negative encode the\n * two winding directions; the factor of two is irrelevant to both uses\n * (sign, and comparison against zero). */\nfunction doubleSignedArea(ring: Ring): number {\n let a = 0;\n for (let i = 0, n = ring.length - 1; i < n; i++) {\n a += ring[i][0] * ring[i + 1][1] - ring[i + 1][0] * ring[i][1];\n }\n return a;\n}\n\n/** Even-odd ray cast of `(px, py)` against a closed ring. */\nfunction pointInRing(ring: Ring, px: number, py: number): boolean {\n let inside = false;\n for (let i = 0, j = ring.length - 2, n = ring.length - 1; i < n; j = i++) {\n const [xi, yi] = ring[i];\n const [xj, yj] = ring[j];\n if ((yi > py) !== (yj > py) && px < ((xj - xi) * (py - yi)) / (yj - yi) + xi) {\n inside = !inside;\n }\n }\n return inside;\n}\n\n/**\n * Group a path's rings into `polygon-clipping` polygons — one filled outer\n * ring followed by the hole rings immediately inside it.\n *\n * Without this a path's own holes are lost: separate polygons in a\n * MultiPolygon are unioned, so a donut arrives at the clipper as a solid disc.\n *\n * Containment is probed from the midpoint of each ring's first edge rather\n * than from a vertex — a shared vertex between a hole and its container is\n * common, and a probe point sitting exactly on the tested boundary answers\n * arbitrarily.\n */\nfunction nestRings(rings: Ring[], fillRule: 'nonzero' | 'evenodd'): MultiPolygon {\n const n = rings.length;\n if (n === 1) return [[rings[0]]];\n\n const areas = rings.map(doubleSignedArea);\n const probes = rings.map((r): Pair => [(r[0][0] + r[1][0]) / 2, (r[0][1] + r[1][1]) / 2]);\n\n // containers[i] — indices of the rings that enclose ring i.\n const containers: number[][] = rings.map(() => []);\n for (let i = 0; i < n; i++) {\n for (let j = 0; j < n; j++) {\n if (i !== j && pointInRing(rings[j], probes[i][0], probes[i][1])) containers[i].push(j);\n }\n }\n\n const filled = rings.map((_, i) => {\n if (fillRule === 'evenodd') return containers[i].length % 2 === 0;\n let winding = Math.sign(areas[i]);\n for (const j of containers[i]) winding += Math.sign(areas[j]);\n return winding !== 0;\n });\n\n const out: MultiPolygon = [];\n for (let i = 0; i < n; i++) {\n if (!filled[i]) continue;\n const poly: Polygon = [rings[i]];\n for (let k = 0; k < n; k++) {\n if (filled[k] || containers[k].length !== containers[i].length + 1) continue;\n if (containers[k].includes(i)) poly.push(rings[k]);\n }\n out.push(poly);\n }\n return out;\n}\n\n/** Convert a `MultiPolygon` to a polygon path with `fillRule: 'nonzero'`. */\nexport function multiPolygonToPath(mp: MultiPolygon): GeomPolygonPath {\n // First pass: count total commands and coord floats.\n let nCmds = 0;\n let nCoords = 0;\n for (const poly of mp) {\n for (const ring of poly) {\n if (ring.length < 4) continue; // 3 unique + 1 closing minimum\n // Drop the repeated closing vertex; emit M + (n-2) L + Z.\n const unique = ring.length - 1;\n nCmds += 1 + (unique - 1) + 1; // M + L*(unique-1) + Z\n nCoords += unique * 2;\n }\n }\n const commands = new Uint8Array(nCmds);\n const coords = new Float32Array(nCoords);\n let ci = 0;\n let pi = 0;\n for (const poly of mp) {\n for (const ring of poly) {\n if (ring.length < 4) continue;\n const unique = ring.length - 1;\n // M (first vertex)\n commands[ci++] = PATH_M;\n coords[pi++] = ring[0][0];\n coords[pi++] = ring[0][1];\n // L for vertices 1..unique-1\n for (let k = 1; k < unique; k++) {\n commands[ci++] = PATH_L;\n coords[pi++] = ring[k][0];\n coords[pi++] = ring[k][1];\n }\n // Z\n commands[ci++] = PATH_Z;\n }\n }\n return { kind: 'polygon', commands, coords, fillRule: 'nonzero' };\n}\n","/**\n * Polygon-boolean operations on `GeomPath` values, backed by\n * `polygon-clipping`. Ported from `src/features/paths/booleans.ts`.\n *\n * v1 limitations (documented; see design doc):\n * - Bezier inputs are flattened to straight-line segments before clipping.\n * The result therefore contains only M/L/Z commands.\n * - Open contours are treated as closed for boolean purposes (a polyline\n * has zero area and would otherwise be silently dropped).\n * - Output `fillRule` is always `'nonzero'`. The engine emits canonical\n * non-overlapping rings, so the choice is cosmetic on its output.\n *\n * This is the ONLY geom module that depends on `polygon-clipping`; it lives in\n * the `@weasel-js/geom/booleans` subpath so the core stays `deps: {}`.\n */\nimport polygonClipping from 'polygon-clipping';\nimport { pathToMultiPolygon, multiPolygonToPath, type GeomPath, type GeomPolygonPath } from './adapter';\n\nexport type { GeomPath, GeomPolygonPath } from './adapter';\n\n/** Union of N paths. Commutative. Returns an empty path if all inputs are empty. */\nexport function pathUnion(...paths: GeomPath[]): GeomPolygonPath {\n if (paths.length === 0) return multiPolygonToPath([]);\n const mps = paths.map((p) => pathToMultiPolygon(p));\n const [head, ...rest] = mps;\n return multiPolygonToPath(polygonClipping.union(head, ...rest));\n}\n\n/** Intersection of N paths. Commutative. Empty result is an empty path. */\nexport function pathIntersect(...paths: GeomPath[]): GeomPolygonPath {\n if (paths.length === 0) return multiPolygonToPath([]);\n const mps = paths.map((p) => pathToMultiPolygon(p));\n const [head, ...rest] = mps;\n return multiPolygonToPath(polygonClipping.intersection(head, ...rest));\n}\n\n/** Asymmetric difference: returns `a − b`. */\nexport function pathSubtract(a: GeomPath, b: GeomPath): GeomPolygonPath {\n return multiPolygonToPath(polygonClipping.difference(pathToMultiPolygon(a), pathToMultiPolygon(b)));\n}\n\n/** Symmetric difference (XOR) of N paths. Commutative. */\nexport function pathExclude(...paths: GeomPath[]): GeomPolygonPath {\n if (paths.length === 0) return multiPolygonToPath([]);\n const mps = paths.map((p) => pathToMultiPolygon(p));\n const [head, ...rest] = mps;\n return multiPolygonToPath(polygonClipping.xor(head, ...rest));\n}\n\n/**\n * Fracture N paths along every intersection into the maximal set of\n * non-overlapping regions. Returns one polygon path per region.\n *\n * Algorithm: for every non-empty subset S ⊆ {A1..AN}, emit the region\n * `(∩ S) − (∪ complement)` — points covered by exactly the members of S\n * and no others. By construction the emitted regions are pairwise disjoint\n * and their union equals `pathUnion(A1..AN)`.\n *\n * For N=2 this collapses to the three Illustrator \"Divide\" outputs\n * (A−B, B−A, A∩B). For N=3 up to 7 regions are emitted. The 2^N − 1\n * subset count limits this to small N in practice; passing more than ~8\n * inputs is a misuse — the polygon-clipping kernel dominates anyway.\n */\nexport function pathDivide(...paths: GeomPath[]): GeomPolygonPath[] {\n if (paths.length === 0) return [];\n if (paths.length === 1) {\n return [multiPolygonToPath(pathToMultiPolygon(paths[0]))];\n }\n const mps = paths.map((p) => pathToMultiPolygon(p));\n const n = mps.length;\n const out: GeomPolygonPath[] = [];\n\n // Iterate every non-empty subset via bitmask. Emit subsets in size-\n // ascending order so the output is stable and reads \"exclusives first,\n // then pairs, then triples, …\" — matches the old N=2 ordering.\n const subsets: number[] = [];\n for (let mask = 1; mask < 1 << n; mask++) subsets.push(mask);\n subsets.sort((a, b) => popcount(a) - popcount(b) || a - b);\n\n for (const mask of subsets) {\n const inside: typeof mps = [];\n const outside: typeof mps = [];\n for (let i = 0; i < n; i++) {\n (mask & (1 << i) ? inside : outside).push(mps[i]);\n }\n const [insideHead, ...insideRest] = inside;\n let region = insideRest.length === 0\n ? insideHead\n : polygonClipping.intersection(insideHead, ...insideRest);\n if (region.length === 0) continue;\n if (outside.length > 0) {\n const [outHead, ...outRest] = outside;\n const outsideUnion = polygonClipping.union(outHead, ...outRest);\n region = polygonClipping.difference(region, outsideUnion);\n if (region.length === 0) continue;\n }\n out.push(multiPolygonToPath(region));\n }\n\n return out;\n}\n\nfunction popcount(n: number): number {\n let c = 0;\n while (n) { n &= n - 1; c++; }\n return c;\n}\n"]}
1
+ {"version":3,"sources":["../../src/booleans/adapter.ts","../../src/booleans/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Adapter between geom's path input shape and `polygon-clipping`'s\n * `MultiPolygon` format. Kept in a dedicated module so the dep is one\n * import away from being swappable. Ported from\n * `src/features/paths/booleans.adapter.ts`.\n *\n * `polygon-clipping` expects:\n * MultiPolygon = Polygon[]\n * Polygon = Ring[] (first ring outer, subsequent rings holes)\n * Ring = [x, y][] (closed — first vertex repeated as last)\n *\n * Bezier inputs are flattened (cubic; quadratics are degree-elevated to cubic\n * first) — v1 is straight-line only. Open contours are implicitly closed\n * because boolean ops are defined on closed regions; polylines have zero area\n * and would otherwise be silently dropped.\n *\n * The `[x,y][]` nested-array form here is the one place geom's flat-everywhere\n * rule is suspended — it is the third-party clipper's required API.\n */\nimport { PATH_M, PATH_L, PATH_C, PATH_Q, PATH_Z } from '../commands';\nimport { elevateQuadraticToCubic } from '../curve';\nimport { flattenCubic } from '../flatten';\n\n/** Minimal path input: a rect or a polygon command stream. geom does not\n * import @weasel-js/core's `Path`; the kit maps `Path` onto this shape. */\nexport type GeomPath =\n | { kind: 'rect'; x: number; y: number; width: number; height: number }\n | { kind: 'polygon'; commands: ArrayLike<number>; coords: ArrayLike<number>; fillRule?: 'nonzero' | 'evenodd' };\n\nconst DEFAULT_FLATTEN_TOLERANCE = 0.5;\n\n/** A `[x, y]` 2-tuple. */\nexport type Pair = [number, number];\n/** Closed ring (first vertex repeated as last). */\nexport type Ring = Pair[];\n/** Polygon: one outer ring optionally followed by hole rings. */\nexport type Polygon = Ring[];\n/** MultiPolygon: list of polygons (used for boolean op I/O). */\nexport type MultiPolygon = Polygon[];\n\nexport interface PathToMultiPolygonOptions {\n /** Flattening tolerance for bezier segments. Default: `DEFAULT_FLATTEN_TOLERANCE`. */\n tolerance?: number;\n}\n\n/** Polygon result shape emitted by `multiPolygonToPath`. */\nexport type GeomPolygonPath = { kind: 'polygon'; commands: Uint8Array; coords: Float32Array; fillRule: 'nonzero' };\n\n/** Convert a `GeomPath` to a `MultiPolygon` suitable for `polygon-clipping`. */\nexport function pathToMultiPolygon(\n path: GeomPath,\n opts: PathToMultiPolygonOptions = {},\n): MultiPolygon {\n if (path.kind === 'rect') {\n const { x, y, width, height } = path;\n const ring: Ring = [\n [x, y],\n [x + width, y],\n [x + width, y + height],\n [x, y + height],\n [x, y],\n ];\n return [[ring]];\n }\n\n const tolerance = opts.tolerance ?? DEFAULT_FLATTEN_TOLERANCE;\n const rings: Ring[] = [];\n let current: Ring | null = null;\n let cx = 0, cy = 0;\n let ci = 0;\n const { commands, coords } = path;\n\n const finalizeCurrent = () => {\n if (!current || current.length === 0) return;\n // Close the ring by repeating the first vertex if not already closed.\n const first = current[0];\n const last = current[current.length - 1];\n if (first[0] !== last[0] || first[1] !== last[1]) {\n current.push([first[0], first[1]]);\n }\n if (current.length >= 4) rings.push(current); // 3 unique + 1 closing\n current = null;\n };\n\n for (let i = 0; i < commands.length; i++) {\n const cmd = commands[i];\n switch (cmd) {\n case PATH_M: {\n finalizeCurrent();\n cx = coords[ci]; cy = coords[ci + 1];\n current = [[cx, cy]];\n ci += 2;\n break;\n }\n case PATH_L: {\n cx = coords[ci]; cy = coords[ci + 1];\n if (current) current.push([cx, cy]);\n ci += 2;\n break;\n }\n case PATH_C: {\n const x1 = coords[ci], y1 = coords[ci + 1];\n const x2 = coords[ci + 2], y2 = coords[ci + 3];\n const x3 = coords[ci + 4], y3 = coords[ci + 5];\n const out: number[] = [];\n flattenCubic(cx, cy, x1, y1, x2, y2, x3, y3, tolerance, out);\n if (current) for (let k = 0; k < out.length; k += 2) current.push([out[k], out[k + 1]]);\n cx = x3; cy = y3;\n ci += 6;\n break;\n }\n case PATH_Q: {\n const x1 = coords[ci], y1 = coords[ci + 1];\n const x2 = coords[ci + 2], y2 = coords[ci + 3];\n const [c1x, c1y, c2x, c2y] = elevateQuadraticToCubic(cx, cy, x1, y1, x2, y2);\n const out: number[] = [];\n flattenCubic(cx, cy, c1x, c1y, c2x, c2y, x2, y2, tolerance, out);\n if (current) for (let k = 0; k < out.length; k += 2) current.push([out[k], out[k + 1]]);\n cx = x2; cy = y2;\n ci += 4;\n break;\n }\n case PATH_Z: {\n finalizeCurrent();\n break;\n }\n default:\n throw new Error(`pathToMultiPolygon: unknown command ${cmd}`);\n }\n }\n finalizeCurrent();\n\n if (rings.length === 0) return [];\n return groupRings(rings, path.fillRule ?? 'nonzero');\n}\n\n/** Shoelace area of a closed ring. Sign gives the winding direction. */\nfunction ringSignedArea(ring: Ring): number {\n let a = 0;\n for (let i = 0, n = ring.length - 1; i < n; i++) {\n a += ring[i][0] * ring[i + 1][1] - ring[i + 1][0] * ring[i][1];\n }\n return a * 0.5;\n}\n\ntype RingBox = [number, number, number, number];\n\nfunction ringBox(ring: Ring): RingBox {\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n for (const [x, y] of ring) {\n if (x < minX) minX = x;\n if (x > maxX) maxX = x;\n if (y < minY) minY = y;\n if (y > maxY) maxY = y;\n }\n return [minX, minY, maxX, maxY];\n}\n\n/** Even-odd ray cast; used only to decide ring nesting, never to fill. */\nfunction pointInRing(ring: Ring, px: number, py: number): boolean {\n let inside = false;\n for (let i = 0, n = ring.length - 1; i < n; i++) {\n const [ax, ay] = ring[i];\n const [bx, by] = ring[i + 1];\n if ((ay > py) !== (by > py) && px < ((bx - ax) * (py - ay)) / (by - ay) + ax) {\n inside = !inside;\n }\n }\n return inside;\n}\n\n/**\n * Nesting test by majority vote over three sample vertices — a single sample\n * gives the wrong answer whenever it lands exactly on the outer ring.\n */\nfunction ringContains(outer: Ring, outerBox: RingBox, inner: Ring, innerBox: RingBox): boolean {\n if (innerBox[0] < outerBox[0] || innerBox[1] < outerBox[1]\n || innerBox[2] > outerBox[2] || innerBox[3] > outerBox[3]) return false;\n const n = inner.length - 1;\n let votes = 0;\n for (const k of [0, Math.floor(n / 3), Math.floor((2 * n) / 3)]) {\n if (pointInRing(outer, inner[k][0], inner[k][1])) votes++;\n }\n return votes >= 2;\n}\n\n/**\n * Resolve rings into `polygon-clipping` polygons (outer ring first, hole\n * rings after) by nesting depth and `fillRule`.\n *\n * Without this a path's own holes are lost: separate polygons in a\n * MultiPolygon are unioned, so a donut arrives at the clipper as a solid disc.\n *\n * Rings that bound no boundary of the filled region — a same-winding ring\n * nested inside a nonzero fill — are dropped; they contribute nothing.\n */\nfunction groupRings(rings: Ring[], fillRule: 'nonzero' | 'evenodd'): MultiPolygon {\n const n = rings.length;\n if (n === 1) return [[rings[0]]];\n\n const boxes = rings.map(ringBox);\n const orient = rings.map((r) => (ringSignedArea(r) >= 0 ? 1 : -1));\n const parent = new Array<number>(n).fill(-1);\n const children: number[][] = rings.map(() => []);\n\n for (let i = 0; i < n; i++) {\n let best = -1;\n let bestArea = Infinity;\n for (let j = 0; j < n; j++) {\n if (i === j) continue;\n if (!ringContains(rings[j], boxes[j], rings[i], boxes[i])) continue;\n const area = (boxes[j][2] - boxes[j][0]) * (boxes[j][3] - boxes[j][1]);\n if (area < bestArea) { bestArea = area; best = j; }\n }\n parent[i] = best;\n }\n for (let i = 0; i < n; i++) if (parent[i] >= 0) children[parent[i]].push(i);\n\n const filled = new Array<boolean>(n);\n for (let i = 0; i < n; i++) {\n let depth = 0;\n let winding = 0;\n for (let a: number = i; a >= 0; a = parent[a]) {\n winding += orient[a];\n if (a !== i) depth++;\n }\n filled[i] = fillRule === 'evenodd' ? depth % 2 === 0 : winding !== 0;\n }\n\n const out: MultiPolygon = [];\n for (let i = 0; i < n; i++) {\n if (!filled[i]) continue;\n if (parent[i] >= 0 && filled[parent[i]]) continue;\n const polygon: Polygon = [rings[i]];\n const queue = [...children[i]];\n while (queue.length > 0) {\n const c = queue.pop() as number;\n // An unfilled child bounds a hole; a filled one merges into this\n // region, so its own children are what may punch holes in it.\n if (filled[c]) queue.push(...children[c]);\n else polygon.push(rings[c]);\n }\n out.push(polygon);\n }\n return out;\n}\n\n/** Convert a `MultiPolygon` to a polygon path with `fillRule: 'nonzero'`. */\nexport function multiPolygonToPath(mp: MultiPolygon): GeomPolygonPath {\n // First pass: count total commands and coord floats.\n let nCmds = 0;\n let nCoords = 0;\n for (const poly of mp) {\n for (const ring of poly) {\n if (ring.length < 4) continue; // 3 unique + 1 closing minimum\n // Drop the repeated closing vertex; emit M + (n-2) L + Z.\n const unique = ring.length - 1;\n nCmds += 1 + (unique - 1) + 1; // M + L*(unique-1) + Z\n nCoords += unique * 2;\n }\n }\n const commands = new Uint8Array(nCmds);\n const coords = new Float32Array(nCoords);\n let ci = 0;\n let pi = 0;\n for (const poly of mp) {\n for (const ring of poly) {\n if (ring.length < 4) continue;\n const unique = ring.length - 1;\n // M (first vertex)\n commands[ci++] = PATH_M;\n coords[pi++] = ring[0][0];\n coords[pi++] = ring[0][1];\n // L for vertices 1..unique-1\n for (let k = 1; k < unique; k++) {\n commands[ci++] = PATH_L;\n coords[pi++] = ring[k][0];\n coords[pi++] = ring[k][1];\n }\n // Z\n commands[ci++] = PATH_Z;\n }\n }\n return { kind: 'polygon', commands, coords, fillRule: 'nonzero' };\n}\n","/**\n * Polygon-boolean operations on `GeomPath` values, backed by\n * `polygon-clipping`. Ported from `src/features/paths/booleans.ts`.\n *\n * v1 limitations (documented; see design doc):\n * - Bezier inputs are flattened to straight-line segments before clipping.\n * The result therefore contains only M/L/Z commands.\n * - Open contours are treated as closed for boolean purposes (a polyline\n * has zero area and would otherwise be silently dropped).\n * - Output `fillRule` is always `'nonzero'`. The engine emits canonical\n * non-overlapping rings, so the choice is cosmetic on its output.\n *\n * This is the ONLY geom module that depends on `polygon-clipping`; it lives in\n * the `@weasel-js/geom/booleans` subpath so the core stays `deps: {}`.\n */\nimport polygonClipping from 'polygon-clipping';\nimport { pathToMultiPolygon, multiPolygonToPath, type GeomPath, type GeomPolygonPath } from './adapter';\n\nexport { pathToMultiPolygon, multiPolygonToPath } from './adapter';\nexport type {\n GeomPath, GeomPolygonPath, Pair, Ring, Polygon, MultiPolygon,\n PathToMultiPolygonOptions,\n} from './adapter';\n\n/** Union of N paths. Commutative. Returns an empty path if all inputs are empty. */\nexport function pathUnion(...paths: GeomPath[]): GeomPolygonPath {\n if (paths.length === 0) return multiPolygonToPath([]);\n const mps = paths.map((p) => pathToMultiPolygon(p));\n const [head, ...rest] = mps;\n return multiPolygonToPath(polygonClipping.union(head, ...rest));\n}\n\n/** Intersection of N paths. Commutative. Empty result is an empty path. */\nexport function pathIntersect(...paths: GeomPath[]): GeomPolygonPath {\n if (paths.length === 0) return multiPolygonToPath([]);\n const mps = paths.map((p) => pathToMultiPolygon(p));\n const [head, ...rest] = mps;\n return multiPolygonToPath(polygonClipping.intersection(head, ...rest));\n}\n\n/** Asymmetric difference: returns `a − b`. */\nexport function pathSubtract(a: GeomPath, b: GeomPath): GeomPolygonPath {\n return multiPolygonToPath(polygonClipping.difference(pathToMultiPolygon(a), pathToMultiPolygon(b)));\n}\n\n/** Symmetric difference (XOR) of N paths. Commutative. */\nexport function pathExclude(...paths: GeomPath[]): GeomPolygonPath {\n if (paths.length === 0) return multiPolygonToPath([]);\n const mps = paths.map((p) => pathToMultiPolygon(p));\n const [head, ...rest] = mps;\n return multiPolygonToPath(polygonClipping.xor(head, ...rest));\n}\n\n/**\n * Fracture N paths along every intersection into the maximal set of\n * non-overlapping regions. Returns one polygon path per region.\n *\n * Algorithm: for every non-empty subset S ⊆ {A1..AN}, emit the region\n * `(∩ S) − (∪ complement)` — points covered by exactly the members of S\n * and no others. By construction the emitted regions are pairwise disjoint\n * and their union equals `pathUnion(A1..AN)`.\n *\n * For N=2 this collapses to the three Illustrator \"Divide\" outputs\n * (A−B, B−A, A∩B). For N=3 up to 7 regions are emitted. The 2^N − 1\n * subset count limits this to small N in practice; passing more than ~8\n * inputs is a misuse — the polygon-clipping kernel dominates anyway.\n */\nexport function pathDivide(...paths: GeomPath[]): GeomPolygonPath[] {\n if (paths.length === 0) return [];\n if (paths.length === 1) {\n return [multiPolygonToPath(pathToMultiPolygon(paths[0]))];\n }\n const mps = paths.map((p) => pathToMultiPolygon(p));\n const n = mps.length;\n const out: GeomPolygonPath[] = [];\n\n // Iterate every non-empty subset via bitmask. Emit subsets in size-\n // ascending order so the output is stable and reads \"exclusives first,\n // then pairs, then triples, …\" — matches the old N=2 ordering.\n const subsets: number[] = [];\n for (let mask = 1; mask < 1 << n; mask++) subsets.push(mask);\n subsets.sort((a, b) => popcount(a) - popcount(b) || a - b);\n\n for (const mask of subsets) {\n const inside: typeof mps = [];\n const outside: typeof mps = [];\n for (let i = 0; i < n; i++) {\n (mask & (1 << i) ? inside : outside).push(mps[i]);\n }\n const [insideHead, ...insideRest] = inside;\n let region = insideRest.length === 0\n ? insideHead\n : polygonClipping.intersection(insideHead, ...insideRest);\n if (region.length === 0) continue;\n if (outside.length > 0) {\n const [outHead, ...outRest] = outside;\n const outsideUnion = polygonClipping.union(outHead, ...outRest);\n region = polygonClipping.difference(region, outsideUnion);\n if (region.length === 0) continue;\n }\n out.push(multiPolygonToPath(region));\n }\n\n return out;\n}\n\nfunction popcount(n: number): number {\n let c = 0;\n while (n) { n &= n - 1; c++; }\n return c;\n}\n\n/**\n * Clip each non-topmost path to the topmost path (Illustrator \"Crop\").\n * Returns `N - 1` results, one per source-below-top, in input order.\n * Discards the topmost path itself — it acts purely as the clipping mask.\n *\n * Empty results (a source that lies entirely outside the mask) are\n * filtered. With `<2` inputs the result is empty.\n */\nexport function pathCrop(...paths: GeomPath[]): GeomPolygonPath[] {\n if (paths.length < 2) return [];\n const mps = paths.map((p) => pathToMultiPolygon(p));\n const mask = mps[mps.length - 1];\n const out: GeomPolygonPath[] = [];\n for (let i = 0; i < mps.length - 1; i++) {\n const clipped = polygonClipping.intersection(mps[i], mask);\n if (clipped.length > 0) out.push(multiPolygonToPath(clipped));\n }\n return out;\n}\n"]}
@@ -0,0 +1,231 @@
1
+ // src/commands.ts
2
+ var PATH_COMMANDS = {
3
+ /** moveTo — opens a new subpath. */
4
+ M: { code: 0, coords: 2 },
5
+ /** Straight segment from the pen to the next coord pair. */
6
+ L: { code: 1, coords: 2 },
7
+ /** Cubic bezier: two control points then the endpoint. */
8
+ C: { code: 2, coords: 6 },
9
+ /** Quadratic bezier: one control point then the endpoint. */
10
+ Q: { code: 3, coords: 4 },
11
+ /** Close the current subpath back to its start. Consumes no coords and
12
+ * leaves the pen where it is. */
13
+ Z: { code: 4, coords: 0 }
14
+ };
15
+ var PATH_M = PATH_COMMANDS.M.code;
16
+ var PATH_L = PATH_COMMANDS.L.code;
17
+ var PATH_C = PATH_COMMANDS.C.code;
18
+ var PATH_Q = PATH_COMMANDS.Q.code;
19
+ var PATH_Z = PATH_COMMANDS.Z.code;
20
+ var PATH_CMD_LENGTHS = buildCmdLengths();
21
+ function buildCmdLengths() {
22
+ const lengths = [];
23
+ for (const { code, coords } of Object.values(PATH_COMMANDS)) lengths[code] = coords;
24
+ return lengths;
25
+ }
26
+ function pathCommandCoordCount(cmd) {
27
+ return PATH_CMD_LENGTHS[cmd];
28
+ }
29
+ function forEachSegment(commands, coords, visit) {
30
+ let ci = 0;
31
+ let px = 0, py = 0;
32
+ let startX = 0, startY = 0;
33
+ for (let i = 0; i < commands.length; i++) {
34
+ const cmd = commands[i];
35
+ if (visit(cmd, ci, px, py, i) === false) return;
36
+ const len = pathCommandCoordCount(cmd);
37
+ if (len > 0) {
38
+ px = coords[ci + len - 2];
39
+ py = coords[ci + len - 1];
40
+ ci += len;
41
+ if (cmd === PATH_M) {
42
+ startX = px;
43
+ startY = py;
44
+ }
45
+ } else if (cmd === PATH_Z) {
46
+ px = startX;
47
+ py = startY;
48
+ }
49
+ }
50
+ }
51
+
52
+ // src/curve.ts
53
+ function cubicEvalAt(x0, y0, x1, y1, x2, y2, x3, y3, t) {
54
+ const u = 1 - t;
55
+ const a = u * u * u, b = 3 * u * u * t, c = 3 * u * t * t, d = t * t * t;
56
+ return [
57
+ a * x0 + b * x1 + c * x2 + d * x3,
58
+ a * y0 + b * y1 + c * y2 + d * y3
59
+ ];
60
+ }
61
+ function elevateQuadraticToCubic(q0x, q0y, cx, cy, q1x, q1y) {
62
+ return [
63
+ q0x + 2 / 3 * (cx - q0x),
64
+ q0y + 2 / 3 * (cy - q0y),
65
+ q1x + 2 / 3 * (cx - q1x),
66
+ q1y + 2 / 3 * (cy - q1y)
67
+ ];
68
+ }
69
+ function componentExtremaTs(p0, p1, p2, p3) {
70
+ const a = -p0 + 3 * p1 - 3 * p2 + p3;
71
+ const b = 2 * (p0 - 2 * p1 + p2);
72
+ const c = -p0 + p1;
73
+ const ts = [];
74
+ const push = (t) => {
75
+ if (t > 0 && t < 1) ts.push(t);
76
+ };
77
+ if (Math.abs(a) < 1e-12) {
78
+ if (Math.abs(b) > 1e-12) push(-c / b);
79
+ } else {
80
+ const disc = b * b - 4 * a * c;
81
+ if (disc >= 0) {
82
+ const sq = Math.sqrt(disc);
83
+ push((-b + sq) / (2 * a));
84
+ push((-b - sq) / (2 * a));
85
+ }
86
+ }
87
+ return ts;
88
+ }
89
+ function cubicBounds(x0, y0, x1, y1, x2, y2, x3, y3) {
90
+ let minX = Math.min(x0, x3), maxX = Math.max(x0, x3);
91
+ let minY = Math.min(y0, y3), maxY = Math.max(y0, y3);
92
+ for (const t of componentExtremaTs(x0, x1, x2, x3)) {
93
+ const [ex] = cubicEvalAt(x0, y0, x1, y1, x2, y2, x3, y3, t);
94
+ if (ex < minX) minX = ex;
95
+ if (ex > maxX) maxX = ex;
96
+ }
97
+ for (const t of componentExtremaTs(y0, y1, y2, y3)) {
98
+ const [, ey] = cubicEvalAt(x0, y0, x1, y1, x2, y2, x3, y3, t);
99
+ if (ey < minY) minY = ey;
100
+ if (ey > maxY) maxY = ey;
101
+ }
102
+ return [minX, minY, maxX, maxY];
103
+ }
104
+
105
+ // src/flatten.ts
106
+ var DEFAULT_FLATTEN_TOLERANCE = 0.5;
107
+ var MIN_FLATTEN_TOLERANCE = 1e-6;
108
+ var MAX_FLATTEN_DEPTH = 16;
109
+ function usableTolerance(tolerance) {
110
+ return tolerance > 0 ? tolerance : MIN_FLATTEN_TOLERANCE;
111
+ }
112
+ function finite6(a, b, c, d, e, f) {
113
+ return Number.isFinite(a) && Number.isFinite(b) && Number.isFinite(c) && Number.isFinite(d) && Number.isFinite(e) && Number.isFinite(f);
114
+ }
115
+ function finite8(a, b, c, d, e, f, g, h) {
116
+ return finite6(a, b, c, d, e, f) && Number.isFinite(g) && Number.isFinite(h);
117
+ }
118
+ function distPointToLine(px, py, ax, ay, bx, by) {
119
+ const dx = bx - ax;
120
+ const dy = by - ay;
121
+ const len2 = dx * dx + dy * dy;
122
+ if (len2 === 0) {
123
+ const ex = px - ax;
124
+ const ey = py - ay;
125
+ return Math.sqrt(ex * ex + ey * ey);
126
+ }
127
+ const cross = (px - ax) * dy - (py - ay) * dx;
128
+ return Math.abs(cross) / Math.sqrt(len2);
129
+ }
130
+ function flattenCubic(x0, y0, x1, y1, x2, y2, x3, y3, tolerance, out) {
131
+ if (!finite8(x0, y0, x1, y1, x2, y2, x3, y3)) {
132
+ out.push(x3, y3);
133
+ return;
134
+ }
135
+ flattenCubicRec(x0, y0, x1, y1, x2, y2, x3, y3, usableTolerance(tolerance), out, 0);
136
+ }
137
+ function flattenCubicRec(x0, y0, x1, y1, x2, y2, x3, y3, tolerance, out, depth) {
138
+ const d1 = distPointToLine(x1, y1, x0, y0, x3, y3);
139
+ const d2 = distPointToLine(x2, y2, x0, y0, x3, y3);
140
+ if (Math.max(d1, d2) <= tolerance || depth >= MAX_FLATTEN_DEPTH) {
141
+ out.push(x3, y3);
142
+ return;
143
+ }
144
+ const x01 = (x0 + x1) * 0.5, y01 = (y0 + y1) * 0.5;
145
+ const x12 = (x1 + x2) * 0.5, y12 = (y1 + y2) * 0.5;
146
+ const x23 = (x2 + x3) * 0.5, y23 = (y2 + y3) * 0.5;
147
+ const x012 = (x01 + x12) * 0.5, y012 = (y01 + y12) * 0.5;
148
+ const x123 = (x12 + x23) * 0.5, y123 = (y12 + y23) * 0.5;
149
+ const x0123 = (x012 + x123) * 0.5, y0123 = (y012 + y123) * 0.5;
150
+ flattenCubicRec(x0, y0, x01, y01, x012, y012, x0123, y0123, tolerance, out, depth + 1);
151
+ flattenCubicRec(x0123, y0123, x123, y123, x23, y23, x3, y3, tolerance, out, depth + 1);
152
+ }
153
+ function flattenQuadratic(x0, y0, x1, y1, x2, y2, tolerance, out) {
154
+ if (!finite6(x0, y0, x1, y1, x2, y2)) {
155
+ out.push(x2, y2);
156
+ return;
157
+ }
158
+ flattenQuadraticRec(x0, y0, x1, y1, x2, y2, usableTolerance(tolerance), out, 0);
159
+ }
160
+ function flattenQuadraticRec(x0, y0, x1, y1, x2, y2, tolerance, out, depth) {
161
+ const d = distPointToLine(x1, y1, x0, y0, x2, y2);
162
+ if (d <= tolerance || depth >= MAX_FLATTEN_DEPTH) {
163
+ out.push(x2, y2);
164
+ return;
165
+ }
166
+ const x01 = (x0 + x1) * 0.5, y01 = (y0 + y1) * 0.5;
167
+ const x12 = (x1 + x2) * 0.5, y12 = (y1 + y2) * 0.5;
168
+ const x012 = (x01 + x12) * 0.5, y012 = (y01 + y12) * 0.5;
169
+ flattenQuadraticRec(x0, y0, x01, y01, x012, y012, tolerance, out, depth + 1);
170
+ flattenQuadraticRec(x012, y012, x12, y12, x2, y2, tolerance, out, depth + 1);
171
+ }
172
+ function flattenCubicWithArcLen(x0, y0, x1, y1, x2, y2, x3, y3, tolerance, out, arcOut) {
173
+ if (!finite8(x0, y0, x1, y1, x2, y2, x3, y3)) {
174
+ out.push(x3, y3);
175
+ arcOut.push(0);
176
+ return 0;
177
+ }
178
+ return flattenCubicArcRec(x0, y0, x1, y1, x2, y2, x3, y3, usableTolerance(tolerance), out, arcOut, 0, 0);
179
+ }
180
+ function flattenCubicArcRec(x0, y0, x1, y1, x2, y2, x3, y3, tolerance, out, arcOut, accum, depth) {
181
+ const d1 = distPointToLine(x1, y1, x0, y0, x3, y3);
182
+ const d2 = distPointToLine(x2, y2, x0, y0, x3, y3);
183
+ if (Math.max(d1, d2) <= tolerance || depth >= MAX_FLATTEN_DEPTH) {
184
+ const lastX = out.length >= 2 ? out[out.length - 2] : x0;
185
+ const lastY = out.length >= 2 ? out[out.length - 1] : y0;
186
+ const seg = Math.hypot(x3 - lastX, y3 - lastY);
187
+ accum += seg;
188
+ out.push(x3, y3);
189
+ arcOut.push(accum);
190
+ return accum;
191
+ }
192
+ const x01 = (x0 + x1) * 0.5, y01 = (y0 + y1) * 0.5;
193
+ const x12 = (x1 + x2) * 0.5, y12 = (y1 + y2) * 0.5;
194
+ const x23 = (x2 + x3) * 0.5, y23 = (y2 + y3) * 0.5;
195
+ const x012 = (x01 + x12) * 0.5, y012 = (y01 + y12) * 0.5;
196
+ const x123 = (x12 + x23) * 0.5, y123 = (y12 + y23) * 0.5;
197
+ const x0123 = (x012 + x123) * 0.5, y0123 = (y012 + y123) * 0.5;
198
+ accum = flattenCubicArcRec(x0, y0, x01, y01, x012, y012, x0123, y0123, tolerance, out, arcOut, accum, depth + 1);
199
+ accum = flattenCubicArcRec(x0123, y0123, x123, y123, x23, y23, x3, y3, tolerance, out, arcOut, accum, depth + 1);
200
+ return accum;
201
+ }
202
+ function flattenQuadraticWithArcLen(x0, y0, x1, y1, x2, y2, tolerance, out, arcOut) {
203
+ if (!finite6(x0, y0, x1, y1, x2, y2)) {
204
+ out.push(x2, y2);
205
+ arcOut.push(0);
206
+ return 0;
207
+ }
208
+ return flattenQuadraticArcRec(x0, y0, x1, y1, x2, y2, usableTolerance(tolerance), out, arcOut, 0, 0);
209
+ }
210
+ function flattenQuadraticArcRec(x0, y0, x1, y1, x2, y2, tolerance, out, arcOut, accum, depth) {
211
+ const d = distPointToLine(x1, y1, x0, y0, x2, y2);
212
+ if (d <= tolerance || depth >= MAX_FLATTEN_DEPTH) {
213
+ const lastX = out.length >= 2 ? out[out.length - 2] : x0;
214
+ const lastY = out.length >= 2 ? out[out.length - 1] : y0;
215
+ const seg = Math.hypot(x2 - lastX, y2 - lastY);
216
+ accum += seg;
217
+ out.push(x2, y2);
218
+ arcOut.push(accum);
219
+ return accum;
220
+ }
221
+ const x01 = (x0 + x1) * 0.5, y01 = (y0 + y1) * 0.5;
222
+ const x12 = (x1 + x2) * 0.5, y12 = (y1 + y2) * 0.5;
223
+ const x012 = (x01 + x12) * 0.5, y012 = (y01 + y12) * 0.5;
224
+ accum = flattenQuadraticArcRec(x0, y0, x01, y01, x012, y012, tolerance, out, arcOut, accum, depth + 1);
225
+ accum = flattenQuadraticArcRec(x012, y012, x12, y12, x2, y2, tolerance, out, arcOut, accum, depth + 1);
226
+ return accum;
227
+ }
228
+
229
+ export { DEFAULT_FLATTEN_TOLERANCE, PATH_C, PATH_CMD_LENGTHS, PATH_COMMANDS, PATH_L, PATH_M, PATH_Q, PATH_Z, cubicBounds, cubicEvalAt, elevateQuadraticToCubic, flattenCubic, flattenCubicWithArcLen, flattenQuadratic, flattenQuadraticWithArcLen, forEachSegment, pathCommandCoordCount };
230
+ //# sourceMappingURL=chunk-DQ6QRAWP.js.map
231
+ //# sourceMappingURL=chunk-DQ6QRAWP.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/commands.ts","../src/curve.ts","../src/flatten.ts"],"names":[],"mappings":"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","file":"chunk-DQ6QRAWP.js","sourcesContent":["/**\n * SVG-style command-stream encoding — the kit's single declaration of the path\n * opcodes. `Path` in @weasel-js/core wraps this with `kind` + `fillRule`.\n *\n * The codes index a `Uint8Array` command stream whose coords live in a\n * parallel float array, so a code declared anywhere but `PATH_COMMANDS` makes\n * every walker that doesn't know it misread the coord stream from that command\n * on — silently, for every path. Derive, never restate.\n */\n\n/** Opcode table: command code and the float coords it consumes. */\nexport const PATH_COMMANDS = {\n /** moveTo — opens a new subpath. */\n M: { code: 0, coords: 2 },\n /** Straight segment from the pen to the next coord pair. */\n L: { code: 1, coords: 2 },\n /** Cubic bezier: two control points then the endpoint. */\n C: { code: 2, coords: 6 },\n /** Quadratic bezier: one control point then the endpoint. */\n Q: { code: 3, coords: 4 },\n /** Close the current subpath back to its start. Consumes no coords and\n * leaves the pen where it is. */\n Z: { code: 4, coords: 0 },\n} as const;\n\n/** Mnemonic of a declared command (`'M' | 'L' | …`). */\nexport type PathCommandName = keyof typeof PATH_COMMANDS;\n/** Numeric code of a declared command. */\nexport type PathCommandCode = (typeof PATH_COMMANDS)[PathCommandName]['code'];\n\nexport const PATH_M = PATH_COMMANDS.M.code;\nexport const PATH_L = PATH_COMMANDS.L.code;\nexport const PATH_C = PATH_COMMANDS.C.code;\nexport const PATH_Q = PATH_COMMANDS.Q.code;\nexport const PATH_Z = PATH_COMMANDS.Z.code;\n\n/** Float coords consumed by each command, indexed by command code. */\nexport const PATH_CMD_LENGTHS: readonly number[] = buildCmdLengths();\n\nfunction buildCmdLengths(): number[] {\n const lengths: number[] = [];\n for (const { code, coords } of Object.values(PATH_COMMANDS)) lengths[code] = coords;\n return lengths;\n}\n\n/** Float coords consumed by the command with this code. */\nexport function pathCommandCoordCount(cmd: number): number {\n return PATH_CMD_LENGTHS[cmd];\n}\n\n/**\n * Visit each command with its coord offset and the pen position BEFORE the\n * command consumes its coords (the segment start). The callback receives\n * (cmd, coordIndex, penX, penY, commandIndex) and stops the walk by returning\n * `false`. The pen advances to the command's last coord pair afterward; `Z`\n * returns it to the subpath's opening `M`, so a command following a `Z`\n * without an intervening `M` starts where SVG says it does.\n */\nexport function forEachSegment(\n commands: ArrayLike<number>,\n coords: ArrayLike<number>,\n visit: (\n cmd: number,\n coordIndex: number,\n penX: number,\n penY: number,\n commandIndex: number,\n ) => void | boolean,\n): void {\n let ci = 0;\n let px = 0, py = 0;\n let startX = 0, startY = 0;\n for (let i = 0; i < commands.length; i++) {\n const cmd = commands[i];\n if (visit(cmd, ci, px, py, i) === false) return;\n const len = pathCommandCoordCount(cmd);\n if (len > 0) {\n px = coords[ci + len - 2];\n py = coords[ci + len - 1];\n ci += len;\n if (cmd === PATH_M) { startX = px; startY = py; }\n } else if (cmd === PATH_Z) {\n px = startX; py = startY;\n }\n }\n}\n","import type { Box } from './box';\n\n/** Cubic Bezier point at parameter t (de Casteljau / Bernstein form). */\nexport function cubicEvalAt(\n x0: number, y0: number, x1: number, y1: number,\n x2: number, y2: number, x3: number, y3: number, t: number,\n): [number, number] {\n const u = 1 - t;\n const a = u * u * u, b = 3 * u * u * t, c = 3 * u * t * t, d = t * t * t;\n return [\n a * x0 + b * x1 + c * x2 + d * x3,\n a * y0 + b * y1 + c * y2 + d * y3,\n ];\n}\n\n/**\n * Degree-elevate a quadratic (q0, ctrl, q1) to a cubic. Returns the two\n * cubic control points [c1x, c1y, c2x, c2y]; the cubic endpoints equal the\n * quadratic endpoints. c1 = q0 + 2/3(ctrl-q0), c2 = q1 + 2/3(ctrl-q1).\n */\nexport function elevateQuadraticToCubic(\n q0x: number, q0y: number, cx: number, cy: number, q1x: number, q1y: number,\n): [number, number, number, number] {\n return [\n q0x + (2 / 3) * (cx - q0x),\n q0y + (2 / 3) * (cy - q0y),\n q1x + (2 / 3) * (cx - q1x),\n q1y + (2 / 3) * (cy - q1y),\n ];\n}\n\n/** Axis-aligned extrema parameters of one cubic component (the 0,1 ends plus\n * any derivative roots in (0,1)). Used by cubicBounds. */\nfunction componentExtremaTs(p0: number, p1: number, p2: number, p3: number): number[] {\n // B'(t)=0 → quadratic a t² + b t + c = 0 with:\n const a = -p0 + 3 * p1 - 3 * p2 + p3;\n const b = 2 * (p0 - 2 * p1 + p2);\n const c = -p0 + p1;\n const ts: number[] = [];\n const push = (t: number) => { if (t > 0 && t < 1) ts.push(t); };\n if (Math.abs(a) < 1e-12) {\n if (Math.abs(b) > 1e-12) push(-c / b);\n } else {\n const disc = b * b - 4 * a * c;\n if (disc >= 0) {\n const sq = Math.sqrt(disc);\n push((-b + sq) / (2 * a));\n push((-b - sq) / (2 * a));\n }\n }\n return ts;\n}\n\n/** Tight AABB of a cubic, evaluating only extrema that lie on the curve. */\nexport function cubicBounds(\n x0: number, y0: number, x1: number, y1: number,\n x2: number, y2: number, x3: number, y3: number,\n): Box {\n let minX = Math.min(x0, x3), maxX = Math.max(x0, x3);\n let minY = Math.min(y0, y3), maxY = Math.max(y0, y3);\n for (const t of componentExtremaTs(x0, x1, x2, x3)) {\n const [ex] = cubicEvalAt(x0, y0, x1, y1, x2, y2, x3, y3, t);\n if (ex < minX) minX = ex;\n if (ex > maxX) maxX = ex;\n }\n for (const t of componentExtremaTs(y0, y1, y2, y3)) {\n const [, ey] = cubicEvalAt(x0, y0, x1, y1, x2, y2, x3, y3, t);\n if (ey < minY) minY = ey;\n if (ey > maxY) maxY = ey;\n }\n return [minX, minY, maxX, maxY];\n}\n","/**\n * Bezier flattening — subdivide cubic and quadratic segments into polyline\n * approximations within a flatness tolerance. Used by hit-testing and\n * (eventually) any kernel that doesn't want to special-case curves.\n *\n * The flatness metric is the maximum perpendicular distance from any\n * control point to the chord between endpoints. When that distance falls\n * below `tolerance`, the segment is \"flat enough\" and emitted as a single\n * line segment.\n *\n * Tolerance is in world units. 0.5 is a sensible default for screen-rate\n * rendering at 1× zoom; consumers that zoom in heavily should pass a\n * tighter tolerance.\n */\n\nexport const DEFAULT_FLATTEN_TOLERANCE = 0.5;\n\n/** Floor for a non-positive or NaN tolerance. Without it the flatness test can\n * never be satisfied and the subdivision recurses until the stack blows. */\nconst MIN_FLATTEN_TOLERANCE = 1e-6;\n\n/** Subdivision ceiling. The tolerance floor bounds the common runaway; this\n * bounds the other one, coordinates large enough that reaching 1e-6 takes\n * hundreds of levels. Error falls roughly 4x per level, so 16 is far beyond\n * any tolerance a caller can mean. */\nconst MAX_FLATTEN_DEPTH = 16;\n\nfunction usableTolerance(tolerance: number): number {\n return tolerance > 0 ? tolerance : MIN_FLATTEN_TOLERANCE;\n}\n\nfunction finite6(a: number, b: number, c: number, d: number, e: number, f: number): boolean {\n return Number.isFinite(a) && Number.isFinite(b) && Number.isFinite(c)\n && Number.isFinite(d) && Number.isFinite(e) && Number.isFinite(f);\n}\n\nfunction finite8(\n a: number, b: number, c: number, d: number,\n e: number, f: number, g: number, h: number,\n): boolean {\n return finite6(a, b, c, d, e, f) && Number.isFinite(g) && Number.isFinite(h);\n}\n\n/** Distance from point P to line AB (perpendicular). */\nfunction distPointToLine(px: number, py: number, ax: number, ay: number, bx: number, by: number): number {\n const dx = bx - ax;\n const dy = by - ay;\n const len2 = dx * dx + dy * dy;\n if (len2 === 0) {\n const ex = px - ax;\n const ey = py - ay;\n return Math.sqrt(ex * ex + ey * ey);\n }\n const cross = (px - ax) * dy - (py - ay) * dx;\n return Math.abs(cross) / Math.sqrt(len2);\n}\n\n/**\n * Recursively subdivide a cubic bezier (P0..P3) and append `lineTo`-style\n * vertices to `out` (interleaved x,y). The starting endpoint is *not*\n * appended — callers usually emitted it as the segment's previous vertex.\n */\nexport function flattenCubic(\n x0: number, y0: number,\n x1: number, y1: number,\n x2: number, y2: number,\n x3: number, y3: number,\n tolerance: number,\n out: number[],\n): void {\n if (!finite8(x0, y0, x1, y1, x2, y2, x3, y3)) {\n out.push(x3, y3);\n return;\n }\n flattenCubicRec(x0, y0, x1, y1, x2, y2, x3, y3, usableTolerance(tolerance), out, 0);\n}\n\nfunction flattenCubicRec(\n x0: number, y0: number,\n x1: number, y1: number,\n x2: number, y2: number,\n x3: number, y3: number,\n tolerance: number,\n out: number[],\n depth: number,\n): void {\n const d1 = distPointToLine(x1, y1, x0, y0, x3, y3);\n const d2 = distPointToLine(x2, y2, x0, y0, x3, y3);\n if (Math.max(d1, d2) <= tolerance || depth >= MAX_FLATTEN_DEPTH) {\n out.push(x3, y3);\n return;\n }\n // De Casteljau split at t=0.5\n const x01 = (x0 + x1) * 0.5, y01 = (y0 + y1) * 0.5;\n const x12 = (x1 + x2) * 0.5, y12 = (y1 + y2) * 0.5;\n const x23 = (x2 + x3) * 0.5, y23 = (y2 + y3) * 0.5;\n const x012 = (x01 + x12) * 0.5, y012 = (y01 + y12) * 0.5;\n const x123 = (x12 + x23) * 0.5, y123 = (y12 + y23) * 0.5;\n const x0123 = (x012 + x123) * 0.5, y0123 = (y012 + y123) * 0.5;\n flattenCubicRec(x0, y0, x01, y01, x012, y012, x0123, y0123, tolerance, out, depth + 1);\n flattenCubicRec(x0123, y0123, x123, y123, x23, y23, x3, y3, tolerance, out, depth + 1);\n}\n\n/** Recursively subdivide a quadratic bezier (P0, P1, P2). */\nexport function flattenQuadratic(\n x0: number, y0: number,\n x1: number, y1: number,\n x2: number, y2: number,\n tolerance: number,\n out: number[],\n): void {\n if (!finite6(x0, y0, x1, y1, x2, y2)) {\n out.push(x2, y2);\n return;\n }\n flattenQuadraticRec(x0, y0, x1, y1, x2, y2, usableTolerance(tolerance), out, 0);\n}\n\nfunction flattenQuadraticRec(\n x0: number, y0: number,\n x1: number, y1: number,\n x2: number, y2: number,\n tolerance: number,\n out: number[],\n depth: number,\n): void {\n const d = distPointToLine(x1, y1, x0, y0, x2, y2);\n if (d <= tolerance || depth >= MAX_FLATTEN_DEPTH) {\n out.push(x2, y2);\n return;\n }\n const x01 = (x0 + x1) * 0.5, y01 = (y0 + y1) * 0.5;\n const x12 = (x1 + x2) * 0.5, y12 = (y1 + y2) * 0.5;\n const x012 = (x01 + x12) * 0.5, y012 = (y01 + y12) * 0.5;\n flattenQuadraticRec(x0, y0, x01, y01, x012, y012, tolerance, out, depth + 1);\n flattenQuadraticRec(x012, y012, x12, y12, x2, y2, tolerance, out, depth + 1);\n}\n\n/**\n * Like `flattenCubic` but also appends, for each new flattened point, its\n * arc-length fraction `t` (relative to the polyline distance accumulated so\n * far inside this curve) to `arcOut`. Caller then post-processes the segment's\n * `arcOut` range by dividing each by the segment's total flattened arc length\n * to yield t ∈ (0, 1].\n *\n * The returned values are *cumulative distance from the segment start*, not\n * normalized fractions. Two-pass design (accumulate, then divide) keeps the\n * recursive splitter simple — it doesn't need to know the total length up\n * front.\n */\nexport function flattenCubicWithArcLen(\n x0: number, y0: number,\n x1: number, y1: number,\n x2: number, y2: number,\n x3: number, y3: number,\n tolerance: number,\n out: number[],\n arcOut: number[],\n): number {\n if (!finite8(x0, y0, x1, y1, x2, y2, x3, y3)) {\n out.push(x3, y3);\n arcOut.push(0);\n return 0;\n }\n return flattenCubicArcRec(x0, y0, x1, y1, x2, y2, x3, y3, usableTolerance(tolerance), out, arcOut, 0, 0);\n}\n\nfunction flattenCubicArcRec(\n x0: number, y0: number,\n x1: number, y1: number,\n x2: number, y2: number,\n x3: number, y3: number,\n tolerance: number,\n out: number[],\n arcOut: number[],\n accum: number,\n depth: number,\n): number {\n const d1 = distPointToLine(x1, y1, x0, y0, x3, y3);\n const d2 = distPointToLine(x2, y2, x0, y0, x3, y3);\n if (Math.max(d1, d2) <= tolerance || depth >= MAX_FLATTEN_DEPTH) {\n const lastX = out.length >= 2 ? out[out.length - 2] : x0;\n const lastY = out.length >= 2 ? out[out.length - 1] : y0;\n const seg = Math.hypot(x3 - lastX, y3 - lastY);\n accum += seg;\n out.push(x3, y3);\n arcOut.push(accum);\n return accum;\n }\n const x01 = (x0 + x1) * 0.5, y01 = (y0 + y1) * 0.5;\n const x12 = (x1 + x2) * 0.5, y12 = (y1 + y2) * 0.5;\n const x23 = (x2 + x3) * 0.5, y23 = (y2 + y3) * 0.5;\n const x012 = (x01 + x12) * 0.5, y012 = (y01 + y12) * 0.5;\n const x123 = (x12 + x23) * 0.5, y123 = (y12 + y23) * 0.5;\n const x0123 = (x012 + x123) * 0.5, y0123 = (y012 + y123) * 0.5;\n accum = flattenCubicArcRec(x0, y0, x01, y01, x012, y012, x0123, y0123, tolerance, out, arcOut, accum, depth + 1);\n accum = flattenCubicArcRec(x0123, y0123, x123, y123, x23, y23, x3, y3, tolerance, out, arcOut, accum, depth + 1);\n return accum;\n}\n\n/** Flatten a quadratic bezier into line segments within `tolerance`, appending\n * points to `out` and their cumulative arc lengths to `arcOut`. The arc\n * lengths are what lets per-anchor color and dash phase be interpolated\n * evenly along the curve rather than per segment. */\nexport function flattenQuadraticWithArcLen(\n x0: number, y0: number,\n x1: number, y1: number,\n x2: number, y2: number,\n tolerance: number,\n out: number[],\n arcOut: number[],\n): number {\n if (!finite6(x0, y0, x1, y1, x2, y2)) {\n out.push(x2, y2);\n arcOut.push(0);\n return 0;\n }\n return flattenQuadraticArcRec(x0, y0, x1, y1, x2, y2, usableTolerance(tolerance), out, arcOut, 0, 0);\n}\n\nfunction flattenQuadraticArcRec(\n x0: number, y0: number,\n x1: number, y1: number,\n x2: number, y2: number,\n tolerance: number,\n out: number[],\n arcOut: number[],\n accum: number,\n depth: number,\n): number {\n const d = distPointToLine(x1, y1, x0, y0, x2, y2);\n if (d <= tolerance || depth >= MAX_FLATTEN_DEPTH) {\n const lastX = out.length >= 2 ? out[out.length - 2] : x0;\n const lastY = out.length >= 2 ? out[out.length - 1] : y0;\n const seg = Math.hypot(x2 - lastX, y2 - lastY);\n accum += seg;\n out.push(x2, y2);\n arcOut.push(accum);\n return accum;\n }\n const x01 = (x0 + x1) * 0.5, y01 = (y0 + y1) * 0.5;\n const x12 = (x1 + x2) * 0.5, y12 = (y1 + y2) * 0.5;\n const x012 = (x01 + x12) * 0.5, y012 = (y01 + y12) * 0.5;\n accum = flattenQuadraticArcRec(x0, y0, x01, y01, x012, y012, tolerance, out, arcOut, accum, depth + 1);\n accum = flattenQuadraticArcRec(x012, y012, x12, y12, x2, y2, tolerance, out, arcOut, accum, depth + 1);\n return accum;\n}\n\n"]}
@@ -0,0 +1,29 @@
1
+ // src/scalar.ts
2
+ var EPS = 1e-6;
3
+ var SINGULAR_RATIO = 1e-12;
4
+ function cross(ax, ay, bx, by) {
5
+ return ax * by - ay * bx;
6
+ }
7
+ function dot(ax, ay, bx, by) {
8
+ return ax * bx + ay * by;
9
+ }
10
+ function sub(ax, ay, bx, by) {
11
+ return [ax - bx, ay - by];
12
+ }
13
+ function len2(x, y) {
14
+ return x * x + y * y;
15
+ }
16
+ function sign(n) {
17
+ return n > 0 ? 1 : n < 0 ? -1 : 0;
18
+ }
19
+ function approxEq(a, b, eps = EPS) {
20
+ if (a === b) return true;
21
+ const diff = Math.abs(a - b);
22
+ if (!Number.isFinite(diff)) return false;
23
+ const scale = Math.max(1, Math.abs(a), Math.abs(b));
24
+ return diff <= eps * scale;
25
+ }
26
+
27
+ export { EPS, SINGULAR_RATIO, approxEq, cross, dot, len2, sign, sub };
28
+ //# sourceMappingURL=chunk-NHMWNQTE.js.map
29
+ //# sourceMappingURL=chunk-NHMWNQTE.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/scalar.ts"],"names":[],"mappings":";AAUO,IAAM,GAAA,GAAM;AAKZ,IAAM,cAAA,GAAiB;AAGvB,SAAS,KAAA,CAAM,EAAA,EAAY,EAAA,EAAY,EAAA,EAAY,EAAA,EAAoB;AAC5E,EAAA,OAAO,EAAA,GAAK,KAAK,EAAA,GAAK,EAAA;AACxB;AAGO,SAAS,GAAA,CAAI,EAAA,EAAY,EAAA,EAAY,EAAA,EAAY,EAAA,EAAoB;AAC1E,EAAA,OAAO,EAAA,GAAK,KAAK,EAAA,GAAK,EAAA;AACxB;AAGO,SAAS,GAAA,CAAI,EAAA,EAAY,EAAA,EAAY,EAAA,EAAY,EAAA,EAA8B;AACpF,EAAA,OAAO,CAAC,EAAA,GAAK,EAAA,EAAI,EAAA,GAAK,EAAE,CAAA;AAC1B;AAGO,SAAS,IAAA,CAAK,GAAW,CAAA,EAAmB;AACjD,EAAA,OAAO,CAAA,GAAI,IAAI,CAAA,GAAI,CAAA;AACrB;AAGO,SAAS,KAAK,CAAA,EAAuB;AAC1C,EAAA,OAAO,CAAA,GAAI,CAAA,GAAI,CAAA,GAAI,CAAA,GAAI,IAAI,EAAA,GAAK,CAAA;AAClC;AAQO,SAAS,QAAA,CAAS,CAAA,EAAW,CAAA,EAAW,GAAA,GAAc,GAAA,EAAc;AACzE,EAAA,IAAI,CAAA,KAAM,GAAG,OAAO,IAAA;AACpB,EAAA,MAAM,IAAA,GAAO,IAAA,CAAK,GAAA,CAAI,CAAA,GAAI,CAAC,CAAA;AAG3B,EAAA,IAAI,CAAC,MAAA,CAAO,QAAA,CAAS,IAAI,GAAG,OAAO,KAAA;AACnC,EAAA,MAAM,KAAA,GAAQ,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,EAAG,IAAA,CAAK,GAAA,CAAI,CAAC,CAAC,CAAA;AAClD,EAAA,OAAO,QAAQ,GAAA,GAAM,KAAA;AACvB","file":"chunk-NHMWNQTE.js","sourcesContent":["/**\n * Scalar / 2-vector primitives and the kernel-wide epsilon policy.\n *\n * Points are scalar pairs (px, py); there is no point struct. All math is\n * f64 (JS-native). Epsilons are f32-SCALE and magnitude-relative, because\n * stored coords are quantized to Float32 (~7 significant digits) — see the\n * geometry-kernel spec.\n */\n\n/** Base relative epsilon, sized for Float32 storage (~1 part in 1e-6). */\nexport const EPS = 1e-6;\n\n/** A determinant at or below this fraction of its matrix's own scale counts as\n * singular. Dimensionless, so a uniformly tiny matrix still inverts while a\n * large one whose determinant is only rounding does not. */\nexport const SINGULAR_RATIO = 1e-12;\n\n/** 2D cross (wedge) product of vectors (ax,ay) and (bx,by). */\nexport function cross(ax: number, ay: number, bx: number, by: number): number {\n return ax * by - ay * bx;\n}\n\n/** 2D dot product. */\nexport function dot(ax: number, ay: number, bx: number, by: number): number {\n return ax * bx + ay * by;\n}\n\n/** Component difference (ax-bx, ay-by) as a tuple. Cold-path use only. */\nexport function sub(ax: number, ay: number, bx: number, by: number): [number, number] {\n return [ax - bx, ay - by];\n}\n\n/** Squared length of (x,y). Avoids the sqrt; compare against squared thresholds. */\nexport function len2(x: number, y: number): number {\n return x * x + y * y;\n}\n\n/** Three-valued sign. */\nexport function sign(n: number): -1 | 0 | 1 {\n return n > 0 ? 1 : n < 0 ? -1 : 0;\n}\n\n/**\n * Magnitude-scaled approximate equality. Two values are equal when their\n * absolute difference is within EPS scaled by the larger magnitude. This is\n * the ONLY equality the kernel uses on computed coordinates — never `===`,\n * never an f64-tight literal.\n */\nexport function approxEq(a: number, b: number, eps: number = EPS): boolean {\n if (a === b) return true; // also the only way two infinities compare equal\n const diff = Math.abs(a - b);\n // Infinity/Infinity is 1, so an unguarded relative test calls every finite\n // number equal to an infinity.\n if (!Number.isFinite(diff)) return false;\n const scale = Math.max(1, Math.abs(a), Math.abs(b));\n return diff <= eps * scale;\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -26,21 +26,6 @@ declare function sign(n: number): -1 | 0 | 1;
26
26
  */
27
27
  declare function approxEq(a: number, b: number, eps?: number): boolean;
28
28
 
29
- /**
30
- * 2D affine transforms in canvas/DOMMatrix order: [a, b, c, d, e, f].
31
- * x' = a·x + c·y + e
32
- * y' = b·x + d·y + f
33
- * Represented as a 6-element number[] (f64). The affine tier of the kernel.
34
- *
35
- * Convention alignment: the renderer already has a `Mat3` in
36
- * `src/renderer/math/mat3.ts`. That one is a 9-element column-major
37
- * `Float32Array` (a full 3×3) shaped for `uniformMatrix3fv` — a deliberately
38
- * different *representation* for the WebGL upload path. Its *logical element
39
- * order* is identical to ours: `create(a, b, c, d, tx, ty)` maps
40
- * `x' = a·x + c·y + tx`, `y' = b·x + d·y + ty` (canvas/DOMMatrix a,b,c,d,e,f).
41
- * We keep the pure 6-tuple f64 form here (the kernel form); the 9-element f32
42
- * form stays a render-layer concern. No second logical convention is created.
43
- */
44
29
  type Mat3 = number[];
45
30
  /** The transform that leaves a point where it is. */
46
31
  declare function identity(): Mat3;
@@ -80,7 +65,10 @@ declare function boundsOfCoords(coords: ArrayLike<number>): Box | null;
80
65
  declare function unionBox(a: Box, b: Box): Box;
81
66
  /** Inclusive point-in-box test. */
82
67
  declare function boxContainsPoint(b: Box, x: number, y: number): boolean;
83
- /** Closed interleaved ring (first vertex repeated) for a rect at (x,y,w,h). */
68
+ /** Interleaved corner ring for a rect at (x,y,w,h), wound clockwise from the
69
+ * origin corner. The closing edge is implicit — the same unclosed shape
70
+ * `pointInPolygon` takes, and what a repeated first vertex would leave as a
71
+ * zero-length segment for anything that strokes it. */
84
72
  declare function rectToContour(x: number, y: number, w: number, h: number): Float64Array;
85
73
 
86
74
  /**
@@ -137,10 +125,12 @@ declare function pathCommandCoordCount(cmd: number): number;
137
125
  /**
138
126
  * Visit each command with its coord offset and the pen position BEFORE the
139
127
  * command consumes its coords (the segment start). The callback receives
140
- * (cmd, coordIndex, penX, penY). The pen advances to the command's last
141
- * coord pair afterward (Z leaves the pen unchanged).
128
+ * (cmd, coordIndex, penX, penY, commandIndex) and stops the walk by returning
129
+ * `false`. The pen advances to the command's last coord pair afterward; `Z`
130
+ * returns it to the subpath's opening `M`, so a command following a `Z`
131
+ * without an intervening `M` starts where SVG says it does.
142
132
  */
143
- declare function forEachSegment(commands: ArrayLike<number>, coords: ArrayLike<number>, visit: (cmd: number, coordIndex: number, penX: number, penY: number) => void): void;
133
+ declare function forEachSegment(commands: ArrayLike<number>, coords: ArrayLike<number>, visit: (cmd: number, coordIndex: number, penX: number, penY: number, commandIndex: number) => void | boolean): void;
144
134
 
145
135
  /** Cubic Bezier point at parameter t (de Casteljau / Bernstein form). */
146
136
  declare function cubicEvalAt(x0: number, y0: number, x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, t: number): [number, number];
@@ -150,24 +140,59 @@ declare function cubicEvalAt(x0: number, y0: number, x1: number, y1: number, x2:
150
140
  * quadratic endpoints. c1 = q0 + 2/3(ctrl-q0), c2 = q1 + 2/3(ctrl-q1).
151
141
  */
152
142
  declare function elevateQuadraticToCubic(q0x: number, q0y: number, cx: number, cy: number, q1x: number, q1y: number): [number, number, number, number];
143
+ /** Tight AABB of a cubic, evaluating only extrema that lie on the curve. */
144
+ declare function cubicBounds(x0: number, y0: number, x1: number, y1: number, x2: number, y2: number, x3: number, y3: number): Box;
145
+
153
146
  /**
154
- * Adaptive flatten of a cubic into interleaved points appended to `out`
155
- * (excludes the start point, includes the endpoint).
147
+ * Bezier flattening — subdivide cubic and quadratic segments into polyline
148
+ * approximations within a flatness tolerance. Used by hit-testing and
149
+ * (eventually) any kernel that doesn't want to special-case curves.
156
150
  *
157
- * Always terminates: a non-finite coordinate makes the flatness test
158
- * unsatisfiable and `tolerance <= 0` makes it unreachable, so subdivision is
159
- * capped at {@link MAX_FLATTEN_DEPTH}.
151
+ * The flatness metric is the maximum perpendicular distance from any
152
+ * control point to the chord between endpoints. When that distance falls
153
+ * below `tolerance`, the segment is "flat enough" and emitted as a single
154
+ * line segment.
155
+ *
156
+ * Tolerance is in world units. 0.5 is a sensible default for screen-rate
157
+ * rendering at 1× zoom; consumers that zoom in heavily should pass a
158
+ * tighter tolerance.
159
+ */
160
+ declare const DEFAULT_FLATTEN_TOLERANCE = 0.5;
161
+ /**
162
+ * Recursively subdivide a cubic bezier (P0..P3) and append `lineTo`-style
163
+ * vertices to `out` (interleaved x,y). The starting endpoint is *not*
164
+ * appended — callers usually emitted it as the segment's previous vertex.
160
165
  */
161
166
  declare function flattenCubic(x0: number, y0: number, x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, tolerance: number, out: number[]): void;
162
- /** Tight AABB of a cubic, evaluating only extrema that lie on the curve. */
163
- declare function cubicBounds(x0: number, y0: number, x1: number, y1: number, x2: number, y2: number, x3: number, y3: number): Box;
167
+ /** Recursively subdivide a quadratic bezier (P0, P1, P2). */
168
+ declare function flattenQuadratic(x0: number, y0: number, x1: number, y1: number, x2: number, y2: number, tolerance: number, out: number[]): void;
169
+ /**
170
+ * Like `flattenCubic` but also appends, for each new flattened point, its
171
+ * arc-length fraction `t` (relative to the polyline distance accumulated so
172
+ * far inside this curve) to `arcOut`. Caller then post-processes the segment's
173
+ * `arcOut` range by dividing each by the segment's total flattened arc length
174
+ * to yield t ∈ (0, 1].
175
+ *
176
+ * The returned values are *cumulative distance from the segment start*, not
177
+ * normalized fractions. Two-pass design (accumulate, then divide) keeps the
178
+ * recursive splitter simple — it doesn't need to know the total length up
179
+ * front.
180
+ */
181
+ declare function flattenCubicWithArcLen(x0: number, y0: number, x1: number, y1: number, x2: number, y2: number, x3: number, y3: number, tolerance: number, out: number[], arcOut: number[]): number;
182
+ /** Flatten a quadratic bezier into line segments within `tolerance`, appending
183
+ * points to `out` and their cumulative arc lengths to `arcOut`. The arc
184
+ * lengths are what lets per-anchor color and dash phase be interpolated
185
+ * evenly along the curve rather than per segment. */
186
+ declare function flattenQuadraticWithArcLen(x0: number, y0: number, x1: number, y1: number, x2: number, y2: number, tolerance: number, out: number[], arcOut: number[]): number;
164
187
 
165
188
  /**
166
189
  * Even-odd ray-cast point-in-polygon over an interleaved, unclosed contour
167
- * [x0,y0,x1,y1,…]. The closing edge (last→first) is implicit. Flat rewrite of
168
- * features/paths/polygonHitTestRect.ts pointInPolygon — same algorithm.
190
+ * [x0,y0,x1,y1,…]. The closing edge (last→first) is implicit.
191
+ *
192
+ * `start`/`end` are vertex indices, not float offsets, and bound one contour
193
+ * inside a buffer holding several.
169
194
  */
170
- declare function pointInPolygon(coords: ArrayLike<number>, px: number, py: number): boolean;
195
+ declare function pointInPolygon(coords: ArrayLike<number>, px: number, py: number, start?: number, end?: number): boolean;
171
196
  /**
172
197
  * True if segments (ax,ay)-(bx,by) and (cx,cy)-(dx,dy) intersect at a single
173
198
  * point. An endpoint landing on the other segment counts (a T-junction and a
@@ -226,4 +251,4 @@ interface PlacedRect {
226
251
  declare function clampRectWithin(rect: Rect, boundary: Rect, padding?: number): Rect;
227
252
  declare function placeRect(options: PlaceRectOptions): PlacedRect;
228
253
 
229
- export { type Box, EPS, type Mat3, PATH_C, PATH_CMD_LENGTHS, PATH_COMMANDS, PATH_L, PATH_M, PATH_Q, PATH_Z, type PathCommandCode, type PathCommandName, type PlaceRectOptions, type PlacedRect, type Placement, type PlacementAlign, type PlacementSide, type Rect, applyToPoint, approxEq, boundsOfCoords, boxContainsPoint, boxToBox, clampRectWithin, cross, cubicBounds, cubicEvalAt, dot, elevateQuadraticToCubic, flattenCubic, forEachSegment, identity, invert, len2, multiply, pathCommandCoordCount, placeRect, pointInPolygon, pointSegmentDist2, rectToContour, rotate, rotateAboutPoint, scale, segmentsCross, sign, sub, transformCoords, translate, unionBox };
254
+ export { type Box, DEFAULT_FLATTEN_TOLERANCE, EPS, type Mat3, PATH_C, PATH_CMD_LENGTHS, PATH_COMMANDS, PATH_L, PATH_M, PATH_Q, PATH_Z, type PathCommandCode, type PathCommandName, type PlaceRectOptions, type PlacedRect, type Placement, type PlacementAlign, type PlacementSide, type Rect, applyToPoint, approxEq, boundsOfCoords, boxContainsPoint, boxToBox, clampRectWithin, cross, cubicBounds, cubicEvalAt, dot, elevateQuadraticToCubic, flattenCubic, flattenCubicWithArcLen, flattenQuadratic, flattenQuadraticWithArcLen, forEachSegment, identity, invert, len2, multiply, pathCommandCoordCount, placeRect, pointInPolygon, pointSegmentDist2, rectToContour, rotate, rotateAboutPoint, scale, segmentsCross, sign, sub, transformCoords, translate, unionBox };