@weasel-js/geom 1.9.3 → 1.9.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.
@@ -1,8 +1,8 @@
1
- import { rectToContour } from '../chunk-6T5I3PR5.js';
2
- export { extractPolylines } from '../chunk-6T5I3PR5.js';
3
- import { DEFAULT_FLATTEN_TOLERANCE, pointInPolygon, flattenCubicWithArcLen, flattenQuadraticWithArcLen } from '../chunk-RQYCDPU5.js';
4
- import '../chunk-7ROQRYOA.js';
5
- import { forEachSegment, PATH_Z, PATH_C, PATH_Q, PATH_L, PATH_M } from '../chunk-HEZTRG2M.js';
1
+ import { rectToContour } from '../chunk-NL423YYZ.js';
2
+ export { extractPolylines } from '../chunk-NL423YYZ.js';
3
+ import { DEFAULT_FLATTEN_TOLERANCE, pointInPolygon, flattenCubicWithArcLen, flattenQuadraticWithArcLen } from '../chunk-X6GJRIQD.js';
4
+ import '../chunk-N5SYTHMR.js';
5
+ import { forEachSegment, PATH_Z, PATH_C, PATH_Q, PATH_L, PATH_M } from '../chunk-E4TJRGJD.js';
6
6
  import earcut from 'earcut';
7
7
 
8
8
  function tessellate(path, opts = {}) {
@@ -40,7 +40,16 @@ function flattenPolygon(p, tolerance) {
40
40
  anchorB[lastIdx] = target;
41
41
  anchorT[lastIdx] = 0;
42
42
  };
43
- forEachSegment(commands, coords, (cmd, coordIdx, prevX, prevY) => {
43
+ forEachSegment(commands, coords, (cmd, coordIdx, prevX, prevY, _i, opensSubpath) => {
44
+ if (opensSubpath) {
45
+ const anchor = Math.max(startAnchor, 0);
46
+ contourStarts.push(out.length / 2);
47
+ out.push(prevX, prevY);
48
+ anchorA.push(anchor);
49
+ anchorB.push(anchor);
50
+ anchorT.push(0);
51
+ prevAnchor = anchor;
52
+ }
44
53
  switch (cmd) {
45
54
  case PATH_M:
46
55
  case PATH_L: {
@@ -235,10 +244,10 @@ function signedArea(coords, start, end) {
235
244
 
236
245
  // src/tessellate/trim.ts
237
246
  var EPS = 1e-9;
238
- function sampleAt(pl, cum, A, B, T, W, dist) {
247
+ function sampleAt(pl, cum, A, B, T, W, dist, vertexFollows) {
239
248
  const n = cum.length;
240
249
  let i = 1;
241
- while (i < n - 1 && cum[i] < dist) i++;
250
+ while (i < n - 1 && (vertexFollows ? cum[i] <= dist : cum[i] < dist)) i++;
242
251
  const segStart = cum[i - 1];
243
252
  const segLen = cum[i] - segStart;
244
253
  const f = segLen > EPS ? (dist - segStart) / segLen : 0;
@@ -282,8 +291,8 @@ function trimPolyline(pl, startInset, endInset) {
282
291
  const cutA = from;
283
292
  const cutB = total - to;
284
293
  if (cutB - cutA <= EPS) return null;
285
- const head = sampleAt(pl, cum, A, B, T, W, cutA);
286
- const tail = sampleAt(pl, cum, A, B, T, W, cutB);
294
+ const head = sampleAt(pl, cum, A, B, T, W, cutA, true);
295
+ const tail = sampleAt(pl, cum, A, B, T, W, cutB, false);
287
296
  const points = [head.x, head.y];
288
297
  const aOut = [head.a];
289
298
  const bOut = [head.b];
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/tessellate/tessellate.ts","../../src/tessellate/trim.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import earcut from 'earcut';\nimport { forEachSegment, PATH_M, PATH_L, PATH_Z, PATH_C, PATH_Q } from '../commands';\nimport { pointInPolygon } from '../polyline';\nimport { rectToContour } from '../box';\nimport type { Path, PolygonPath, RectPath } from '../path';\nimport {\n DEFAULT_FLATTEN_TOLERANCE,\n flattenCubicWithArcLen,\n flattenQuadraticWithArcLen,\n} from '../flatten';\nimport type { Mesh } from './mesh';\n\n/** Options for `tessellate`. A smaller tolerance means more triangles and\n * smoother curves; it is in path-local units, so callers rendering at a\n * larger scale should tighten it. */\nexport interface TessellateOptions {\n /** Flatness tolerance for bezier subdivision in path-local units. */\n flattenTolerance?: number;\n}\n\n/** Turn a path into a triangle mesh the renderer can draw: curves flattened to\n * line segments, then the resulting polygon triangulated. */\nexport function tessellate(path: Path, opts: TessellateOptions = {}): Mesh {\n if (path.kind === 'rect') return tessellateRect(path);\n return tessellatePolygon(path, opts);\n}\n\nfunction tessellateRect(p: RectPath): Mesh {\n const { x, y, width: w, height: h } = p;\n return {\n vertices: Float32Array.from(rectToContour(x, y, w, h)),\n indices: new Uint32Array([0, 1, 2, 0, 2, 3]),\n anchorA: new Uint32Array([0, 1, 2, 3]),\n anchorB: new Uint32Array([0, 1, 2, 3]),\n anchorT: new Float32Array([0, 0, 0, 0]),\n };\n}\n\ninterface FlattenedContours {\n coords: number[];\n contourStarts: number[];\n anchorA: number[];\n anchorB: number[];\n anchorT: number[];\n}\n\nfunction flattenPolygon(p: PolygonPath, tolerance: number): FlattenedContours {\n const { commands, coords } = p;\n const out: number[] = [];\n const anchorA: number[] = [];\n const anchorB: number[] = [];\n const anchorT: number[] = [];\n const contourStarts: number[] = [];\n let startAnchor = -1;\n let prevAnchor = -1;\n let anchorCounter = 0;\n\n // Anchor bookkeeping for the points a curve just appended: interior points\n // interpolate (prevAnchor → target); the last is pinned anchor-exact.\n const pushCurveAnchors = (anchorStart: number, arcAccum: number[], total: number, target: number): void => {\n for (let k = 0; k < arcAccum.length; k++) {\n anchorA.push(prevAnchor);\n anchorB.push(target);\n anchorT.push(total > 0 ? arcAccum[k] / total : 0);\n }\n const lastIdx = anchorStart + arcAccum.length - 1;\n anchorA[lastIdx] = target;\n anchorB[lastIdx] = target;\n anchorT[lastIdx] = 0;\n };\n\n forEachSegment(commands, coords, (cmd, coordIdx, prevX, prevY) => {\n switch (cmd) {\n case PATH_M:\n case PATH_L: {\n if (cmd === PATH_M) {\n contourStarts.push(out.length / 2);\n startAnchor = anchorCounter;\n }\n out.push(coords[coordIdx], coords[coordIdx + 1]);\n anchorA.push(anchorCounter);\n anchorB.push(anchorCounter);\n anchorT.push(0);\n prevAnchor = anchorCounter;\n anchorCounter++;\n break;\n }\n case PATH_Q: {\n const target = anchorCounter;\n const arcAccum: number[] = [];\n const anchorStart = anchorA.length;\n const total = flattenQuadraticWithArcLen(\n prevX, prevY,\n coords[coordIdx], coords[coordIdx + 1],\n coords[coordIdx + 2], coords[coordIdx + 3],\n tolerance, out, arcAccum,\n );\n pushCurveAnchors(anchorStart, arcAccum, total, target);\n prevAnchor = target;\n anchorCounter++;\n break;\n }\n case PATH_C: {\n const target = anchorCounter;\n const arcAccum: number[] = [];\n const anchorStart = anchorA.length;\n const total = flattenCubicWithArcLen(\n prevX, prevY,\n coords[coordIdx], coords[coordIdx + 1],\n coords[coordIdx + 2], coords[coordIdx + 3],\n coords[coordIdx + 4], coords[coordIdx + 5],\n tolerance, out, arcAccum,\n );\n pushCurveAnchors(anchorStart, arcAccum, total, target);\n prevAnchor = target;\n anchorCounter++;\n break;\n }\n case PATH_Z:\n // The pen returns to the subpath start (forEachSegment does that); the\n // anchor it carries has to follow, or a curve after the Z interpolates\n // from the wrong end.\n prevAnchor = startAnchor;\n break;\n default:\n throw new Error(`tessellate: unknown command code ${cmd}`);\n }\n });\n\n return { coords: out, contourStarts, anchorA, anchorB, anchorT };\n}\n\nfunction tessellatePolygon(p: PolygonPath, opts: TessellateOptions): Mesh {\n const tolerance = opts.flattenTolerance ?? DEFAULT_FLATTEN_TOLERANCE;\n const { coords, contourStarts, anchorA, anchorB, anchorT } = flattenPolygon(p, tolerance);\n\n if (p.fillRule === 'evenodd') {\n return tessellateEvenoddWithAnchors(coords, contourStarts, anchorA, anchorB, anchorT);\n }\n\n // nonzero compound-path tessellation:\n // - The first contour establishes the reference winding direction.\n // - Subsequent contours with the SAME winding as the first are positives\n // (filled, disjoint shapes).\n // - Subsequent contours with OPPOSITE winding are holes; each is grouped\n // with the smallest positive whose polygon contains its first vertex.\n // - Each (positive, [its holes]) group is earcut'd independently;\n // triangles concatenated.\n // Authors mostly write disjoint-positives-with-same-winding; the previous\n // implementation passed every subsequent contour as a hole, which broke\n // those (a duck with body+head+beak, a hamburglar with brim+crown+cape).\n // Using shoelace sign relative to the first contour avoids guessing about\n // screen-down vs math-up axis conventions.\n\n const totalVerts = coords.length / 2;\n const contourEnd = (i: number): number =>\n i + 1 < contourStarts.length ? contourStarts[i + 1] : totalVerts;\n\n if (contourStarts.length <= 1) {\n const tri = earcut(coords);\n return {\n vertices: new Float32Array(coords),\n indices: new Uint32Array(tri),\n anchorA: new Uint32Array(anchorA),\n anchorB: new Uint32Array(anchorB),\n anchorT: new Float32Array(anchorT),\n };\n }\n\n const areas: number[] = contourStarts.map((s, i) => signedArea(coords, s, contourEnd(i)));\n const refSign = Math.sign(areas[0]) || 1;\n\n const positives: number[] = [];\n const negatives: number[] = [];\n for (let i = 0; i < contourStarts.length; i++) {\n if (areas[i] === 0) continue;\n if (Math.sign(areas[i]) === refSign) positives.push(i);\n else negatives.push(i);\n }\n\n if (positives.length === 1 && negatives.length > 0) {\n // Classic outer-with-holes pattern; pass directly to earcut.\n const holeIndices = contourStarts.slice(1);\n const tri = earcut(coords, holeIndices);\n return {\n vertices: new Float32Array(coords),\n indices: new Uint32Array(tri),\n anchorA: new Uint32Array(anchorA),\n anchorB: new Uint32Array(anchorB),\n anchorT: new Float32Array(anchorT),\n };\n }\n\n // Group each opposite-wound contour with the smallest positive that\n // contains its first vertex. Orphans (opposite-wound but not inside any\n // positive) get promoted to independent positives — author probably\n // intended them as separate shapes with inconsistent winding.\n const holesByPositive = new Map<number, number[]>();\n const orphanPositives: number[] = [];\n for (const n of negatives) {\n const px = coords[contourStarts[n] * 2];\n const py = coords[contourStarts[n] * 2 + 1];\n let bestPos = -1;\n let bestAbsArea = Infinity;\n for (const pos of positives) {\n const absArea = Math.abs(areas[pos]);\n if (absArea < bestAbsArea && pointInPolygon(coords, px, py, contourStarts[pos], contourEnd(pos))) {\n bestAbsArea = absArea;\n bestPos = pos;\n }\n }\n if (bestPos >= 0) {\n const arr = holesByPositive.get(bestPos) ?? [];\n arr.push(n);\n holesByPositive.set(bestPos, arr);\n } else {\n orphanPositives.push(n);\n }\n }\n\n const allPositives = [...positives, ...orphanPositives];\n\n const finalCoords: number[] = [];\n const finalAnchorA: number[] = [];\n const finalAnchorB: number[] = [];\n const finalAnchorT: number[] = [];\n const finalIndices: number[] = [];\n for (const pos of allPositives) {\n const holes = holesByPositive.get(pos) ?? [];\n const offset = finalCoords.length / 2;\n const groupCoords: number[] = [];\n const groupStarts: number[] = [0];\n for (let i = contourStarts[pos]; i < contourEnd(pos); i++) {\n groupCoords.push(coords[i * 2], coords[i * 2 + 1]);\n finalAnchorA.push(anchorA[i]);\n finalAnchorB.push(anchorB[i]);\n finalAnchorT.push(anchorT[i]);\n }\n for (const h of holes) {\n groupStarts.push(groupCoords.length / 2);\n for (let i = contourStarts[h]; i < contourEnd(h); i++) {\n groupCoords.push(coords[i * 2], coords[i * 2 + 1]);\n finalAnchorA.push(anchorA[i]);\n finalAnchorB.push(anchorB[i]);\n finalAnchorT.push(anchorT[i]);\n }\n }\n const tri = earcut(groupCoords, groupStarts.length > 1 ? groupStarts.slice(1) : undefined);\n for (const v of groupCoords) finalCoords.push(v);\n for (const idx of tri) finalIndices.push(idx + offset);\n }\n\n return {\n vertices: new Float32Array(finalCoords),\n indices: new Uint32Array(finalIndices),\n anchorA: new Uint32Array(finalAnchorA),\n anchorB: new Uint32Array(finalAnchorB),\n anchorT: new Float32Array(finalAnchorT),\n };\n}\n\nfunction tessellateEvenoddWithAnchors(\n coords: number[],\n contourStarts: number[],\n anchorA: number[],\n anchorB: number[],\n anchorT: number[],\n): Mesh {\n const indices: number[] = [];\n const totalVerts = coords.length / 2;\n for (let c = 0; c < contourStarts.length; c++) {\n const start = contourStarts[c];\n const end = c + 1 < contourStarts.length ? contourStarts[c + 1] : totalVerts;\n for (let i = start + 1; i < end - 1; i++) {\n indices.push(start, i, i + 1);\n }\n }\n return {\n vertices: new Float32Array(coords),\n indices: new Uint32Array(indices),\n requiresStencil: true,\n anchorA: new Uint32Array(anchorA),\n anchorB: new Uint32Array(anchorB),\n anchorT: new Float32Array(anchorT),\n };\n}\n\nfunction signedArea(coords: number[], start: number, end: number): number {\n let a = 0;\n for (let i = start; i < end; i++) {\n const j = i + 1 === end ? start : i + 1;\n a += coords[i * 2] * coords[j * 2 + 1] - coords[j * 2] * coords[i * 2 + 1];\n }\n return a * 0.5;\n}\n","/**\n * Shortening a flattened subpath so a filled marker is not speared by its own\n * line. SVG has no equivalent — it paints the marker over a full-length\n * stroke — so this is the one place our rendering deliberately differs.\n *\n * Runs before dash splitting, so a dash pattern fits the visible line rather\n * than running off under the head. The anchor-param interpolation matches\n * `splitForDash`'s rule for a boundary landing mid-segment.\n */\n\nimport type { Polyline } from './polyline';\n\nconst EPS = 1e-9;\n\ninterface Sample {\n x: number; y: number;\n a: number; b: number; t: number;\n w: number;\n /** Index of the first original point at or after this sample. */\n next: number;\n}\n\nfunction sampleAt(\n pl: Polyline, cum: Float64Array,\n A: Uint32Array, B: Uint32Array, T: Float32Array, W: Float32Array | undefined,\n dist: number,\n): Sample {\n const n = cum.length;\n let i = 1;\n while (i < n - 1 && cum[i] < dist) i++;\n const segStart = cum[i - 1];\n const segLen = cum[i] - segStart;\n const f = segLen > EPS ? (dist - segStart) / segLen : 0;\n\n const px = pl.points[(i - 1) * 2], py = pl.points[(i - 1) * 2 + 1];\n const qx = pl.points[i * 2], qy = pl.points[i * 2 + 1];\n\n let a: number, b: number, t: number;\n if (A[i - 1] === A[i] && B[i - 1] === B[i]) {\n a = A[i - 1]; b = B[i - 1];\n t = T[i - 1] + (T[i] - T[i - 1]) * f;\n } else if (f < 0.5) {\n a = A[i - 1]; b = B[i - 1]; t = T[i - 1];\n } else {\n a = A[i]; b = B[i]; t = T[i];\n }\n\n const w = W ? W[i - 1] + (W[i] - W[i - 1]) * f : 0;\n return { x: px + (qx - px) * f, y: py + (qy - py) * f, a, b, t, w, next: i };\n}\n\n/**\n * Shorten `pl` by `startInset` from its first point and `endInset` from its\n * last, both in the same world units as the points.\n *\n * Returns `pl` itself when there is nothing to do (both insets zero, or the\n * subpath is closed and so has no free ends), and `null` when the insets\n * consume the whole run — a caller should then draw no ribbon at all.\n */\nexport function trimPolyline(\n pl: Polyline,\n startInset: number,\n endInset: number,\n): Polyline | null {\n const from = Math.max(0, startInset);\n const to = Math.max(0, endInset);\n if (from <= 0 && to <= 0) return pl;\n if (pl.closed) return pl;\n\n const n = pl.points.length / 2;\n if (n < 2) return null;\n\n const A = pl.anchorA ?? new Uint32Array(n);\n const B = pl.anchorB ?? new Uint32Array(n);\n const T = pl.anchorT ?? new Float32Array(n);\n const W = pl.widths;\n\n const cum = new Float64Array(n);\n for (let i = 1; i < n; i++) {\n const dx = pl.points[i * 2] - pl.points[(i - 1) * 2];\n const dy = pl.points[i * 2 + 1] - pl.points[(i - 1) * 2 + 1];\n cum[i] = cum[i - 1] + Math.hypot(dx, dy);\n }\n const total = cum[n - 1];\n const cutA = from;\n const cutB = total - to;\n if (cutB - cutA <= EPS) return null;\n\n const head = sampleAt(pl, cum, A, B, T, W, cutA);\n const tail = sampleAt(pl, cum, A, B, T, W, cutB);\n\n const points: number[] = [head.x, head.y];\n const aOut: number[] = [head.a];\n const bOut: number[] = [head.b];\n const tOut: number[] = [head.t];\n const wOut: number[] | undefined = W ? [head.w] : undefined;\n\n for (let i = head.next; i < tail.next; i++) {\n points.push(pl.points[i * 2], pl.points[i * 2 + 1]);\n aOut.push(A[i]); bOut.push(B[i]); tOut.push(T[i]);\n if (wOut) wOut.push(W![i]);\n }\n\n points.push(tail.x, tail.y);\n aOut.push(tail.a); bOut.push(tail.b); tOut.push(tail.t);\n if (wOut) wOut.push(tail.w);\n\n return {\n points,\n closed: false,\n anchorA: new Uint32Array(aOut),\n anchorB: new Uint32Array(bOut),\n anchorT: new Float32Array(tOut),\n ...(wOut ? { widths: new Float32Array(wOut) } : {}),\n };\n}\n"]}
1
+ {"version":3,"sources":["../../src/tessellate/tessellate.ts","../../src/tessellate/trim.ts"],"names":[],"mappings":";;;;;;;AAsBO,SAAS,UAAA,CAAW,IAAA,EAAY,IAAA,GAA0B,EAAC,EAAS;AACzE,EAAA,IAAI,IAAA,CAAK,IAAA,KAAS,MAAA,EAAQ,OAAO,eAAe,IAAI,CAAA;AACpD,EAAA,OAAO,iBAAA,CAAkB,MAAM,IAAI,CAAA;AACrC;AAEA,SAAS,eAAe,CAAA,EAAmB;AACzC,EAAA,MAAM,EAAE,CAAA,EAAG,CAAA,EAAG,OAAO,CAAA,EAAG,MAAA,EAAQ,GAAE,GAAI,CAAA;AACtC,EAAA,OAAO;AAAA,IACL,QAAA,EAAU,aAAa,IAAA,CAAK,aAAA,CAAc,GAAG,CAAA,EAAG,CAAA,EAAG,CAAC,CAAC,CAAA;AAAA,IACrD,OAAA,EAAS,IAAI,WAAA,CAAY,CAAC,CAAA,EAAG,GAAG,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAC,CAAC,CAAA;AAAA,IAC3C,OAAA,EAAS,IAAI,WAAA,CAAY,CAAC,GAAG,CAAA,EAAG,CAAA,EAAG,CAAC,CAAC,CAAA;AAAA,IACrC,OAAA,EAAS,IAAI,WAAA,CAAY,CAAC,GAAG,CAAA,EAAG,CAAA,EAAG,CAAC,CAAC,CAAA;AAAA,IACrC,OAAA,EAAS,IAAI,YAAA,CAAa,CAAC,GAAG,CAAA,EAAG,CAAA,EAAG,CAAC,CAAC;AAAA,GACxC;AACF;AAUA,SAAS,cAAA,CAAe,GAAgB,SAAA,EAAsC;AAC5E,EAAA,MAAM,EAAE,QAAA,EAAU,MAAA,EAAO,GAAI,CAAA;AAC7B,EAAA,MAAM,MAAgB,EAAC;AACvB,EAAA,MAAM,UAAoB,EAAC;AAC3B,EAAA,MAAM,UAAoB,EAAC;AAC3B,EAAA,MAAM,UAAoB,EAAC;AAC3B,EAAA,MAAM,gBAA0B,EAAC;AACjC,EAAA,IAAI,WAAA,GAAc,EAAA;AAClB,EAAA,IAAI,UAAA,GAAa,EAAA;AACjB,EAAA,IAAI,aAAA,GAAgB,CAAA;AAIpB,EAAA,MAAM,gBAAA,GAAmB,CAAC,WAAA,EAAqB,QAAA,EAAoB,OAAe,MAAA,KAAyB;AACzG,IAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,QAAA,CAAS,QAAQ,CAAA,EAAA,EAAK;AACxC,MAAA,OAAA,CAAQ,KAAK,UAAU,CAAA;AACvB,MAAA,OAAA,CAAQ,KAAK,MAAM,CAAA;AACnB,MAAA,OAAA,CAAQ,KAAK,KAAA,GAAQ,CAAA,GAAI,SAAS,CAAC,CAAA,GAAI,QAAQ,CAAC,CAAA;AAAA,IAClD;AACA,IAAA,MAAM,OAAA,GAAU,WAAA,GAAc,QAAA,CAAS,MAAA,GAAS,CAAA;AAChD,IAAA,OAAA,CAAQ,OAAO,CAAA,GAAI,MAAA;AACnB,IAAA,OAAA,CAAQ,OAAO,CAAA,GAAI,MAAA;AACnB,IAAA,OAAA,CAAQ,OAAO,CAAA,GAAI,CAAA;AAAA,EACrB,CAAA;AAEA,EAAA,cAAA,CAAe,QAAA,EAAU,QAAQ,CAAC,GAAA,EAAK,UAAU,KAAA,EAAO,KAAA,EAAO,IAAI,YAAA,KAAiB;AAClF,IAAA,IAAI,YAAA,EAAc;AAChB,MAAA,MAAM,MAAA,GAAS,IAAA,CAAK,GAAA,CAAI,WAAA,EAAa,CAAC,CAAA;AACtC,MAAA,aAAA,CAAc,IAAA,CAAK,GAAA,CAAI,MAAA,GAAS,CAAC,CAAA;AACjC,MAAA,GAAA,CAAI,IAAA,CAAK,OAAO,KAAK,CAAA;AACrB,MAAA,OAAA,CAAQ,KAAK,MAAM,CAAA;AACnB,MAAA,OAAA,CAAQ,KAAK,MAAM,CAAA;AACnB,MAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AACd,MAAA,UAAA,GAAa,MAAA;AAAA,IACf;AACA,IAAA,QAAQ,GAAA;AAAK,MACX,KAAK,MAAA;AAAA,MACL,KAAK,MAAA,EAAQ;AACX,QAAA,IAAI,QAAQ,MAAA,EAAQ;AAClB,UAAA,aAAA,CAAc,IAAA,CAAK,GAAA,CAAI,MAAA,GAAS,CAAC,CAAA;AACjC,UAAA,WAAA,GAAc,aAAA;AAAA,QAChB;AACA,QAAA,GAAA,CAAI,KAAK,MAAA,CAAO,QAAQ,GAAG,MAAA,CAAO,QAAA,GAAW,CAAC,CAAC,CAAA;AAC/C,QAAA,OAAA,CAAQ,KAAK,aAAa,CAAA;AAC1B,QAAA,OAAA,CAAQ,KAAK,aAAa,CAAA;AAC1B,QAAA,OAAA,CAAQ,KAAK,CAAC,CAAA;AACd,QAAA,UAAA,GAAa,aAAA;AACb,QAAA,aAAA,EAAA;AACA,QAAA;AAAA,MACF;AAAA,MACA,KAAK,MAAA,EAAQ;AACX,QAAA,MAAM,MAAA,GAAS,aAAA;AACf,QAAA,MAAM,WAAqB,EAAC;AAC5B,QAAA,MAAM,cAAc,OAAA,CAAQ,MAAA;AAC5B,QAAA,MAAM,KAAA,GAAQ,0BAAA;AAAA,UACZ,KAAA;AAAA,UAAO,KAAA;AAAA,UACP,OAAO,QAAQ,CAAA;AAAA,UAAG,MAAA,CAAO,WAAW,CAAC,CAAA;AAAA,UACrC,MAAA,CAAO,WAAW,CAAC,CAAA;AAAA,UAAG,MAAA,CAAO,WAAW,CAAC,CAAA;AAAA,UACzC,SAAA;AAAA,UAAW,GAAA;AAAA,UAAK;AAAA,SAClB;AACA,QAAA,gBAAA,CAAiB,WAAA,EAAa,QAAA,EAAU,KAAA,EAAO,MAAM,CAAA;AACrD,QAAA,UAAA,GAAa,MAAA;AACb,QAAA,aAAA,EAAA;AACA,QAAA;AAAA,MACF;AAAA,MACA,KAAK,MAAA,EAAQ;AACX,QAAA,MAAM,MAAA,GAAS,aAAA;AACf,QAAA,MAAM,WAAqB,EAAC;AAC5B,QAAA,MAAM,cAAc,OAAA,CAAQ,MAAA;AAC5B,QAAA,MAAM,KAAA,GAAQ,sBAAA;AAAA,UACZ,KAAA;AAAA,UAAO,KAAA;AAAA,UACP,OAAO,QAAQ,CAAA;AAAA,UAAG,MAAA,CAAO,WAAW,CAAC,CAAA;AAAA,UACrC,MAAA,CAAO,WAAW,CAAC,CAAA;AAAA,UAAG,MAAA,CAAO,WAAW,CAAC,CAAA;AAAA,UACzC,MAAA,CAAO,WAAW,CAAC,CAAA;AAAA,UAAG,MAAA,CAAO,WAAW,CAAC,CAAA;AAAA,UACzC,SAAA;AAAA,UAAW,GAAA;AAAA,UAAK;AAAA,SAClB;AACA,QAAA,gBAAA,CAAiB,WAAA,EAAa,QAAA,EAAU,KAAA,EAAO,MAAM,CAAA;AACrD,QAAA,UAAA,GAAa,MAAA;AACb,QAAA,aAAA,EAAA;AACA,QAAA;AAAA,MACF;AAAA,MACA,KAAK,MAAA;AAIH,QAAA,UAAA,GAAa,WAAA;AACb,QAAA;AAAA,MACF;AACE,QAAA,MAAM,IAAI,KAAA,CAAM,CAAA,iCAAA,EAAoC,GAAG,CAAA,CAAE,CAAA;AAAA;AAC7D,EACF,CAAC,CAAA;AAED,EAAA,OAAO,EAAE,MAAA,EAAQ,GAAA,EAAK,aAAA,EAAe,OAAA,EAAS,SAAS,OAAA,EAAQ;AACjE;AAEA,SAAS,iBAAA,CAAkB,GAAgB,IAAA,EAA+B;AACxE,EAAA,MAAM,SAAA,GAAY,KAAK,gBAAA,IAAoB,yBAAA;AAC3C,EAAA,MAAM,EAAE,QAAQ,aAAA,EAAe,OAAA,EAAS,SAAS,OAAA,EAAQ,GAAI,cAAA,CAAe,CAAA,EAAG,SAAS,CAAA;AAExF,EAAA,IAAI,CAAA,CAAE,aAAa,SAAA,EAAW;AAC5B,IAAA,OAAO,4BAAA,CAA6B,MAAA,EAAQ,aAAA,EAAe,OAAA,EAAS,SAAS,OAAO,CAAA;AAAA,EACtF;AAgBA,EAAA,MAAM,UAAA,GAAa,OAAO,MAAA,GAAS,CAAA;AACnC,EAAA,MAAM,UAAA,GAAa,CAAC,CAAA,KAClB,CAAA,GAAI,CAAA,GAAI,cAAc,MAAA,GAAS,aAAA,CAAc,CAAA,GAAI,CAAC,CAAA,GAAI,UAAA;AAExD,EAAA,IAAI,aAAA,CAAc,UAAU,CAAA,EAAG;AAC7B,IAAA,MAAM,GAAA,GAAM,OAAO,MAAM,CAAA;AACzB,IAAA,OAAO;AAAA,MACL,QAAA,EAAU,IAAI,YAAA,CAAa,MAAM,CAAA;AAAA,MACjC,OAAA,EAAS,IAAI,WAAA,CAAY,GAAG,CAAA;AAAA,MAC5B,OAAA,EAAS,IAAI,WAAA,CAAY,OAAO,CAAA;AAAA,MAChC,OAAA,EAAS,IAAI,WAAA,CAAY,OAAO,CAAA;AAAA,MAChC,OAAA,EAAS,IAAI,YAAA,CAAa,OAAO;AAAA,KACnC;AAAA,EACF;AAEA,EAAA,MAAM,KAAA,GAAkB,aAAA,CAAc,GAAA,CAAI,CAAC,CAAA,EAAG,CAAA,KAAM,UAAA,CAAW,MAAA,EAAQ,CAAA,EAAG,UAAA,CAAW,CAAC,CAAC,CAAC,CAAA;AACxF,EAAA,MAAM,UAAU,IAAA,CAAK,IAAA,CAAK,KAAA,CAAM,CAAC,CAAC,CAAA,IAAK,CAAA;AAEvC,EAAA,MAAM,YAAsB,EAAC;AAC7B,EAAA,MAAM,YAAsB,EAAC;AAC7B,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,aAAA,CAAc,QAAQ,CAAA,EAAA,EAAK;AAC7C,IAAA,IAAI,KAAA,CAAM,CAAC,CAAA,KAAM,CAAA,EAAG;AACpB,IAAA,IAAI,IAAA,CAAK,KAAK,KAAA,CAAM,CAAC,CAAC,CAAA,KAAM,OAAA,EAAS,SAAA,CAAU,IAAA,CAAK,CAAC,CAAA;AAAA,SAChD,SAAA,CAAU,KAAK,CAAC,CAAA;AAAA,EACvB;AAEA,EAAA,IAAI,SAAA,CAAU,MAAA,KAAW,CAAA,IAAK,SAAA,CAAU,SAAS,CAAA,EAAG;AAElD,IAAA,MAAM,WAAA,GAAc,aAAA,CAAc,KAAA,CAAM,CAAC,CAAA;AACzC,IAAA,MAAM,GAAA,GAAM,MAAA,CAAO,MAAA,EAAQ,WAAW,CAAA;AACtC,IAAA,OAAO;AAAA,MACL,QAAA,EAAU,IAAI,YAAA,CAAa,MAAM,CAAA;AAAA,MACjC,OAAA,EAAS,IAAI,WAAA,CAAY,GAAG,CAAA;AAAA,MAC5B,OAAA,EAAS,IAAI,WAAA,CAAY,OAAO,CAAA;AAAA,MAChC,OAAA,EAAS,IAAI,WAAA,CAAY,OAAO,CAAA;AAAA,MAChC,OAAA,EAAS,IAAI,YAAA,CAAa,OAAO;AAAA,KACnC;AAAA,EACF;AAMA,EAAA,MAAM,eAAA,uBAAsB,GAAA,EAAsB;AAClD,EAAA,MAAM,kBAA4B,EAAC;AACnC,EAAA,KAAA,MAAW,KAAK,SAAA,EAAW;AACzB,IAAA,MAAM,EAAA,GAAK,MAAA,CAAO,aAAA,CAAc,CAAC,IAAI,CAAC,CAAA;AACtC,IAAA,MAAM,KAAK,MAAA,CAAO,aAAA,CAAc,CAAC,CAAA,GAAI,IAAI,CAAC,CAAA;AAC1C,IAAA,IAAI,OAAA,GAAU,EAAA;AACd,IAAA,IAAI,WAAA,GAAc,QAAA;AAClB,IAAA,KAAA,MAAW,OAAO,SAAA,EAAW;AAC3B,MAAA,MAAM,OAAA,GAAU,IAAA,CAAK,GAAA,CAAI,KAAA,CAAM,GAAG,CAAC,CAAA;AACnC,MAAA,IAAI,OAAA,GAAU,WAAA,IAAe,cAAA,CAAe,MAAA,EAAQ,EAAA,EAAI,EAAA,EAAI,aAAA,CAAc,GAAG,CAAA,EAAG,UAAA,CAAW,GAAG,CAAC,CAAA,EAAG;AAChG,QAAA,WAAA,GAAc,OAAA;AACd,QAAA,OAAA,GAAU,GAAA;AAAA,MACZ;AAAA,IACF;AACA,IAAA,IAAI,WAAW,CAAA,EAAG;AAChB,MAAA,MAAM,GAAA,GAAM,eAAA,CAAgB,GAAA,CAAI,OAAO,KAAK,EAAC;AAC7C,MAAA,GAAA,CAAI,KAAK,CAAC,CAAA;AACV,MAAA,eAAA,CAAgB,GAAA,CAAI,SAAS,GAAG,CAAA;AAAA,IAClC,CAAA,MAAO;AACL,MAAA,eAAA,CAAgB,KAAK,CAAC,CAAA;AAAA,IACxB;AAAA,EACF;AAEA,EAAA,MAAM,YAAA,GAAe,CAAC,GAAG,SAAA,EAAW,GAAG,eAAe,CAAA;AAEtD,EAAA,MAAM,cAAwB,EAAC;AAC/B,EAAA,MAAM,eAAyB,EAAC;AAChC,EAAA,MAAM,eAAyB,EAAC;AAChC,EAAA,MAAM,eAAyB,EAAC;AAChC,EAAA,MAAM,eAAyB,EAAC;AAChC,EAAA,KAAA,MAAW,OAAO,YAAA,EAAc;AAC9B,IAAA,MAAM,KAAA,GAAQ,eAAA,CAAgB,GAAA,CAAI,GAAG,KAAK,EAAC;AAC3C,IAAA,MAAM,MAAA,GAAS,YAAY,MAAA,GAAS,CAAA;AACpC,IAAA,MAAM,cAAwB,EAAC;AAC/B,IAAA,MAAM,WAAA,GAAwB,CAAC,CAAC,CAAA;AAChC,IAAA,KAAA,IAAS,CAAA,GAAI,cAAc,GAAG,CAAA,EAAG,IAAI,UAAA,CAAW,GAAG,GAAG,CAAA,EAAA,EAAK;AACzD,MAAA,WAAA,CAAY,IAAA,CAAK,OAAO,CAAA,GAAI,CAAC,GAAG,MAAA,CAAO,CAAA,GAAI,CAAA,GAAI,CAAC,CAAC,CAAA;AACjD,MAAA,YAAA,CAAa,IAAA,CAAK,OAAA,CAAQ,CAAC,CAAC,CAAA;AAC5B,MAAA,YAAA,CAAa,IAAA,CAAK,OAAA,CAAQ,CAAC,CAAC,CAAA;AAC5B,MAAA,YAAA,CAAa,IAAA,CAAK,OAAA,CAAQ,CAAC,CAAC,CAAA;AAAA,IAC9B;AACA,IAAA,KAAA,MAAW,KAAK,KAAA,EAAO;AACrB,MAAA,WAAA,CAAY,IAAA,CAAK,WAAA,CAAY,MAAA,GAAS,CAAC,CAAA;AACvC,MAAA,KAAA,IAAS,CAAA,GAAI,cAAc,CAAC,CAAA,EAAG,IAAI,UAAA,CAAW,CAAC,GAAG,CAAA,EAAA,EAAK;AACrD,QAAA,WAAA,CAAY,IAAA,CAAK,OAAO,CAAA,GAAI,CAAC,GAAG,MAAA,CAAO,CAAA,GAAI,CAAA,GAAI,CAAC,CAAC,CAAA;AACjD,QAAA,YAAA,CAAa,IAAA,CAAK,OAAA,CAAQ,CAAC,CAAC,CAAA;AAC5B,QAAA,YAAA,CAAa,IAAA,CAAK,OAAA,CAAQ,CAAC,CAAC,CAAA;AAC5B,QAAA,YAAA,CAAa,IAAA,CAAK,OAAA,CAAQ,CAAC,CAAC,CAAA;AAAA,MAC9B;AAAA,IACF;AACA,IAAA,MAAM,GAAA,GAAM,MAAA,CAAO,WAAA,EAAa,WAAA,CAAY,MAAA,GAAS,IAAI,WAAA,CAAY,KAAA,CAAM,CAAC,CAAA,GAAI,MAAS,CAAA;AACzF,IAAA,KAAA,MAAW,CAAA,IAAK,WAAA,EAAa,WAAA,CAAY,IAAA,CAAK,CAAC,CAAA;AAC/C,IAAA,KAAA,MAAW,GAAA,IAAO,GAAA,EAAK,YAAA,CAAa,IAAA,CAAK,MAAM,MAAM,CAAA;AAAA,EACvD;AAEA,EAAA,OAAO;AAAA,IACL,QAAA,EAAU,IAAI,YAAA,CAAa,WAAW,CAAA;AAAA,IACtC,OAAA,EAAS,IAAI,WAAA,CAAY,YAAY,CAAA;AAAA,IACrC,OAAA,EAAS,IAAI,WAAA,CAAY,YAAY,CAAA;AAAA,IACrC,OAAA,EAAS,IAAI,WAAA,CAAY,YAAY,CAAA;AAAA,IACrC,OAAA,EAAS,IAAI,YAAA,CAAa,YAAY;AAAA,GACxC;AACF;AAEA,SAAS,4BAAA,CACP,MAAA,EACA,aAAA,EACA,OAAA,EACA,SACA,OAAA,EACM;AACN,EAAA,MAAM,UAAoB,EAAC;AAC3B,EAAA,MAAM,UAAA,GAAa,OAAO,MAAA,GAAS,CAAA;AACnC,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,aAAA,CAAc,QAAQ,CAAA,EAAA,EAAK;AAC7C,IAAA,MAAM,KAAA,GAAQ,cAAc,CAAC,CAAA;AAC7B,IAAA,MAAM,GAAA,GAAM,IAAI,CAAA,GAAI,aAAA,CAAc,SAAS,aAAA,CAAc,CAAA,GAAI,CAAC,CAAA,GAAI,UAAA;AAClE,IAAA,KAAA,IAAS,IAAI,KAAA,GAAQ,CAAA,EAAG,CAAA,GAAI,GAAA,GAAM,GAAG,CAAA,EAAA,EAAK;AACxC,MAAA,OAAA,CAAQ,IAAA,CAAK,KAAA,EAAO,CAAA,EAAG,CAAA,GAAI,CAAC,CAAA;AAAA,IAC9B;AAAA,EACF;AACA,EAAA,OAAO;AAAA,IACL,QAAA,EAAU,IAAI,YAAA,CAAa,MAAM,CAAA;AAAA,IACjC,OAAA,EAAS,IAAI,WAAA,CAAY,OAAO,CAAA;AAAA,IAChC,eAAA,EAAiB,IAAA;AAAA,IACjB,OAAA,EAAS,IAAI,WAAA,CAAY,OAAO,CAAA;AAAA,IAChC,OAAA,EAAS,IAAI,WAAA,CAAY,OAAO,CAAA;AAAA,IAChC,OAAA,EAAS,IAAI,YAAA,CAAa,OAAO;AAAA,GACnC;AACF;AAEA,SAAS,UAAA,CAAW,MAAA,EAAkB,KAAA,EAAe,GAAA,EAAqB;AACxE,EAAA,IAAI,CAAA,GAAI,CAAA;AACR,EAAA,KAAA,IAAS,CAAA,GAAI,KAAA,EAAO,CAAA,GAAI,GAAA,EAAK,CAAA,EAAA,EAAK;AAChC,IAAA,MAAM,CAAA,GAAI,CAAA,GAAI,CAAA,KAAM,GAAA,GAAM,QAAQ,CAAA,GAAI,CAAA;AACtC,IAAA,CAAA,IAAK,OAAO,CAAA,GAAI,CAAC,CAAA,GAAI,MAAA,CAAO,IAAI,CAAA,GAAI,CAAC,CAAA,GAAI,MAAA,CAAO,IAAI,CAAC,CAAA,GAAI,MAAA,CAAO,CAAA,GAAI,IAAI,CAAC,CAAA;AAAA,EAC3E;AACA,EAAA,OAAO,CAAA,GAAI,GAAA;AACb;;;ACnSA,IAAM,GAAA,GAAM,IAAA;AAUZ,SAAS,QAAA,CACP,IAAc,GAAA,EACd,CAAA,EAAgB,GAAgB,CAAA,EAAiB,CAAA,EACjD,MAGA,aAAA,EACQ;AACR,EAAA,MAAM,IAAI,GAAA,CAAI,MAAA;AACd,EAAA,IAAI,CAAA,GAAI,CAAA;AACR,EAAA,OAAO,CAAA,GAAI,CAAA,GAAI,CAAA,KAAM,aAAA,GAAgB,GAAA,CAAI,CAAC,CAAA,IAAK,IAAA,GAAO,GAAA,CAAI,CAAC,CAAA,GAAI,IAAA,CAAA,EAAO,CAAA,EAAA;AACtE,EAAA,MAAM,QAAA,GAAW,GAAA,CAAI,CAAA,GAAI,CAAC,CAAA;AAC1B,EAAA,MAAM,MAAA,GAAS,GAAA,CAAI,CAAC,CAAA,GAAI,QAAA;AACxB,EAAA,MAAM,CAAA,GAAI,MAAA,GAAS,GAAA,GAAA,CAAO,IAAA,GAAO,YAAY,MAAA,GAAS,CAAA;AAEtD,EAAA,MAAM,EAAA,GAAK,EAAA,CAAG,MAAA,CAAA,CAAQ,CAAA,GAAI,CAAA,IAAK,CAAC,CAAA,EAAG,EAAA,GAAK,EAAA,CAAG,MAAA,CAAA,CAAQ,CAAA,GAAI,CAAA,IAAK,IAAI,CAAC,CAAA;AACjE,EAAA,MAAM,EAAA,GAAK,EAAA,CAAG,MAAA,CAAO,CAAA,GAAI,CAAC,CAAA,EAAG,EAAA,GAAK,EAAA,CAAG,MAAA,CAAO,CAAA,GAAI,CAAA,GAAI,CAAC,CAAA;AAErD,EAAA,IAAI,GAAW,CAAA,EAAW,CAAA;AAC1B,EAAA,IAAI,CAAA,CAAE,CAAA,GAAI,CAAC,CAAA,KAAM,CAAA,CAAE,CAAC,CAAA,IAAK,CAAA,CAAE,CAAA,GAAI,CAAC,CAAA,KAAM,CAAA,CAAE,CAAC,CAAA,EAAG;AAC1C,IAAA,CAAA,GAAI,CAAA,CAAE,IAAI,CAAC,CAAA;AAAG,IAAA,CAAA,GAAI,CAAA,CAAE,IAAI,CAAC,CAAA;AACzB,IAAA,CAAA,GAAI,CAAA,CAAE,CAAA,GAAI,CAAC,CAAA,GAAA,CAAK,CAAA,CAAE,CAAC,CAAA,GAAI,CAAA,CAAE,CAAA,GAAI,CAAC,CAAA,IAAK,CAAA;AAAA,EACrC,CAAA,MAAA,IAAW,IAAI,GAAA,EAAK;AAClB,IAAA,CAAA,GAAI,CAAA,CAAE,IAAI,CAAC,CAAA;AAAG,IAAA,CAAA,GAAI,CAAA,CAAE,IAAI,CAAC,CAAA;AAAG,IAAA,CAAA,GAAI,CAAA,CAAE,IAAI,CAAC,CAAA;AAAA,EACzC,CAAA,MAAO;AACL,IAAA,CAAA,GAAI,EAAE,CAAC,CAAA;AAAG,IAAA,CAAA,GAAI,EAAE,CAAC,CAAA;AAAG,IAAA,CAAA,GAAI,EAAE,CAAC,CAAA;AAAA,EAC7B;AAEA,EAAA,MAAM,CAAA,GAAI,CAAA,GAAI,CAAA,CAAE,CAAA,GAAI,CAAC,CAAA,GAAA,CAAK,CAAA,CAAE,CAAC,CAAA,GAAI,CAAA,CAAE,CAAA,GAAI,CAAC,KAAK,CAAA,GAAI,CAAA;AACjD,EAAA,OAAO,EAAE,CAAA,EAAG,EAAA,GAAA,CAAM,EAAA,GAAK,EAAA,IAAM,GAAG,CAAA,EAAG,EAAA,GAAA,CAAM,EAAA,GAAK,EAAA,IAAM,GAAG,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,MAAM,CAAA,EAAE;AAC7E;AAUO,SAAS,YAAA,CACd,EAAA,EACA,UAAA,EACA,QAAA,EACiB;AACjB,EAAA,MAAM,IAAA,GAAO,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,UAAU,CAAA;AACnC,EAAA,MAAM,EAAA,GAAK,IAAA,CAAK,GAAA,CAAI,CAAA,EAAG,QAAQ,CAAA;AAC/B,EAAA,IAAI,IAAA,IAAQ,CAAA,IAAK,EAAA,IAAM,CAAA,EAAG,OAAO,EAAA;AACjC,EAAA,IAAI,EAAA,CAAG,QAAQ,OAAO,EAAA;AAEtB,EAAA,MAAM,CAAA,GAAI,EAAA,CAAG,MAAA,CAAO,MAAA,GAAS,CAAA;AAC7B,EAAA,IAAI,CAAA,GAAI,GAAG,OAAO,IAAA;AAElB,EAAA,MAAM,CAAA,GAAI,EAAA,CAAG,OAAA,IAAW,IAAI,YAAY,CAAC,CAAA;AACzC,EAAA,MAAM,CAAA,GAAI,EAAA,CAAG,OAAA,IAAW,IAAI,YAAY,CAAC,CAAA;AACzC,EAAA,MAAM,CAAA,GAAI,EAAA,CAAG,OAAA,IAAW,IAAI,aAAa,CAAC,CAAA;AAC1C,EAAA,MAAM,IAAI,EAAA,CAAG,MAAA;AAEb,EAAA,MAAM,GAAA,GAAM,IAAI,YAAA,CAAa,CAAC,CAAA;AAC9B,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,CAAA,EAAG,CAAA,EAAA,EAAK;AAC1B,IAAA,MAAM,EAAA,GAAK,EAAA,CAAG,MAAA,CAAO,CAAA,GAAI,CAAC,IAAI,EAAA,CAAG,MAAA,CAAA,CAAQ,CAAA,GAAI,CAAA,IAAK,CAAC,CAAA;AACnD,IAAA,MAAM,EAAA,GAAK,EAAA,CAAG,MAAA,CAAO,CAAA,GAAI,CAAA,GAAI,CAAC,CAAA,GAAI,EAAA,CAAG,MAAA,CAAA,CAAQ,CAAA,GAAI,CAAA,IAAK,CAAA,GAAI,CAAC,CAAA;AAC3D,IAAA,GAAA,CAAI,CAAC,IAAI,GAAA,CAAI,CAAA,GAAI,CAAC,CAAA,GAAI,IAAA,CAAK,KAAA,CAAM,EAAA,EAAI,EAAE,CAAA;AAAA,EACzC;AACA,EAAA,MAAM,KAAA,GAAQ,GAAA,CAAI,CAAA,GAAI,CAAC,CAAA;AACvB,EAAA,MAAM,IAAA,GAAO,IAAA;AACb,EAAA,MAAM,OAAO,KAAA,GAAQ,EAAA;AACrB,EAAA,IAAI,IAAA,GAAO,IAAA,IAAQ,GAAA,EAAK,OAAO,IAAA;AAE/B,EAAA,MAAM,IAAA,GAAO,SAAS,EAAA,EAAI,GAAA,EAAK,GAAG,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,IAAA,EAAM,IAAI,CAAA;AACrD,EAAA,MAAM,IAAA,GAAO,SAAS,EAAA,EAAI,GAAA,EAAK,GAAG,CAAA,EAAG,CAAA,EAAG,CAAA,EAAG,IAAA,EAAM,KAAK,CAAA;AAEtD,EAAA,MAAM,MAAA,GAAmB,CAAC,IAAA,CAAK,CAAA,EAAG,KAAK,CAAC,CAAA;AACxC,EAAA,MAAM,IAAA,GAAiB,CAAC,IAAA,CAAK,CAAC,CAAA;AAC9B,EAAA,MAAM,IAAA,GAAiB,CAAC,IAAA,CAAK,CAAC,CAAA;AAC9B,EAAA,MAAM,IAAA,GAAiB,CAAC,IAAA,CAAK,CAAC,CAAA;AAC9B,EAAA,MAAM,IAAA,GAA6B,CAAA,GAAI,CAAC,IAAA,CAAK,CAAC,CAAA,GAAI,MAAA;AAElD,EAAA,KAAA,IAAS,IAAI,IAAA,CAAK,IAAA,EAAM,CAAA,GAAI,IAAA,CAAK,MAAM,CAAA,EAAA,EAAK;AAC1C,IAAA,MAAA,CAAO,IAAA,CAAK,EAAA,CAAG,MAAA,CAAO,CAAA,GAAI,CAAC,CAAA,EAAG,EAAA,CAAG,MAAA,CAAO,CAAA,GAAI,CAAA,GAAI,CAAC,CAAC,CAAA;AAClD,IAAA,IAAA,CAAK,IAAA,CAAK,CAAA,CAAE,CAAC,CAAC,CAAA;AAAG,IAAA,IAAA,CAAK,IAAA,CAAK,CAAA,CAAE,CAAC,CAAC,CAAA;AAAG,IAAA,IAAA,CAAK,IAAA,CAAK,CAAA,CAAE,CAAC,CAAC,CAAA;AAChD,IAAA,IAAI,IAAA,EAAM,IAAA,CAAK,IAAA,CAAK,CAAA,CAAG,CAAC,CAAC,CAAA;AAAA,EAC3B;AAEA,EAAA,MAAA,CAAO,IAAA,CAAK,IAAA,CAAK,CAAA,EAAG,IAAA,CAAK,CAAC,CAAA;AAC1B,EAAA,IAAA,CAAK,IAAA,CAAK,KAAK,CAAC,CAAA;AAAG,EAAA,IAAA,CAAK,IAAA,CAAK,KAAK,CAAC,CAAA;AAAG,EAAA,IAAA,CAAK,IAAA,CAAK,KAAK,CAAC,CAAA;AACtD,EAAA,IAAI,IAAA,EAAM,IAAA,CAAK,IAAA,CAAK,IAAA,CAAK,CAAC,CAAA;AAE1B,EAAA,OAAO;AAAA,IACL,MAAA;AAAA,IACA,MAAA,EAAQ,KAAA;AAAA,IACR,OAAA,EAAS,IAAI,WAAA,CAAY,IAAI,CAAA;AAAA,IAC7B,OAAA,EAAS,IAAI,WAAA,CAAY,IAAI,CAAA;AAAA,IAC7B,OAAA,EAAS,IAAI,YAAA,CAAa,IAAI,CAAA;AAAA,IAC9B,GAAI,OAAO,EAAE,MAAA,EAAQ,IAAI,YAAA,CAAa,IAAI,CAAA,EAAE,GAAI;AAAC,GACnD;AACF","file":"index.js","sourcesContent":["import earcut from 'earcut';\nimport { forEachSegment, PATH_M, PATH_L, PATH_Z, PATH_C, PATH_Q } from '../commands';\nimport { pointInPolygon } from '../polyline';\nimport { rectToContour } from '../box';\nimport type { Path, PolygonPath, RectPath } from '../path';\nimport {\n DEFAULT_FLATTEN_TOLERANCE,\n flattenCubicWithArcLen,\n flattenQuadraticWithArcLen,\n} from '../flatten';\nimport type { Mesh } from './mesh';\n\n/** Options for `tessellate`. A smaller tolerance means more triangles and\n * smoother curves; it is in path-local units, so callers rendering at a\n * larger scale should tighten it. */\nexport interface TessellateOptions {\n /** Flatness tolerance for bezier subdivision in path-local units. */\n flattenTolerance?: number;\n}\n\n/** Turn a path into a triangle mesh the renderer can draw: curves flattened to\n * line segments, then the resulting polygon triangulated. */\nexport function tessellate(path: Path, opts: TessellateOptions = {}): Mesh {\n if (path.kind === 'rect') return tessellateRect(path);\n return tessellatePolygon(path, opts);\n}\n\nfunction tessellateRect(p: RectPath): Mesh {\n const { x, y, width: w, height: h } = p;\n return {\n vertices: Float32Array.from(rectToContour(x, y, w, h)),\n indices: new Uint32Array([0, 1, 2, 0, 2, 3]),\n anchorA: new Uint32Array([0, 1, 2, 3]),\n anchorB: new Uint32Array([0, 1, 2, 3]),\n anchorT: new Float32Array([0, 0, 0, 0]),\n };\n}\n\ninterface FlattenedContours {\n coords: number[];\n contourStarts: number[];\n anchorA: number[];\n anchorB: number[];\n anchorT: number[];\n}\n\nfunction flattenPolygon(p: PolygonPath, tolerance: number): FlattenedContours {\n const { commands, coords } = p;\n const out: number[] = [];\n const anchorA: number[] = [];\n const anchorB: number[] = [];\n const anchorT: number[] = [];\n const contourStarts: number[] = [];\n let startAnchor = -1;\n let prevAnchor = -1;\n let anchorCounter = 0;\n\n // Anchor bookkeeping for the points a curve just appended: interior points\n // interpolate (prevAnchor → target); the last is pinned anchor-exact.\n const pushCurveAnchors = (anchorStart: number, arcAccum: number[], total: number, target: number): void => {\n for (let k = 0; k < arcAccum.length; k++) {\n anchorA.push(prevAnchor);\n anchorB.push(target);\n anchorT.push(total > 0 ? arcAccum[k] / total : 0);\n }\n const lastIdx = anchorStart + arcAccum.length - 1;\n anchorA[lastIdx] = target;\n anchorB[lastIdx] = target;\n anchorT[lastIdx] = 0;\n };\n\n forEachSegment(commands, coords, (cmd, coordIdx, prevX, prevY, _i, opensSubpath) => {\n if (opensSubpath) {\n const anchor = Math.max(startAnchor, 0);\n contourStarts.push(out.length / 2);\n out.push(prevX, prevY);\n anchorA.push(anchor);\n anchorB.push(anchor);\n anchorT.push(0);\n prevAnchor = anchor;\n }\n switch (cmd) {\n case PATH_M:\n case PATH_L: {\n if (cmd === PATH_M) {\n contourStarts.push(out.length / 2);\n startAnchor = anchorCounter;\n }\n out.push(coords[coordIdx], coords[coordIdx + 1]);\n anchorA.push(anchorCounter);\n anchorB.push(anchorCounter);\n anchorT.push(0);\n prevAnchor = anchorCounter;\n anchorCounter++;\n break;\n }\n case PATH_Q: {\n const target = anchorCounter;\n const arcAccum: number[] = [];\n const anchorStart = anchorA.length;\n const total = flattenQuadraticWithArcLen(\n prevX, prevY,\n coords[coordIdx], coords[coordIdx + 1],\n coords[coordIdx + 2], coords[coordIdx + 3],\n tolerance, out, arcAccum,\n );\n pushCurveAnchors(anchorStart, arcAccum, total, target);\n prevAnchor = target;\n anchorCounter++;\n break;\n }\n case PATH_C: {\n const target = anchorCounter;\n const arcAccum: number[] = [];\n const anchorStart = anchorA.length;\n const total = flattenCubicWithArcLen(\n prevX, prevY,\n coords[coordIdx], coords[coordIdx + 1],\n coords[coordIdx + 2], coords[coordIdx + 3],\n coords[coordIdx + 4], coords[coordIdx + 5],\n tolerance, out, arcAccum,\n );\n pushCurveAnchors(anchorStart, arcAccum, total, target);\n prevAnchor = target;\n anchorCounter++;\n break;\n }\n case PATH_Z:\n // The pen returns to the subpath start (forEachSegment does that); the\n // anchor it carries has to follow, or a curve after the Z interpolates\n // from the wrong end.\n prevAnchor = startAnchor;\n break;\n default:\n throw new Error(`tessellate: unknown command code ${cmd}`);\n }\n });\n\n return { coords: out, contourStarts, anchorA, anchorB, anchorT };\n}\n\nfunction tessellatePolygon(p: PolygonPath, opts: TessellateOptions): Mesh {\n const tolerance = opts.flattenTolerance ?? DEFAULT_FLATTEN_TOLERANCE;\n const { coords, contourStarts, anchorA, anchorB, anchorT } = flattenPolygon(p, tolerance);\n\n if (p.fillRule === 'evenodd') {\n return tessellateEvenoddWithAnchors(coords, contourStarts, anchorA, anchorB, anchorT);\n }\n\n // nonzero compound-path tessellation:\n // - The first contour establishes the reference winding direction.\n // - Subsequent contours with the SAME winding as the first are positives\n // (filled, disjoint shapes).\n // - Subsequent contours with OPPOSITE winding are holes; each is grouped\n // with the smallest positive whose polygon contains its first vertex.\n // - Each (positive, [its holes]) group is earcut'd independently;\n // triangles concatenated.\n // Authors mostly write disjoint-positives-with-same-winding; the previous\n // implementation passed every subsequent contour as a hole, which broke\n // those (a duck with body+head+beak, a hamburglar with brim+crown+cape).\n // Using shoelace sign relative to the first contour avoids guessing about\n // screen-down vs math-up axis conventions.\n\n const totalVerts = coords.length / 2;\n const contourEnd = (i: number): number =>\n i + 1 < contourStarts.length ? contourStarts[i + 1] : totalVerts;\n\n if (contourStarts.length <= 1) {\n const tri = earcut(coords);\n return {\n vertices: new Float32Array(coords),\n indices: new Uint32Array(tri),\n anchorA: new Uint32Array(anchorA),\n anchorB: new Uint32Array(anchorB),\n anchorT: new Float32Array(anchorT),\n };\n }\n\n const areas: number[] = contourStarts.map((s, i) => signedArea(coords, s, contourEnd(i)));\n const refSign = Math.sign(areas[0]) || 1;\n\n const positives: number[] = [];\n const negatives: number[] = [];\n for (let i = 0; i < contourStarts.length; i++) {\n if (areas[i] === 0) continue;\n if (Math.sign(areas[i]) === refSign) positives.push(i);\n else negatives.push(i);\n }\n\n if (positives.length === 1 && negatives.length > 0) {\n // Classic outer-with-holes pattern; pass directly to earcut.\n const holeIndices = contourStarts.slice(1);\n const tri = earcut(coords, holeIndices);\n return {\n vertices: new Float32Array(coords),\n indices: new Uint32Array(tri),\n anchorA: new Uint32Array(anchorA),\n anchorB: new Uint32Array(anchorB),\n anchorT: new Float32Array(anchorT),\n };\n }\n\n // Group each opposite-wound contour with the smallest positive that\n // contains its first vertex. Orphans (opposite-wound but not inside any\n // positive) get promoted to independent positives — author probably\n // intended them as separate shapes with inconsistent winding.\n const holesByPositive = new Map<number, number[]>();\n const orphanPositives: number[] = [];\n for (const n of negatives) {\n const px = coords[contourStarts[n] * 2];\n const py = coords[contourStarts[n] * 2 + 1];\n let bestPos = -1;\n let bestAbsArea = Infinity;\n for (const pos of positives) {\n const absArea = Math.abs(areas[pos]);\n if (absArea < bestAbsArea && pointInPolygon(coords, px, py, contourStarts[pos], contourEnd(pos))) {\n bestAbsArea = absArea;\n bestPos = pos;\n }\n }\n if (bestPos >= 0) {\n const arr = holesByPositive.get(bestPos) ?? [];\n arr.push(n);\n holesByPositive.set(bestPos, arr);\n } else {\n orphanPositives.push(n);\n }\n }\n\n const allPositives = [...positives, ...orphanPositives];\n\n const finalCoords: number[] = [];\n const finalAnchorA: number[] = [];\n const finalAnchorB: number[] = [];\n const finalAnchorT: number[] = [];\n const finalIndices: number[] = [];\n for (const pos of allPositives) {\n const holes = holesByPositive.get(pos) ?? [];\n const offset = finalCoords.length / 2;\n const groupCoords: number[] = [];\n const groupStarts: number[] = [0];\n for (let i = contourStarts[pos]; i < contourEnd(pos); i++) {\n groupCoords.push(coords[i * 2], coords[i * 2 + 1]);\n finalAnchorA.push(anchorA[i]);\n finalAnchorB.push(anchorB[i]);\n finalAnchorT.push(anchorT[i]);\n }\n for (const h of holes) {\n groupStarts.push(groupCoords.length / 2);\n for (let i = contourStarts[h]; i < contourEnd(h); i++) {\n groupCoords.push(coords[i * 2], coords[i * 2 + 1]);\n finalAnchorA.push(anchorA[i]);\n finalAnchorB.push(anchorB[i]);\n finalAnchorT.push(anchorT[i]);\n }\n }\n const tri = earcut(groupCoords, groupStarts.length > 1 ? groupStarts.slice(1) : undefined);\n for (const v of groupCoords) finalCoords.push(v);\n for (const idx of tri) finalIndices.push(idx + offset);\n }\n\n return {\n vertices: new Float32Array(finalCoords),\n indices: new Uint32Array(finalIndices),\n anchorA: new Uint32Array(finalAnchorA),\n anchorB: new Uint32Array(finalAnchorB),\n anchorT: new Float32Array(finalAnchorT),\n };\n}\n\nfunction tessellateEvenoddWithAnchors(\n coords: number[],\n contourStarts: number[],\n anchorA: number[],\n anchorB: number[],\n anchorT: number[],\n): Mesh {\n const indices: number[] = [];\n const totalVerts = coords.length / 2;\n for (let c = 0; c < contourStarts.length; c++) {\n const start = contourStarts[c];\n const end = c + 1 < contourStarts.length ? contourStarts[c + 1] : totalVerts;\n for (let i = start + 1; i < end - 1; i++) {\n indices.push(start, i, i + 1);\n }\n }\n return {\n vertices: new Float32Array(coords),\n indices: new Uint32Array(indices),\n requiresStencil: true,\n anchorA: new Uint32Array(anchorA),\n anchorB: new Uint32Array(anchorB),\n anchorT: new Float32Array(anchorT),\n };\n}\n\nfunction signedArea(coords: number[], start: number, end: number): number {\n let a = 0;\n for (let i = start; i < end; i++) {\n const j = i + 1 === end ? start : i + 1;\n a += coords[i * 2] * coords[j * 2 + 1] - coords[j * 2] * coords[i * 2 + 1];\n }\n return a * 0.5;\n}\n","/**\n * Shortening a flattened subpath so a filled marker is not speared by its own\n * line. SVG has no equivalent — it paints the marker over a full-length\n * stroke — so this is the one place our rendering deliberately differs.\n *\n * Runs before dash splitting, so a dash pattern fits the visible line rather\n * than running off under the head. The anchor-param interpolation matches\n * `splitForDash`'s rule for a boundary landing mid-segment.\n */\n\nimport type { Polyline } from './polyline';\n\nconst EPS = 1e-9;\n\ninterface Sample {\n x: number; y: number;\n a: number; b: number; t: number;\n w: number;\n /** Index of the first original point at or after this sample. */\n next: number;\n}\n\nfunction sampleAt(\n pl: Polyline, cum: Float64Array,\n A: Uint32Array, B: Uint32Array, T: Float32Array, W: Float32Array | undefined,\n dist: number,\n /** For a cut landing exactly on a vertex: whether the vertex belongs to the\n * run after the sample (a head) or before it (a tail), so it is kept once. */\n vertexFollows: boolean,\n): Sample {\n const n = cum.length;\n let i = 1;\n while (i < n - 1 && (vertexFollows ? cum[i] <= dist : cum[i] < dist)) i++;\n const segStart = cum[i - 1];\n const segLen = cum[i] - segStart;\n const f = segLen > EPS ? (dist - segStart) / segLen : 0;\n\n const px = pl.points[(i - 1) * 2], py = pl.points[(i - 1) * 2 + 1];\n const qx = pl.points[i * 2], qy = pl.points[i * 2 + 1];\n\n let a: number, b: number, t: number;\n if (A[i - 1] === A[i] && B[i - 1] === B[i]) {\n a = A[i - 1]; b = B[i - 1];\n t = T[i - 1] + (T[i] - T[i - 1]) * f;\n } else if (f < 0.5) {\n a = A[i - 1]; b = B[i - 1]; t = T[i - 1];\n } else {\n a = A[i]; b = B[i]; t = T[i];\n }\n\n const w = W ? W[i - 1] + (W[i] - W[i - 1]) * f : 0;\n return { x: px + (qx - px) * f, y: py + (qy - py) * f, a, b, t, w, next: i };\n}\n\n/**\n * Shorten `pl` by `startInset` from its first point and `endInset` from its\n * last, both in the same world units as the points.\n *\n * Returns `pl` itself when there is nothing to do (both insets zero, or the\n * subpath is closed and so has no free ends), and `null` when the insets\n * consume the whole run — a caller should then draw no ribbon at all.\n */\nexport function trimPolyline(\n pl: Polyline,\n startInset: number,\n endInset: number,\n): Polyline | null {\n const from = Math.max(0, startInset);\n const to = Math.max(0, endInset);\n if (from <= 0 && to <= 0) return pl;\n if (pl.closed) return pl;\n\n const n = pl.points.length / 2;\n if (n < 2) return null;\n\n const A = pl.anchorA ?? new Uint32Array(n);\n const B = pl.anchorB ?? new Uint32Array(n);\n const T = pl.anchorT ?? new Float32Array(n);\n const W = pl.widths;\n\n const cum = new Float64Array(n);\n for (let i = 1; i < n; i++) {\n const dx = pl.points[i * 2] - pl.points[(i - 1) * 2];\n const dy = pl.points[i * 2 + 1] - pl.points[(i - 1) * 2 + 1];\n cum[i] = cum[i - 1] + Math.hypot(dx, dy);\n }\n const total = cum[n - 1];\n const cutA = from;\n const cutB = total - to;\n if (cutB - cutA <= EPS) return null;\n\n const head = sampleAt(pl, cum, A, B, T, W, cutA, true);\n const tail = sampleAt(pl, cum, A, B, T, W, cutB, false);\n\n const points: number[] = [head.x, head.y];\n const aOut: number[] = [head.a];\n const bOut: number[] = [head.b];\n const tOut: number[] = [head.t];\n const wOut: number[] | undefined = W ? [head.w] : undefined;\n\n for (let i = head.next; i < tail.next; i++) {\n points.push(pl.points[i * 2], pl.points[i * 2 + 1]);\n aOut.push(A[i]); bOut.push(B[i]); tOut.push(T[i]);\n if (wOut) wOut.push(W![i]);\n }\n\n points.push(tail.x, tail.y);\n aOut.push(tail.a); bOut.push(tail.b); tOut.push(tail.t);\n if (wOut) wOut.push(tail.w);\n\n return {\n points,\n closed: false,\n anchorA: new Uint32Array(aOut),\n anchorB: new Uint32Array(bOut),\n anchorT: new Float32Array(tOut),\n ...(wOut ? { widths: new Float32Array(wOut) } : {}),\n };\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@weasel-js/geom",
3
- "version": "1.9.3",
3
+ "version": "1.9.4",
4
4
  "description": "Pure geometry kernel for @weasel-js/core: affine, box, curve, polyline, the Path command stream and its math, and easing curves in 2D. Dependency-free core; curve representations in ./curves, tessellation in ./tessellate (earcut), polygon booleans and path splitting in ./booleans (polygon-clipping), vectors, quaternions, 4x4 matrices and ray intersection in ./3d.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/box.ts","../src/tessellate/polyline.ts"],"names":[],"mappings":"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","file":"chunk-6T5I3PR5.js","sourcesContent":["/** Axis-aligned box as [minX, minY, maxX, maxY]. */\nexport type Box = readonly [number, number, number, number];\n\n/** An axis-aligned rectangle in object form. `Box` is the tuple form; this is\n * the one that survives being read by a human. */\nexport interface Rect { x: number; y: number; width: number; height: number }\n\n/** Tight bounds of an interleaved coord stream, or null if empty. */\nexport function boundsOfCoords(coords: ArrayLike<number>): Box | null {\n if (coords.length < 2) return null;\n let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;\n for (let i = 0; i + 1 < coords.length; i += 2) {\n const x = coords[i], y = coords[i + 1];\n if (x < minX) minX = x;\n if (y < minY) minY = y;\n if (x > maxX) maxX = x;\n if (y > maxY) maxY = y;\n }\n return [minX, minY, maxX, maxY];\n}\n\n/** Smallest box containing both inputs. */\nexport function unionBox(a: Box, b: Box): Box {\n return [\n Math.min(a[0], b[0]),\n Math.min(a[1], b[1]),\n Math.max(a[2], b[2]),\n Math.max(a[3], b[3]),\n ];\n}\n\n/** Inclusive point-in-box test. */\nexport function boxContainsPoint(b: Box, x: number, y: number): boolean {\n return x >= b[0] && x <= b[2] && y >= b[1] && y <= b[3];\n}\n\n/** Whether `outer` wholly holds `inner`, edges inclusive. Two boxes that merely\n * overlap answer false. */\nexport function boxContainsBox(outer: Box, inner: Box): boolean {\n return inner[0] >= outer[0] && inner[1] >= outer[1] && inner[2] <= outer[2] && inner[3] <= outer[3];\n}\n\n/** Interleaved corner ring for a rect at (x,y,w,h), wound clockwise from the\n * origin corner. The closing edge is implicit — the same unclosed shape\n * `pointInPolygon` takes, and what a repeated first vertex would leave as a\n * zero-length segment for anything that strokes it. */\nexport function rectToContour(x: number, y: number, w: number, h: number): Float64Array {\n return Float64Array.of(x, y, x + w, y, x + w, y + h, x, y + h);\n}\n","import { forEachSegment, PATH_M, PATH_L, PATH_Z, PATH_C, PATH_Q } from '../commands';\nimport { rectToContour } from '../box';\nimport { DEFAULT_FLATTEN_TOLERANCE, flattenCubicWithArcLen, flattenQuadraticWithArcLen } from '../flatten';\nimport type { Path, PolygonPath, RectPath } from '../path';\n\n/** One contour of a path, flattened to straight segments. */\nexport interface Polyline {\n /** Interleaved x,y vertices (length = 2 × point count). */\n points: number[];\n /** Whether the contour was closed (ends with Z, or is a RectPath). */\n closed: boolean;\n /** For each point, the previous anchor index. Anchor-aligned points set A === B. */\n anchorA?: Uint32Array;\n /** For each point, the next anchor index. */\n anchorB?: Uint32Array;\n /** For each point, the arc-length fraction along (A, B). 0 at anchor A; for anchor-aligned, set to 0. */\n anchorT?: Float32Array;\n /** Per-point stroke width, populated by the tessellator when the Stroke\n * carries `vertexWidths`. Undefined means uniform `Stroke.width`. */\n widths?: Float32Array;\n}\n\n/** Options for `extractPolylines`. */\nexport interface ExtractOptions {\n flattenTolerance?: number;\n}\n\n/** Flatten each contour of a path to a straight-segment polyline, carrying the\n * anchor parameterization per point. A rect yields one closed contour. */\nexport function extractPolylines(path: Path, opts: ExtractOptions = {}): Polyline[] {\n if (path.kind === 'rect') return [extractRect(path)];\n return extractPolygon(path, opts);\n}\n\nfunction extractRect(p: RectPath): Polyline {\n const { x, y, width: w, height: h } = p;\n return {\n points: Array.from(rectToContour(x, y, w, h)),\n closed: true,\n anchorA: new Uint32Array([0, 1, 2, 3]),\n anchorB: new Uint32Array([0, 1, 2, 3]),\n anchorT: new Float32Array([0, 0, 0, 0]),\n };\n}\n\nfunction extractPolygon(p: PolygonPath, opts: ExtractOptions): Polyline[] {\n const tolerance = opts.flattenTolerance ?? DEFAULT_FLATTEN_TOLERANCE;\n const { commands, coords } = p;\n const out: Polyline[] = [];\n // Anchors are numbered globally (across all contours) in command-stream order.\n let anchorCounter = 0;\n\n // Builders for the current polyline.\n let pts: number[] | null = null;\n let aA: number[] | null = null;\n let aB: number[] | null = null;\n let aT: number[] | null = null;\n let current: Polyline | null = null;\n\n let prevAnchor = -1;\n\n const beginContour = (): Polyline => {\n pts = [];\n aA = [];\n aB = [];\n aT = [];\n const next: Polyline = { points: pts, closed: false };\n out.push(next);\n return next;\n };\n\n /**\n * A closed contour's last point repeating its first is redundant — Z already\n * says \"return to the start\" — and it is *harmful*: it leaves a zero-length\n * closing segment, which the stroker discards along with the wrap-around\n * join it should have carried, notching the ribbon at the contour's start.\n *\n * Every font outline serialized by opentype.js is written this way, as is a\n * great deal of hand-written and exported SVG, so this is the common case\n * rather than a defensive edge. Exact equality is the right test: the\n * duplicate is a re-emission of the same number, not an approach to it, and\n * a near-miss is a genuine (if tiny) segment the author asked for.\n */\n const dropDuplicateClosingPoint = (): void => {\n if (!pts || !aA || !aB || !aT) return;\n const n = pts.length / 2;\n if (n < 2) return;\n if (pts[0] !== pts[(n - 1) * 2] || pts[1] !== pts[(n - 1) * 2 + 1]) return;\n pts.length -= 2;\n aA.length -= 1;\n aB.length -= 1;\n aT.length -= 1;\n };\n\n const commit = (target: Polyline): void => {\n if (!pts || !aA || !aB || !aT) return;\n target.anchorA = new Uint32Array(aA);\n target.anchorB = new Uint32Array(aB);\n target.anchorT = new Float32Array(aT);\n };\n\n // Fill anchorA/B/T for each point a curve just appended: interior points\n // interpolate (prevAnchor → target), and the final point is pinned to the\n // target so the draw-time lerp returns anchor B's color exactly.\n const pushCurveAnchors = (segStart: number, arcAccum: number[], total: number, target: number): void => {\n for (let k = 0; k < arcAccum.length; k++) {\n aA!.push(prevAnchor);\n aB!.push(target);\n aT!.push(total > 0 ? arcAccum[k] / total : 0);\n }\n const lastIdx = (segStart + arcAccum.length) - 1;\n aA![lastIdx] = target;\n aB![lastIdx] = target;\n aT![lastIdx] = 0;\n };\n\n forEachSegment(commands, coords, (cmd, coordIdx, prevX, prevY) => {\n switch (cmd) {\n case PATH_M:\n case PATH_L: {\n if (cmd === PATH_M) {\n if (current) commit(current);\n current = beginContour();\n }\n pts!.push(coords[coordIdx], coords[coordIdx + 1]);\n aA!.push(anchorCounter);\n aB!.push(anchorCounter);\n aT!.push(0);\n prevAnchor = anchorCounter;\n anchorCounter++;\n break;\n }\n case PATH_Q: {\n const target = anchorCounter;\n const segStart = pts!.length / 2;\n const arcAccum: number[] = [];\n const total = flattenQuadraticWithArcLen(\n prevX, prevY,\n coords[coordIdx], coords[coordIdx + 1],\n coords[coordIdx + 2], coords[coordIdx + 3],\n tolerance, pts!, arcAccum,\n );\n pushCurveAnchors(segStart, arcAccum, total, target);\n prevAnchor = target;\n anchorCounter++;\n break;\n }\n case PATH_C: {\n const target = anchorCounter;\n const segStart = pts!.length / 2;\n const arcAccum: number[] = [];\n const total = flattenCubicWithArcLen(\n prevX, prevY,\n coords[coordIdx], coords[coordIdx + 1],\n coords[coordIdx + 2], coords[coordIdx + 3],\n coords[coordIdx + 4], coords[coordIdx + 5],\n tolerance, pts!, arcAccum,\n );\n pushCurveAnchors(segStart, arcAccum, total, target);\n prevAnchor = target;\n anchorCounter++;\n break;\n }\n case PATH_Z: {\n if (current) {\n current.closed = true;\n dropDuplicateClosingPoint();\n }\n break;\n }\n default:\n throw new Error(`extractPolylines: unknown command code ${cmd}`);\n }\n });\n\n if (current) commit(current);\n return out;\n}\n"]}
@@ -1 +0,0 @@
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;AAcO,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-7ROQRYOA.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. Every\n * comparison of two *computed coordinates* goes through this — never `===`,\n * never an f64-tight literal.\n *\n * The exception is a guard against an exact algebraic value that a formula\n * produces bit-for-bit: a homogeneous `w === 1`, a ray's `d === 0`. Those are\n * testing a branch, not comparing coordinates, and `geom/3d` has two of them\n * (`mat4.ts`, `ray3.ts`). Widening one to `approxEq` would change which branch\n * runs, not how precisely it runs.\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"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/commands.ts"],"names":[],"mappings":";AAWO,IAAM,aAAA,GAAgB;AAAA;AAAA,EAE3B,CAAA,EAAG,EAAE,IAAA,EAAM,CAAA,EAAG,QAAQ,CAAA,EAAE;AAAA;AAAA,EAExB,CAAA,EAAG,EAAE,IAAA,EAAM,CAAA,EAAG,QAAQ,CAAA,EAAE;AAAA;AAAA,EAExB,CAAA,EAAG,EAAE,IAAA,EAAM,CAAA,EAAG,QAAQ,CAAA,EAAE;AAAA;AAAA,EAExB,CAAA,EAAG,EAAE,IAAA,EAAM,CAAA,EAAG,QAAQ,CAAA,EAAE;AAAA;AAAA;AAAA,EAGxB,CAAA,EAAG,EAAE,IAAA,EAAM,CAAA,EAAG,QAAQ,CAAA;AACxB;AAQO,IAAM,MAAA,GAAS,cAAc,CAAA,CAAE;AAE/B,IAAM,MAAA,GAAS,cAAc,CAAA,CAAE;AAE/B,IAAM,MAAA,GAAS,cAAc,CAAA,CAAE;AAE/B,IAAM,MAAA,GAAS,cAAc,CAAA,CAAE;AAE/B,IAAM,MAAA,GAAS,cAAc,CAAA,CAAE;AAG/B,IAAM,mBAAsC,eAAA;AAEnD,SAAS,eAAA,GAA4B;AACnC,EAAA,MAAM,UAAoB,EAAC;AAC3B,EAAA,KAAA,MAAW,EAAE,IAAA,EAAM,MAAA,EAAO,IAAK,MAAA,CAAO,OAAO,aAAa,CAAA,EAAG,OAAA,CAAQ,IAAI,CAAA,GAAI,MAAA;AAC7E,EAAA,OAAO,OAAA;AACT;AAGO,SAAS,sBAAsB,GAAA,EAAqB;AACzD,EAAA,OAAO,iBAAiB,GAAG,CAAA;AAC7B;AAaO,SAAS,cAAA,CACd,QAAA,EACA,MAAA,EACA,KAAA,EAOM;AACN,EAAA,IAAI,EAAA,GAAK,CAAA;AACT,EAAA,IAAI,EAAA,GAAK,GAAG,EAAA,GAAK,CAAA;AACjB,EAAA,IAAI,MAAA,GAAS,GAAG,MAAA,GAAS,CAAA;AACzB,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,QAAA,CAAS,QAAQ,CAAA,EAAA,EAAK;AACxC,IAAA,MAAM,GAAA,GAAM,SAAS,CAAC,CAAA;AACtB,IAAA,IAAI,MAAM,GAAA,EAAK,EAAA,EAAI,IAAI,EAAA,EAAI,CAAC,MAAM,KAAA,EAAO;AACzC,IAAA,MAAM,GAAA,GAAM,sBAAsB,GAAG,CAAA;AACrC,IAAA,IAAI,QAAQ,MAAA,EAAW,MAAM,IAAI,KAAA,CAAM,CAAA,qCAAA,EAAwC,GAAG,CAAA,CAAE,CAAA;AACpF,IAAA,IAAI,MAAM,CAAA,EAAG;AACX,MAAA,EAAA,GAAK,MAAA,CAAO,EAAA,GAAK,GAAA,GAAM,CAAC,CAAA;AACxB,MAAA,EAAA,GAAK,MAAA,CAAO,EAAA,GAAK,GAAA,GAAM,CAAC,CAAA;AACxB,MAAA,EAAA,IAAM,GAAA;AACN,MAAA,IAAI,QAAQ,MAAA,EAAQ;AAAE,QAAA,MAAA,GAAS,EAAA;AAAI,QAAA,MAAA,GAAS,EAAA;AAAA,MAAI;AAAA,IAClD,CAAA,MAAA,IAAW,QAAQ,MAAA,EAAQ;AACzB,MAAA,EAAA,GAAK,MAAA;AAAQ,MAAA,EAAA,GAAK,MAAA;AAAA,IACpB;AAAA,EACF;AACF","file":"chunk-HEZTRG2M.js","sourcesContent":["/**\n * SVG-style command-stream encoding — the kit's single declaration of the path\n * opcodes. `Path` (`./path`) 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\n/** Command code of `M` (moveTo). */\nexport const PATH_M = PATH_COMMANDS.M.code;\n/** Command code of `L` (lineTo). */\nexport const PATH_L = PATH_COMMANDS.L.code;\n/** Command code of `C` (cubic bezier). */\nexport const PATH_C = PATH_COMMANDS.C.code;\n/** Command code of `Q` (quadratic bezier). */\nexport const PATH_Q = PATH_COMMANDS.Q.code;\n/** Command code of `Z` (close subpath). */\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 *\n * A code `PATH_COMMANDS` does not declare throws once the visitor has seen it,\n * since the walker cannot tell how many coords it consumes.\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 === undefined) throw new Error(`forEachSegment: unknown command code ${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"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/flatten.ts","../src/polyline.ts"],"names":["len2"],"mappings":"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","file":"chunk-RQYCDPU5.js","sourcesContent":["/**\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","import { sign, dot, len2 } from './scalar';\n\n/**\n * Even-odd ray-cast point-in-polygon over an interleaved, unclosed contour\n * [x0,y0,x1,y1,…]. The closing edge (last→first) is implicit.\n *\n * `start`/`end` are vertex indices, not float offsets, and bound one contour\n * inside a buffer holding several.\n */\nexport function pointInPolygon(\n coords: ArrayLike<number>,\n px: number,\n py: number,\n start = 0,\n end = coords.length >> 1,\n): boolean {\n if (end - start < 3) return false;\n let inside = false;\n for (let i = start, j = end - 1; i < end; j = i++) {\n const xi = coords[i * 2], yi = coords[i * 2 + 1];\n const xj = coords[j * 2], yj = coords[j * 2 + 1];\n const crosses =\n (yi > py) !== (yj > py) &&\n px < ((xj - xi) * (py - yi)) / (yj - yi) + xi;\n if (crosses) inside = !inside;\n }\n return inside;\n}\n\n/**\n * True if segments (ax,ay)-(bx,by) and (cx,cy)-(dx,dy) intersect at a single\n * point. An endpoint landing on the other segment counts (a T-junction and a\n * shared endpoint both answer true) — hit-testing wants a grazing edge to\n * register. Collinear overlap answers false: there is no single crossing\n * point, so the sign test both segments rely on is zero on all four sides.\n */\nexport function segmentsCross(\n ax: number, ay: number, bx: number, by: number,\n cx: number, cy: number, dx: number, dy: number,\n): boolean {\n const d1 = sign((dx - cx) * (ay - cy) - (dy - cy) * (ax - cx));\n const d2 = sign((dx - cx) * (by - cy) - (dy - cy) * (bx - cx));\n const d3 = sign((bx - ax) * (cy - ay) - (by - ay) * (cx - ax));\n const d4 = sign((bx - ax) * (dy - ay) - (by - ay) * (dx - ax));\n return d1 !== d2 && d3 !== d4;\n}\n\n/** Squared distance from (px,py) to segment (ax,ay)-(bx,by), endpoint-clamped. */\nexport function pointSegmentDist2(\n px: number, py: number, ax: number, ay: number, bx: number, by: number,\n): number {\n const vx = bx - ax, vy = by - ay;\n const wx = px - ax, wy = py - ay;\n const vv = len2(vx, vy);\n let t = vv === 0 ? 0 : dot(wx, wy, vx, vy) / vv;\n t = t < 0 ? 0 : t > 1 ? 1 : t;\n const dx = px - (ax + t * vx), dy = py - (ay + t * vy);\n return len2(dx, dy);\n}\n"]}