@weasel-js/geom 1.10.1 → 1.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/README.md +9 -1
  2. package/dist/3d/index.d.ts +29 -2
  3. package/dist/3d/index.js +49 -1
  4. package/dist/3d/index.js.map +1 -1
  5. package/dist/booleans/index.d.ts +18 -11
  6. package/dist/booleans/index.js +432 -352
  7. package/dist/booleans/index.js.map +1 -1
  8. package/dist/chunk-4Y67BZL5.js +573 -0
  9. package/dist/chunk-4Y67BZL5.js.map +1 -0
  10. package/dist/chunk-6FGQML7D.js +152 -0
  11. package/dist/chunk-6FGQML7D.js.map +1 -0
  12. package/dist/{chunk-7WFFCHRL.js → chunk-7F66PQCJ.js} +6 -37
  13. package/dist/chunk-7F66PQCJ.js.map +1 -0
  14. package/dist/chunk-B53BERKG.js +386 -0
  15. package/dist/chunk-B53BERKG.js.map +1 -0
  16. package/dist/chunk-CE7IY7TB.js +104 -0
  17. package/dist/chunk-CE7IY7TB.js.map +1 -0
  18. package/dist/chunk-EAKE3N7W.js +804 -0
  19. package/dist/chunk-EAKE3N7W.js.map +1 -0
  20. package/dist/chunk-LRVPK7HI.js +491 -0
  21. package/dist/chunk-LRVPK7HI.js.map +1 -0
  22. package/dist/chunk-Q66NA2FU.js +174 -0
  23. package/dist/chunk-Q66NA2FU.js.map +1 -0
  24. package/dist/chunk-UI3FUWXM.js +533 -0
  25. package/dist/chunk-UI3FUWXM.js.map +1 -0
  26. package/dist/curvature-PkoLduGc.d.ts +454 -0
  27. package/dist/curves/index.d.ts +14 -5
  28. package/dist/curves/index.js +33 -111
  29. package/dist/curves/index.js.map +1 -1
  30. package/dist/index.d.ts +1511 -283
  31. package/dist/index.js +5755 -2674
  32. package/dist/index.js.map +1 -1
  33. package/dist/nd/index.d.ts +92 -27
  34. package/dist/nd/index.js +297 -0
  35. package/dist/nd/index.js.map +1 -1
  36. package/dist/path-BW8d_2RY.d.ts +157 -0
  37. package/dist/portCurve-C5HDWuuV.d.ts +30 -0
  38. package/dist/tessellate/index.d.ts +15 -4
  39. package/dist/tessellate/index.js +21 -277
  40. package/dist/tessellate/index.js.map +1 -1
  41. package/dist/warp/index.d.ts +254 -0
  42. package/dist/warp/index.js +1448 -0
  43. package/dist/warp/index.js.map +1 -0
  44. package/package.json +5 -1
  45. package/dist/chunk-7WFFCHRL.js.map +0 -1
  46. package/dist/chunk-IDXY2NCA.js +0 -177
  47. package/dist/chunk-IDXY2NCA.js.map +0 -1
  48. package/dist/chunk-NJ3IGAKR.js +0 -16
  49. package/dist/chunk-NJ3IGAKR.js.map +0 -1
  50. package/dist/chunk-OXH3NOXC.js +0 -62
  51. package/dist/chunk-OXH3NOXC.js.map +0 -1
  52. package/dist/chunk-URQMDR6Q.js +0 -80
  53. package/dist/chunk-URQMDR6Q.js.map +0 -1
  54. package/dist/cubicMath-BW-HJrCE.d.ts +0 -16
  55. package/dist/path-ljHxobyu.d.ts +0 -44
package/dist/index.d.ts CHANGED
@@ -1,7 +1,8 @@
1
- import { b as PathOpenFill, a as PolygonPath, c as PathFillRule, R as RectPath, P as Path } from './path-ljHxobyu.js';
2
- import { P as Point$1 } from './cubicMath-BW-HJrCE.js';
3
- export { c as cubicPointAt, s as splitCubicAtT } from './cubicMath-BW-HJrCE.js';
4
- export { PORT_REACH } from './nd/index.js';
1
+ import { c as PathOpenFill, P as PolygonPath, d as PathFillRule, a as Path, R as RectPath, b as Point, C as CornerSpec, e as CornerPiece } from './path-BW8d_2RY.js';
2
+ export { f as CORNER_FIT_TOLERANCE, g as CORNER_KEYWORDS, h as CornerKeyword, i as CornerShape, j as CornerShapeFrame, k as compactCorners, l as cornerAt, m as cornerCenter, n as cornerKeywordOf, o as cornerShapeK, p as cornerShapePieces, q as cornerShapePoint, r as cornerSpecAt, s as cubicPointAt, t as hasCorners, u as isCornerShape, v as lerpCorners, w as nextCornerShape, x as scaleCorners, y as splitCubicAtT, z as withCorner, A as withoutCorners } from './path-BW8d_2RY.js';
3
+ import { A as AnchorSet, P as PenAnchor, a as SpiroPoint, S as SpiroKind, b as Scale2 } from './curvature-PkoLduGc.js';
4
+ export { c as AnchorRect, d as CombTooth, e as CurvatureCombOptions, C as CurvatureSource, E as EulerFit, f as EulerSegment, g as SPIRO_KINDS, h as SegmentComb, i as SegmentHit, j as SpiroSegment, k as anchorAt, l as anchorCount, m as anchorsInRect, n as anchorsToPath, o as combTeeth, p as countPathAnchors, q as cubicCurvatureAt, r as cubicCurvatureSource, s as cubicDerivativeAt, t as curvatureComb, u as deleteAnchorsAt, v as editAnchorSet, w as eulerAngleAt, x as eulerCurvatureAt, y as eulerCurvatureDerivativesAt, z as eulerPointAt, B as fitEulerSegment, D as flatAnchorIndex, F as insertAnchorOnSegment, G as isAnchorSmooth, H as isSpiroKind, I as isStraightSegment, J as locateAnchor, K as moveHandleTo, L as nearestSegmentT, M as openSubpathAt, N as pathToAnchors, O as placeEulerSegment, Q as pxExtent, R as scaleDelta, T as screenAngleOf, U as segmentAt, V as segmentEnds, W as solveSpiro, X as standoff, Y as translateAnchorBy, Z as withinPxBox, _ as withinPxRadius } from './curvature-PkoLduGc.js';
5
+ export { P as PORT_REACH } from './portCurve-C5HDWuuV.js';
5
6
 
6
7
  /**
7
8
  * Scalar / 2-vector primitives and the kernel-wide epsilon policy.
@@ -203,6 +204,9 @@ declare function cubicEvalAt(x0: number, y0: number, x1: number, y1: number, x2:
203
204
  * quadratic endpoints. c1 = q0 + 2/3(ctrl-q0), c2 = q1 + 2/3(ctrl-q1).
204
205
  */
205
206
  declare function elevateQuadraticToCubic(q0x: number, q0y: number, cx: number, cy: number, q1x: number, q1y: number): [number, number, number, number];
207
+ /** The parameters in (0, 1) where one coordinate of a cubic, with control
208
+ * values `p0..p3`, turns: the roots of its derivative. */
209
+ declare function cubicAxisExtremaTs(p0: number, p1: number, p2: number, p3: number): number[];
206
210
  /** Tight AABB of a cubic, evaluating only extrema that lie on the curve. */
207
211
  declare function cubicBounds(x0: number, y0: number, x1: number, y1: number, x2: number, y2: number, x3: number, y3: number): Box;
208
212
  /** Quadratic Bezier point at parameter t (Bernstein form). */
@@ -375,6 +379,9 @@ declare class PathBuilder {
375
379
  }
376
380
  /** Construct a `RectPath` (the fast-path subtype). */
377
381
  declare function rectPath(x: number, y: number, width: number, height: number): RectPath;
382
+ /** `path` as a command stream drawing the same outline. A rect becomes its four
383
+ * corners clockwise from `(x, y)`, the order `countPathAnchors` numbers them in. */
384
+ declare function asPolygonPath(path: Path): PolygonPath;
378
385
  /** Build an open polyline from a flat list of points — the same geometry as
379
386
  * {@link polygonFromPoints} without the closing edge. A freehand stroke and a
380
387
  * measurement line want this; a region wants the closed one. */
@@ -421,10 +428,133 @@ declare function linePath(a: {
421
428
  /**
422
429
  * AABB of a `Path`, returned as a `RectPath` for direct reuse with rect-fast-path machinery.
423
430
  * Control points are NOT included directly; they're used only to compute extrema that actually
424
- * lie on the curve. Empty paths (no commands) return a zero-size rect anchored at the origin.
431
+ * lie on the curve. Corner shapes are bounded as they are drawn, expanded. Empty paths (no commands) return a zero-size rect anchored at the origin.
425
432
  */
426
433
  declare function boundsOfPath(path: Path): RectPath;
427
434
 
435
+ /**
436
+ * Corner expansion: a path's corner specs turned into the plain geometry
437
+ * that every reader draws, hits, bounds, and exports.
438
+ */
439
+
440
+ /** Where and how a corner anchor can be cut. */
441
+ interface CornerFrame {
442
+ /** Flat anchor index. */
443
+ index: number;
444
+ /** The anchor. */
445
+ x: number;
446
+ y: number;
447
+ /** Unit direction from the anchor into the wedge the cut is taken from. */
448
+ bisector: Point;
449
+ /** Half the angle between the two edges at the anchor. */
450
+ halfAngle: number;
451
+ /** How far along each edge the stored spec cuts, its setback, after clamping. */
452
+ trim: number;
453
+ /** The longest cut the edges allow while the neighbors keep theirs. */
454
+ maxTrim: number;
455
+ }
456
+ /** Every anchor of `path` that can take a corner, with the cut its spec
457
+ * makes now. */
458
+ declare function cornerFrames(path: PolygonPath): CornerFrame[];
459
+ /** The frame of the corner at flat anchor `index`, or null when that anchor
460
+ * cannot take one. */
461
+ declare function cornerFrameAt(path: PolygonPath, index: number): CornerFrame | null;
462
+ /** A path with its corners expanded, and where its anchors came from. */
463
+ interface ResolvedCorners {
464
+ path: PolygonPath;
465
+ /**
466
+ * For each anchor of `path` (each M, L, C, or Q, as `countPathAnchors`
467
+ * counts them), the anchor of the source path it belongs to, in the same
468
+ * numbering. Every point a corner's cut adds belongs to that corner's
469
+ * anchor. Null when the expansion added none.
470
+ */
471
+ anchorSources: Uint32Array | null;
472
+ }
473
+ /** {@link resolveCorners}, also answering which source anchor each anchor of
474
+ * the result came from, so an array kept per anchor (`vertexColors`) can be
475
+ * carried onto it with {@link remapPerAnchor}. */
476
+ declare function resolveCornersWithSources(path: PolygonPath): ResolvedCorners;
477
+ /**
478
+ * `path` with its corner specs expanded into plain geometry and dropped: each
479
+ * corner is cut `radius` along both edges and spans the cut with its shape's
480
+ * superellipse (`cornerShapePieces`). Each cut is clamped so the cuts on
481
+ * either end of a segment never overlap. A path with no corners comes back
482
+ * as itself, and so does a rect.
483
+ */
484
+ declare function resolveCorners<P extends Path>(path: P): P;
485
+ /** `values`, `stride` numbers per source anchor, as `stride` per anchor of
486
+ * the expanded path that `sources` describes. */
487
+ declare function remapPerAnchor<T>(values: readonly T[], sources: Uint32Array, stride: number): T[];
488
+ /** One corner of a path as its expansion draws it. */
489
+ interface CornerCut {
490
+ /** Flat anchor index. */
491
+ index: number;
492
+ anchor: Point;
493
+ spec: CornerSpec;
494
+ /** Where the cut leaves the edge into the anchor, and where it rejoins the edge out of it. */
495
+ start: Point;
496
+ end: Point;
497
+ /** The outline from `start` to `end`. */
498
+ pieces: CornerPiece[];
499
+ }
500
+ /** Every corner `path` cuts, in path order. */
501
+ declare function cornerCuts(path: PolygonPath): CornerCut[];
502
+
503
+ /**
504
+ * Putting corner specs back on a path an operation rebuilt from expanded
505
+ * geometry. Booleans, trims and cuts work on what a path draws, its corners
506
+ * cut and spanned (`resolveCorners`); wherever a corner's cut comes through
507
+ * whole, it folds back into its anchor and spec, and only a corner the
508
+ * operation cut into or moved stays expanded.
509
+ */
510
+
511
+ /** A corner a rebuilt path may hold expanded: the anchor and spec it folds
512
+ * back into, and the cut it is drawn as, from `start` to `end`. */
513
+ interface CornerTrace {
514
+ anchor: Point;
515
+ spec: CornerSpec;
516
+ start: Point;
517
+ end: Point;
518
+ pieces: readonly CornerPiece[];
519
+ }
520
+ /** How far a point may sit from where a corner draws it and still count as on it. */
521
+ declare const CORNER_RESTORE_TOLERANCE = 0.001;
522
+ /** The corners `path` cuts, as {@link restoreCorners} looks for them. */
523
+ declare function cornerTraces(path: Path): CornerTrace[];
524
+ /**
525
+ * `result` with the corners of `sources` folded back in wherever it still
526
+ * draws them whole: an operation's output, rebuilt from what the sources
527
+ * draw. A corner the operation cut into, or whose edges it moved, stays as
528
+ * the plain geometry it already is.
529
+ */
530
+ declare function keepCorners(sources: readonly Path[], result: PolygonPath, tolerance?: number): PolygonPath;
531
+ /**
532
+ * `result` with each of `traces` it draws whole folded back into its anchor
533
+ * and spec. A trace counts as drawn when a run of anchors goes from one end
534
+ * of its cut to the other along it, the edges either side carry on to its
535
+ * anchor, and the folded corner cuts the same again. Specs `result` already
536
+ * holds are kept.
537
+ */
538
+ declare function restoreCorners(result: PolygonPath, traces: readonly CornerTrace[], tolerance?: number): PolygonPath;
539
+
540
+ /**
541
+ * The corners an offset outline would hold as corners: each of the source's,
542
+ * moved to where its offset edges meet and resized so its cut keeps the
543
+ * same center.
544
+ */
545
+
546
+ /**
547
+ * Where the corners of `path` would sit on its outline grown by `distance`
548
+ * (shrunk by a negative one), for `restoreCorners` to look for. A corner
549
+ * moves with its edges and keeps its center, so its setback changes by
550
+ * `distance / tan(half the corner's angle)`: a round corner at a right angle
551
+ * grows its radius by exactly `distance`, and is then exactly what the offset
552
+ * draws. A shape whose offset is no longer that shape, or a corner between
553
+ * curved edges, draws differently from its trace, so `restoreCorners` leaves
554
+ * it expanded. A corner shrunk to nothing has no trace.
555
+ */
556
+ declare function offsetCornerTraces(path: Path, distance: number): CornerTrace[];
557
+
428
558
  /**
429
559
  * AABB union over a heterogeneous set of `Path` poses. Returns the
430
560
  * envelope as a `RectPath`, or `null` for empty input — analog of
@@ -486,7 +616,8 @@ declare function decomposePath(parent: Path, world: Path): Path;
486
616
  /** Split a path into one path per subpath, cutting at each `M`. A path with a
487
617
  * single subpath comes back as a one-element array. `fillRule` is propagated
488
618
  * unchanged, so even-odd compound paths with interior "holes" lose the hole
489
- * semantics — each subpath becomes its own filled region. */
619
+ * semantics — each subpath becomes its own filled region. Each subpath keeps
620
+ * the corner specs of its own anchors. */
490
621
  declare function splitSubpaths(path: PolygonPath): PolygonPath[];
491
622
 
492
623
  /** Whether any subpath of `path` lacks the `Z` that closes it. */
@@ -521,7 +652,7 @@ declare function pathSignedArea(path: Path): number;
521
652
  /**
522
653
  * `path` with every contour traversed backwards: same region, same curves,
523
654
  * opposite winding. A closed contour keeps its starting point; an open one
524
- * starts from where it used to end.
655
+ * starts from where it used to end. Corner specs stay on their anchors.
525
656
  */
526
657
  declare function reversePath(path: PolygonPath): PolygonPath;
527
658
 
@@ -546,26 +677,84 @@ declare function reversePath(path: PolygonPath): PolygonPath;
546
677
  declare function pathFromD(d: string, onWarn?: (message: string) => void): ReturnType<PathBuilder['build']>;
547
678
 
548
679
  /**
549
- * A station along a path: where it is at a fraction of its length, and which
550
- * way it is heading there.
680
+ * `pathToD` — a weasel `Path` as an SVG `d=` string, the inverse of
681
+ * `pathFromD`. `RectPath` lowers to `M h v h Z`; `PolygonPath` walks the
682
+ * (commands, coords) arrays, one SVG command per kit command, with corner
683
+ * shapes expanded into the geometry they draw.
551
684
  *
552
- * For anything positioned *along* geometry rather than beside it — a label on a
553
- * routed edge, a tick on a curve, a badge near an arrowhead. Curves are
554
- * flattened first, so the fraction is arc length along the drawn shape rather
555
- * than a curve parameter, which is what makes 0.5 look like the middle.
685
+ * Absolute commands only; numbers are rounded to 6 decimals.
556
686
  */
557
687
 
558
- /** The answer `pointAlongPath` gives: a point on the path and its heading there. */
688
+ /** `path` as SVG path data. */
689
+ declare function pathToD(given: Path): string;
690
+
691
+ /**
692
+ * A path measured once by arc length, so many stations along it cost a binary
693
+ * search each rather than a fresh flatten: what `pointAlongPath` answers one
694
+ * fraction at a time, and what anything placing or bending geometry along a
695
+ * path reads many times over.
696
+ */
697
+
698
+ /** A point on a path and its heading there. */
559
699
  interface PathStation {
560
- point: Point$1;
700
+ point: Point;
561
701
  /** Unit vector along the path at `point`, pointing toward the end. */
562
- tangent: Point$1;
702
+ tangent: Point;
563
703
  }
564
- /** Options for `pointAlongPath`. */
565
- interface PointAlongPathOptions {
704
+ /** Options for {@link measurePath}. */
705
+ interface MeasurePathOptions {
566
706
  /** Curve flattening tolerance, in world units. Default 0.5. */
567
707
  flattenTolerance?: number;
568
708
  }
709
+ /** The station on a path nearest a point. */
710
+ interface PathNearestStation extends PathStation {
711
+ /** Arc length at `point`, on the scale {@link PathMeasure.at} reads. */
712
+ s: number;
713
+ /** Distance from the queried point to `point`. */
714
+ dist: number;
715
+ }
716
+ /** A measured path: its length, and the station at any distance along it. */
717
+ interface PathMeasure {
718
+ /** Total arc length, every subpath counted in order. */
719
+ readonly length: number;
720
+ /** True when the path is a single closed contour, so a distance past the
721
+ * end can wrap round to the start. */
722
+ readonly closed: boolean;
723
+ /**
724
+ * The station `s` along the path, `s` clamped to `0..length`.
725
+ *
726
+ * The tangent is the heading of the flattened segment under `s`. With
727
+ * `smooth`, it is instead blended across each segment from the heading at
728
+ * one vertex to the next, so geometry bent along it turns without facets.
729
+ */
730
+ at(s: number, smooth?: boolean): PathStation;
731
+ /**
732
+ * The inverse of `at`: the station nearest `p`. On a tie the earliest
733
+ * segment wins. The tangent is the heading of the segment holding it.
734
+ */
735
+ nearest(p: Point): PathNearestStation;
736
+ }
737
+ /**
738
+ * Measure `path` by arc length. Subpaths are measured in order and treated as
739
+ * one run, the way a browser measures a whole `<path>`. Returns `null` for a
740
+ * path with no points; a path of zero length answers at its single point,
741
+ * heading along +X.
742
+ */
743
+ declare function measurePath(path: Path, opts?: MeasurePathOptions): PathMeasure | null;
744
+
745
+ /**
746
+ * A station along a path: where it is at a fraction of its length, and which
747
+ * way it is heading there.
748
+ *
749
+ * For anything positioned *along* geometry rather than beside it — a label on a
750
+ * routed edge, a tick on a curve, a badge near an arrowhead. Curves are
751
+ * flattened first, so the fraction is arc length along the drawn shape rather
752
+ * than a curve parameter, which is what makes 0.5 look like the middle. For
753
+ * many stations along one path, measure it once with `measurePath`.
754
+ */
755
+
756
+ /** Options for `pointAlongPath`. */
757
+ type PointAlongPathOptions = MeasurePathOptions;
569
758
  /**
570
759
  * Where `path` is at `t` of its total length, and its heading there.
571
760
  *
@@ -576,6 +765,144 @@ interface PointAlongPathOptions {
576
765
  */
577
766
  declare function pointAlongPath(path: Path, t: number, opts?: PointAlongPathOptions): PathStation | null;
578
767
 
768
+ /** One cubic segment, `[x0, y0, x1, y1, x2, y2, x3, y3]`, and whether it was
769
+ * drawn straight. A straight one keeps its controls at its thirds, so it
770
+ * interpolates and warps as a line would. */
771
+ interface CubicSegment {
772
+ c: [number, number, number, number, number, number, number, number];
773
+ line: boolean;
774
+ }
775
+ /** One contour of segments, each starting where the one before it ends. */
776
+ interface CubicContour {
777
+ segs: CubicSegment[];
778
+ closed: boolean;
779
+ }
780
+ /**
781
+ * `path`'s contours as cubic segments. A closed contour whose last point
782
+ * stops short of its first gains the straight closing edge it is drawn with;
783
+ * zero-length straight segments are dropped. A contour with no segments is a
784
+ * lone point and is left out. Corner specs are expanded first.
785
+ */
786
+ declare function pathToCubicContours(path: Path): CubicContour[];
787
+ /** The path drawing `contours`: a straight segment as `L`, the rest as `C`. */
788
+ declare function cubicContoursToPath(contours: readonly CubicContour[], fillRule?: PathFillRule): PolygonPath;
789
+
790
+ /**
791
+ * Shape interpolation between two paths: the steps of a blend, or the frames
792
+ * of a morph.
793
+ *
794
+ * The two shapes are matched once — contour to contour, then segment to
795
+ * segment — and every step is a straight lerp of the matched control points.
796
+ * Where one contour has fewer segments, its longest ones are split in half
797
+ * until the counts agree, which adds anchors without moving the outline.
798
+ */
799
+
800
+ /** How a blend matches the second shape's anchors to the first's. */
801
+ interface BlendPathsOptions {
802
+ /**
803
+ * Choose, for each pair of contours, the start point (and, when `reverse`
804
+ * is unset, the direction) of the second that keeps matched anchors
805
+ * closest, with both contours centered on their own middles first so that
806
+ * where the shapes sit does not decide it. Default `true`.
807
+ */
808
+ autoAlign?: boolean;
809
+ /**
810
+ * Turn the second shape's start point this many anchors further round each
811
+ * closed contour, after any `autoAlign` choice. Negative turns it back.
812
+ * Default 0.
813
+ */
814
+ startOffset?: number;
815
+ /** Run the second shape's contours backwards. Unset, `autoAlign` decides;
816
+ * without it, they run as drawn. */
817
+ reverse?: boolean;
818
+ }
819
+ /** Two shapes matched for interpolation. */
820
+ interface PathBlend {
821
+ /** The shape `t` of the way from the first to the second: exactly the
822
+ * first at 0 and the second at 1, up to the anchors matching added. */
823
+ at(t: number): PolygonPath;
824
+ /** Segments per matched pair of contours. */
825
+ readonly segmentCounts: readonly number[];
826
+ }
827
+ /** The shape `t` of the way from `a` to `b`. Matching once with
828
+ * {@link prepareBlend} is cheaper when several steps are wanted. */
829
+ declare function blendPaths(a: Path, b: Path, t: number, opts?: BlendPathsOptions): PolygonPath;
830
+ /** Match `a` to `b` for interpolation. */
831
+ declare function prepareBlend(a: Path, b: Path, opts?: BlendPathsOptions): PathBlend;
832
+
833
+ /**
834
+ * Bend a shape along a spine: the shape's x becomes distance along the spine
835
+ * and its y distance off it, along the spine's normal. A straight edge of the
836
+ * shape comes out curved wherever the spine bends, so each segment is
837
+ * sampled through the warp and refit to cubics within a tolerance; anchors
838
+ * stay where they were, so a corner of the shape stays a corner.
839
+ */
840
+
841
+ /** How a shape is laid along its spine. */
842
+ interface BendAlongPathOptions {
843
+ /**
844
+ * `'stretch'`, the default, spreads the shape's width over the spine's
845
+ * whole length. `'natural'` keeps its width: one unit across the shape is
846
+ * one unit along the spine, starting at the spine's start, and a shape
847
+ * longer than the spine runs on straight past its end.
848
+ */
849
+ fit?: 'stretch' | 'natural';
850
+ /** Where across the shape's height the spine runs, 0 at its top and 1 at
851
+ * its bottom. Default 0.5, the middle. */
852
+ baseline?: number;
853
+ /** Lay the shape on the other side of the spine, mirrored across it. */
854
+ flip?: boolean;
855
+ /** How far the refit curves may stray from the exact bend, in world
856
+ * units. Default 0.5. */
857
+ tolerance?: number;
858
+ }
859
+ /**
860
+ * `shape` bent along `spine`. A spine heading left to right keeps the shape
861
+ * upright; one heading the other way turns it over, as a road sign painted
862
+ * along a lane does. Returns `null` when the spine has no length or the shape
863
+ * nothing to bend.
864
+ */
865
+ declare function bendAlongPath(shape: Path, spine: Path, opts?: BendAlongPathOptions): PolygonPath | null;
866
+
867
+ /** How copies are spaced along a path. */
868
+ interface RepeatAlongPathOptions {
869
+ /**
870
+ * How many copies. With no `spacing`, they spread evenly over the whole
871
+ * path — end to end on an open one, evenly round a closed one — and the
872
+ * default is 5. With a `spacing`, it caps the run; unset, as many as fit.
873
+ */
874
+ count?: number;
875
+ /** Distance along the path from one copy's center to the next. */
876
+ spacing?: number;
877
+ /** Where a spaced run that is shorter than the path sits on it. Default
878
+ * `'start'`. */
879
+ align?: 'start' | 'center' | 'end';
880
+ /** Slide every copy this far along the path. On an open path a copy slid
881
+ * off either end is dropped; round a closed one it wraps. Default 0. */
882
+ offset?: number;
883
+ /** Turn each copy to the path's heading where it sits. Default `true`. */
884
+ orient?: boolean;
885
+ /** Curve flattening tolerance for measuring the path. Default 0.5. */
886
+ flattenTolerance?: number;
887
+ }
888
+ /** Where one copy sits. */
889
+ interface RepeatStation {
890
+ point: Point;
891
+ /** The path's heading there, radians clockwise from +X in a y-down frame. */
892
+ angle: number;
893
+ /** Arc length from the path's start. */
894
+ distance: number;
895
+ }
896
+ /** The stations copies sit at along `path`, in order. Empty for a path with
897
+ * no points. */
898
+ declare function stationsAlongPath(path: Path, opts?: RepeatAlongPathOptions): RepeatStation[];
899
+ /**
900
+ * Copies of `shape`, each centered on a station along `path` — its bounding
901
+ * box's middle on the path — and, with `orient`, turned to the heading
902
+ * there. The shape's own +X runs along the path.
903
+ */
904
+ declare function repeatAlongPath(shape: Path, path: Path, opts?: RepeatAlongPathOptions): Path[];
905
+
579
906
  /**
580
907
  * Pure-geometry distance from a point to a path's boundary (stroke), with
581
908
  * no fill-side logic. Used by pickers that want to know "how close is this
@@ -593,89 +920,313 @@ declare function pointAlongPath(path: Path, t: number, opts?: PointAlongPathOpti
593
920
  * combine with `pathContainsPoint` at the call site. */
594
921
  declare function pathDistanceToPoint(path: Path, px: number, py: number): number;
595
922
 
923
+ /** Where two Bézier segments cross, by subdivision then Newton refinement. */
924
+
925
+ /** One crossing of segments `a` and `b`: the parameter on each, and the point. */
926
+ interface SegmentCrossing {
927
+ ta: number;
928
+ tb: number;
929
+ x: number;
930
+ y: number;
931
+ }
596
932
  /**
597
- * Counts the path anchors used by the per-anchor coloring surface. An
598
- * "anchor" is the destination point of a path command: M, L, C, Q each
599
- * contribute one (the (x, y) where the pen ends up); Z contributes none
600
- * (it closes back to the subpath's first M). RectPath has four implicit
601
- * anchors — the corners — matching its M/L/L/L/Z stroke tessellation.
602
- *
603
- * Consumers use this to size their per-anchor color array; the renderer
604
- * uses it to validate the array length in dev builds.
933
+ * Every point where segment `a` crosses or touches segment `b` — each a line,
934
+ * quadratic or cubic given by its control points — with the parameter on
935
+ * each. Two lines are solved exactly; a curve is subdivided until its pieces
936
+ * are flat, their chords crossed, and the answer refined against the curves.
937
+ * Segments that overlap along a stretch report at most a few points of it.
938
+ * Sorted by `ta`.
939
+ */
940
+ declare function intersectSegments(a: Point[], b: Point[]): SegmentCrossing[];
941
+
942
+ /** A path's stroke as a flat list of segments, each knowing where it sits. */
943
+
944
+ /** One segment of a path's stroke, in the order the path draws them. */
945
+ interface PathSegment {
946
+ /** Control points: 2 for a line, 3 for a quadratic, 4 for a cubic. */
947
+ pts: Point[];
948
+ /** Index of its subpath among the path's subpaths. */
949
+ sub: number;
950
+ /** Index within its subpath. */
951
+ index: number;
952
+ /** Segments in its subpath. */
953
+ count: number;
954
+ /** Whether its subpath is closed, so its last segment meets its first. */
955
+ closed: boolean;
956
+ /** Axis-aligned box of the control points, which holds the segment. */
957
+ box: {
958
+ x0: number;
959
+ y0: number;
960
+ x1: number;
961
+ y1: number;
962
+ };
963
+ }
964
+ /** `path`'s stroke as segments: a closed subpath includes its closing edge,
965
+ * an open one does not, and a zero-length line is left out. */
966
+ declare function pathSegments(path: Path): PathSegment[];
967
+
968
+ /** Where paths cross one another and themselves. */
969
+
970
+ /** A place on a path's stroke: which segment, and how far along it. */
971
+ interface PathStop {
972
+ /** Index of the path in the list it came from. */
973
+ path: number;
974
+ sub: number;
975
+ /** Segment index within the subpath. */
976
+ index: number;
977
+ /** Parameter on that segment, in [0, 1]. */
978
+ t: number;
979
+ }
980
+ /** A point where two strokes cross or touch, and where it falls on each. */
981
+ interface PathCrossing {
982
+ x: number;
983
+ y: number;
984
+ a: PathStop;
985
+ b: PathStop;
986
+ }
987
+ /**
988
+ * Every crossing among `paths`: between each pair, and — unless `self` is
989
+ * false — of a path with itself, leaving out the joint where one segment
990
+ * meets the next. Points where strokes merely touch count too. With `of`,
991
+ * only the crossings involving that one path.
605
992
  */
993
+ declare function pathCrossings(paths: readonly Path[], opts?: {
994
+ self?: boolean;
995
+ of?: number;
996
+ }): PathCrossing[];
606
997
 
607
- /** One anchor of an editable path: its on-curve point plus the two control
608
- * handles that shape the segments either side of it. Handles are in the same
609
- * space as the point, and absent when the adjoining segment is straight. */
610
- interface PenAnchor {
998
+ /**
999
+ * Geometric snapping onto paths: the points on a set of strokes a drawn or
1000
+ * dragged point can lock to, and which of them a probe lands on.
1001
+ */
1002
+
1003
+ /**
1004
+ * What a snap target is.
1005
+ *
1006
+ * - `anchor` — an end of a segment: a path's anchors, a box's corners.
1007
+ * - `center` — a point a caller names as the middle of something: a text or
1008
+ * image box's center, given to {@link createPathSnapIndex} as a target.
1009
+ * - `intersection` — where two strokes cross, or one crosses itself.
1010
+ * - `tangent` — where a line from the query's origin touches a curve.
1011
+ * - `perpendicular` — where a line from the origin meets a stroke square on.
1012
+ * - `midpoint` — the middle of a segment by length.
1013
+ * - `extremum` — on a curve, where its tangent turns horizontal or vertical.
1014
+ * - `quadrant` — where a closed subpath crosses the horizontal and vertical
1015
+ * lines through the center of its box: a circle's four compass points.
1016
+ * - `nearest` — the closest point on any stroke, when nothing else is in range.
1017
+ */
1018
+ type PathSnapKind = 'anchor' | 'center' | 'intersection' | 'tangent' | 'perpendicular' | 'midpoint' | 'extremum' | 'quadrant' | 'nearest';
1019
+ /** Every snap kind, in the order a picker lists them. */
1020
+ declare const PATH_SNAP_KINDS: readonly PathSnapKind[];
1021
+ /** The kinds whose targets stand whatever the probe. */
1022
+ type StaticPathSnapKind = 'anchor' | 'center' | 'intersection' | 'midpoint' | 'extremum' | 'quadrant';
1023
+ /** A target the probe landed on. */
1024
+ interface PathSnapHit {
1025
+ kind: PathSnapKind;
611
1026
  x: number;
612
1027
  y: number;
613
- inHandle?: {
614
- x: number;
615
- y: number;
616
- };
617
- outHandle?: {
1028
+ /** Distance from the probe, in the query's `radius` units. */
1029
+ distance: number;
1030
+ /** Indices of the paths that make the target: two for a crossing between
1031
+ * paths, one otherwise. */
1032
+ paths: readonly number[];
1033
+ }
1034
+ /** A query for {@link findPathSnap}. */
1035
+ interface PathSnapQuery {
1036
+ /** How far from the probe a target may be, in the paths' units times
1037
+ * `scale`. */
1038
+ radius: number;
1039
+ /** Per-axis scale from the paths' units to the units `radius` is in — a
1040
+ * view's, to measure the radius in screen pixels under any zoom. Default
1041
+ * `{ x: 1, y: 1 }`. */
1042
+ scale?: {
618
1043
  x: number;
619
1044
  y: number;
620
1045
  };
1046
+ /** Kinds to consider. Absent, all of them. */
1047
+ kinds?: Iterable<PathSnapKind>;
1048
+ /** Where the line being drawn starts. Tangent and perpendicular targets are
1049
+ * measured from it, and there are none without it. */
1050
+ origin?: Point;
1051
+ /** Paths by index that offer no targets — the ones a drag is moving. */
1052
+ skip?: (path: number) => boolean;
621
1053
  }
1054
+ /** A target that stands whatever the probe: an anchor, a center, a crossing,
1055
+ * a midpoint, an extremum or a quadrant point. */
1056
+ interface PathSnapTarget {
1057
+ kind: StaticPathSnapKind;
1058
+ x: number;
1059
+ y: number;
1060
+ paths: readonly number[];
1061
+ }
1062
+ /** A set of paths, prepared for repeated snapping. Static targets are
1063
+ * computed on first use and kept. */
1064
+ interface PathSnapIndex {
1065
+ readonly paths: readonly Path[];
1066
+ /** Each path's segments. */
1067
+ readonly segments: readonly (readonly PathSegment[])[];
1068
+ /** The targets that do not depend on the probe, of one kind. */
1069
+ targets(kind: StaticPathSnapKind): readonly PathSnapTarget[];
1070
+ }
1071
+ /** Prepare `paths` for {@link findPathSnap}. Build one per set of paths and
1072
+ * reuse it while they stand: a crossing search is quadratic in segments.
1073
+ * `extra` adds targets of the caller's own — the center of a box, a point
1074
+ * with no segment at it — each naming the path it belongs to. */
1075
+ declare function createPathSnapIndex(paths: readonly Path[], extra?: readonly PathSnapTarget[]): PathSnapIndex;
622
1076
  /**
623
- * Derive a per-subpath anchor model from a PolygonPath. Subpaths split on
624
- * every `M` command; a subpath is closed iff it ends with `Z`.
625
- *
626
- * Cubic-segment control points become the outHandle of the previous anchor
627
- * and the inHandle of the next anchor. A closed subpath whose last curve ends
628
- * exactly on its first point holds that point twice; the two are one anchor,
629
- * and the curve's second control is that anchor's inHandle. Quadratic segments are upgraded to
630
- * cubics (each control reused for both adjacent handles) — this loses no
631
- * geometry. Linear segments produce anchors with no handles.
632
- */
633
- declare function pathToAnchors(path: PolygonPath): {
634
- anchors: PenAnchor[][];
635
- closed: boolean[];
636
- };
1077
+ * The snap target nearest `probe` within `query.radius`, or null when none
1078
+ * is in range. Every enabled kind competes on distance, except `nearest`,
1079
+ * which answers only when no other target is in range.
1080
+ */
1081
+ declare function findPathSnap(index: PathSnapIndex, probe: Point, query: PathSnapQuery): PathSnapHit | null;
637
1082
  /**
638
- * Serialize the per-subpath anchor model back to a PolygonPath. Inverse of
639
- * `pathToAnchors`. Curve-vs-line decision per segment:
640
- * - Both adjacent handles absent → straight L segment.
641
- * - Either handle present → C segment, with missing handles defaulting to
642
- * the anchor point itself (degenerate but valid; renders as a near-line).
643
- * Given `like`, the path being reshaped, the result keeps its fill rules.
1083
+ * Every snap target within `query.radius` of `probe`, unsorted. `nearest`
1084
+ * hits appear only when no other target is in range. Tangent and perpendicular targets
1085
+ * closer to the origin than the radius are dropped, so a line cannot snap
1086
+ * back onto its own start.
644
1087
  */
645
- declare function anchorsToPath(anchors: PenAnchor[][], closed: boolean[], like?: PolygonPath): PolygonPath;
1088
+ declare function findPathSnaps(index: PathSnapIndex, probe: Point, query: PathSnapQuery): PathSnapHit[];
1089
+
646
1090
  /**
647
- * Returns true if the anchor's in-handle and out-handle are collinear with
648
- * the anchor point, indicating "smooth" (mirror-drag) behavior. Detected via
649
- * the magnitude of the normalized cross product of the two handle vectors.
1091
+ * Trim: remove the piece of a stroke between the crossings on either side of
1092
+ * a point, as a drafting trim does.
1093
+ */
1094
+
1095
+ /** Options for {@link trimPathAt}. */
1096
+ interface TrimPathOptions {
1097
+ /** How far from the stroke `probe` may be. Default: any distance. */
1098
+ radius?: number;
1099
+ }
1100
+ /** What {@link trimPathAt} did. */
1101
+ interface TrimResult {
1102
+ /** The path with the piece gone; it has no commands when nothing is left. */
1103
+ path: PolygonPath;
1104
+ /** The piece removed, as an open path. */
1105
+ removed: PolygonPath;
1106
+ }
1107
+ /**
1108
+ * Remove the piece of `path`'s stroke that `probe` is nearest, bounded by the
1109
+ * nearest crossings on either side — with any of `cutters`, or with the path
1110
+ * itself. On an open subpath an end with no crossing before it bounds the
1111
+ * piece too, so a subpath touched only at its ends goes whole; a closed
1112
+ * subpath is opened, and one crossed at a single point is removed whole.
650
1113
  *
651
- * Edge cases:
652
- * - Missing in or out handle → false (corner by definition).
653
- * - Either handle at zero distance from anchor → false.
654
- */
655
- declare function isAnchorSmooth(a: PenAnchor): boolean;
656
- /** How many anchors a path has. Matches the per-anchor arrays the renderer
657
- * expects for `vertexColors`. */
658
- declare function countPathAnchors(path: Path): number;
659
- /** The segment `(sub, segIdx)` as its two end anchors, or null when it
660
- * doesn't exist. `segIdx === sub.length - 1` names a closed subpath's
661
- * closing segment, which runs from the last anchor back to the first. */
662
- declare function segmentEnds(anchors: readonly PenAnchor[][], closed: readonly boolean[] | undefined, sub: number, segIdx: number): {
663
- a: PenAnchor;
664
- b: PenAnchor;
665
- } | null;
666
- /** Whether the segment from `a` to `b` is a straight line (no handles). */
667
- declare function isStraightSegment(a: PenAnchor, b: PenAnchor): boolean;
668
- /** The segment of a decoded path nearest `(wx, wy)`, and the parameter `t`
669
- * on it closest to that point. Pass `closed` (from `pathToAnchors`) to
670
- * include each closed subpath's closing segment, reported as
671
- * `segIdx === sub.length - 1`. `t` spans `[0, 1]`, endpoints included.
672
- * Returns `null` only when there are no segments. */
673
- declare function nearestSegmentT(anchors: PenAnchor[][], wx: number, wy: number, closed?: readonly boolean[]): {
1114
+ * Returns null when the probe is further than `radius` from the stroke, or
1115
+ * when nothing crosses or touches the subpath it is on. Curves are split where they are
1116
+ * cut and keep their type; other subpaths are left as they were.
1117
+ */
1118
+ declare function trimPathAt(path: Path, cutters: readonly Path[], probe: Point, opts?: TrimPathOptions): TrimResult | null;
1119
+
1120
+ /** What stays put of a path while some of its anchors move. */
1121
+ interface PathAwayFromAnchors {
1122
+ /** The segments touching none of the moving anchors, as open runs; a
1123
+ * subpath none of them is on stays as it was. */
1124
+ path: PolygonPath;
1125
+ /** Every anchor that is not moving, a lone one with no segment left at it
1126
+ * included. */
1127
+ anchors: Point[];
1128
+ }
1129
+ /**
1130
+ * The part of `path` that holds still while the anchors at `moving` (flat
1131
+ * indices, as anchor editing numbers them) are dragged: every segment with a
1132
+ * moving anchor at either end is dropped, and so are the moving anchors.
1133
+ */
1134
+ declare function pathAwayFromAnchors(path: PolygonPath, moving: Iterable<number>): PathAwayFromAnchors;
1135
+
1136
+ /**
1137
+ * Growing an open end of a path along its tangent: by a distance, or until it
1138
+ * meets another stroke.
1139
+ */
1140
+
1141
+ /** One end of an open subpath. `sub` counts subpaths as the path's anchor set
1142
+ * (`pathToAnchors`) does, a bare `M` included. */
1143
+ interface OpenPathEnd {
674
1144
  sub: number;
675
- segIdx: number;
676
- t: number;
1145
+ end: 'first' | 'last';
1146
+ }
1147
+ /** Every end of every open subpath of `path` that has a direction to grow in. */
1148
+ declare function openPathEnds(path: Path): OpenPathEnd[];
1149
+ /** Where `end` sits and the unit direction it points out along, or null when
1150
+ * it is no open end or has no direction there. */
1151
+ declare function openEndRay(path: Path, end: OpenPathEnd): {
1152
+ at: Point;
1153
+ dir: Point;
1154
+ } | null;
1155
+ /**
1156
+ * `path` with `end` carried `distance` further along its tangent, by
1157
+ * `lengthenPathEnd` in `'tangent'` mode: a straight end segment grows longer,
1158
+ * and a curved one gains a straight segment, which keeps the tangent
1159
+ * continuous. Null when the end is not open or has no direction, or
1160
+ * `distance` is not positive.
1161
+ */
1162
+ declare function lengthenOpenEnd(path: Path, end: OpenPathEnd, distance: number): PolygonPath | null;
1163
+ /** Options for {@link extendToMeet}. */
1164
+ interface ExtendToMeetOptions {
1165
+ /** The furthest the end may travel. Default: as far as any stroke reaches. */
1166
+ maxDistance?: number;
1167
+ }
1168
+ /**
1169
+ * Extend `end` of `path` along its tangent to the first stroke it meets —
1170
+ * one of `boundaries`, or `path`'s own other segments. Returns the extended
1171
+ * path, the point it now ends at and how far it went, or null when the
1172
+ * tangent meets nothing.
1173
+ */
1174
+ declare function extendToMeet(path: Path, boundaries: readonly Path[], end: OpenPathEnd, opts?: ExtendToMeetOptions): {
1175
+ path: PolygonPath;
1176
+ at: Point;
1177
+ distance: number;
677
1178
  } | null;
678
1179
 
1180
+ /**
1181
+ * Grow or trim an open subpath at one of its ends. Lengthen drags this, and
1182
+ * Extend to next path reaches it through `lengthenOpenEnd`.
1183
+ *
1184
+ * A positive distance extends the end outward: straight along the end tangent,
1185
+ * or along a circular arc with the curvature the end has, which meets the path
1186
+ * with matching direction and curvature. A straight end segment is lengthened
1187
+ * in place; a curved one is continued with a new segment. A negative distance
1188
+ * trims the path back along itself by arc length, whichever way it would have
1189
+ * grown.
1190
+ *
1191
+ * The arc rather than extrapolating the end cubic past t = 1: a cubic's
1192
+ * leading term takes over beyond its range, so a continued curve swings off
1193
+ * and curls on itself within a segment's length, while the arc keeps the
1194
+ * curvature the end shows for as long as it is drawn.
1195
+ */
1196
+
1197
+ /** How `lengthenPathEnd` grows an end: straight on, or bending as the end bends. */
1198
+ type LengthenMode = 'tangent' | 'curvature';
1199
+ /** Where an end is, which way it heads out of the path, and how it bends there. */
1200
+ interface PathEndFrame {
1201
+ point: Point;
1202
+ /** Unit vector pointing out of the path. */
1203
+ tangent: Point;
1204
+ /** Signed curvature along `tangent`: positive turns toward `(-tangent.y, tangent.x)`. */
1205
+ curvature: number;
1206
+ }
1207
+ /** The end of an open subpath that the anchor at `flatIndex` is, or null when it is
1208
+ * an inner anchor, on a closed subpath, or alone in its subpath. */
1209
+ declare function openEndAt(set: AnchorSet, flatIndex: number): OpenPathEnd | null;
1210
+ /** Flat index of the anchor at `end`, or -1 when there is none. */
1211
+ declare function pathEndAnchorIndex(set: AnchorSet, end: OpenPathEnd): number;
1212
+ /** The frame at `end`, or null when it is not the end of an open subpath of two or
1213
+ * more anchors, or the path has no direction there. */
1214
+ declare function pathEndFrame(set: AnchorSet, end: OpenPathEnd): PathEndFrame | null;
1215
+ /**
1216
+ * Lengthen `end` by `distance` (see the module comment), in place. A curvature arc
1217
+ * stops at one full turn. Returns false when `end` is not the end of an open
1218
+ * subpath or nothing changed.
1219
+ */
1220
+ declare function lengthenPathEnd(set: AnchorSet, end: OpenPathEnd, distance: number, mode: LengthenMode): boolean;
1221
+ /**
1222
+ * The distance `lengthenPathEnd` takes for its new end to land nearest `point`: the
1223
+ * point projected onto the end tangent, or for a curvature lengthening, measured
1224
+ * around the circle of curvature. A measurement around the circle can name the
1225
+ * same spot a turn apart; it answers the one nearest `near`, so a drag passing
1226
+ * half a turn keeps going instead of jumping back.
1227
+ */
1228
+ declare function lengthToward(set: AnchorSet, end: OpenPathEnd, mode: LengthenMode, point: Point, near?: number): number;
1229
+
679
1230
  /**
680
1231
  * Controls for the one cubic that replaces `prev → removed → next` when
681
1232
  * `removed` is deleted. The new controls keep the directions the curve leaves
@@ -685,8 +1236,8 @@ declare function nearestSegmentT(anchors: PenAnchor[][], wx: number, wy: number,
685
1236
  * cubic, the original cubic comes back.
686
1237
  */
687
1238
  declare function fitCubicThroughDeletion(prev: PenAnchor, removed: PenAnchor, next: PenAnchor): {
688
- c1: Point$1;
689
- c2: Point$1;
1239
+ c1: Point;
1240
+ c2: Point;
690
1241
  };
691
1242
 
692
1243
  /**
@@ -698,7 +1249,7 @@ declare function fitCubicThroughDeletion(prev: PenAnchor, removed: PenAnchor, ne
698
1249
  * `C` cubic segments. For colinear / two-point inputs, returns a single
699
1250
  * degenerate cubic. For empty input, returns an empty polygon path.
700
1251
  */
701
- declare function schneiderFit(samples: ReadonlyArray<Point$1>, errorTolerance: number): PolygonPath;
1252
+ declare function schneiderFit(samples: ReadonlyArray<Point>, errorTolerance: number): PolygonPath;
702
1253
  /**
703
1254
  * The single cubic from the first sample to the last that best fits the
704
1255
  * samples between, with its control points held to the given unit tangents:
@@ -709,12 +1260,12 @@ declare function schneiderFit(samples: ReadonlyArray<Point$1>, errorTolerance: n
709
1260
  * omitted; `passes` is how many times those are refined and the lengths
710
1261
  * solved again.
711
1262
  */
712
- declare function fitCubicWithTangents(samples: ReadonlyArray<Point$1>, tStart: Point$1, tEnd: Point$1, opts?: {
1263
+ declare function fitCubicWithTangents(samples: ReadonlyArray<Point>, tStart: Point, tEnd: Point, opts?: {
713
1264
  params?: ReadonlyArray<number>;
714
1265
  passes?: number;
715
1266
  }): {
716
- cp1: Point$1;
717
- cp2: Point$1;
1267
+ cp1: Point;
1268
+ cp2: Point;
718
1269
  };
719
1270
 
720
1271
  /** Options for {@link simplifyPath}. */
@@ -734,195 +1285,156 @@ interface SimplifyPathOptions {
734
1285
  * becomes one straight segment. Fill rules carry over.
735
1286
  */
736
1287
  declare function simplifyPath(path: PolygonPath, tolerance: number, opts?: SimplifyPathOptions): PolygonPath;
737
-
1288
+ /** One subpath of {@link simplifyPath}: its anchors refitted, corners and
1289
+ * open ends kept. */
1290
+ declare function simplifySubpath(sub: PenAnchor[], closed: boolean, tolerance: number, opts?: SimplifyPathOptions): PenAnchor[];
1291
+ /**
1292
+ * The anchors of `sub` from index `from` to `to`, refitted the way
1293
+ * {@link simplifyPath} refits a subpath: as few as hold the span within
1294
+ * `tolerance`, corners inside it kept. Indices run modulo the subpath's
1295
+ * length, so on a closed subpath `to` may pass its end and wrap; the span is
1296
+ * shorter than one full turn. The two end anchors stay where they are and
1297
+ * keep their handles facing out of the span. Answers the anchors from `from`
1298
+ * to `to`, both included, to splice in place of the originals.
1299
+ */
1300
+ declare function simplifySpan(sub: PenAnchor[], closed: boolean, from: number, to: number, tolerance: number, opts?: SimplifyPathOptions): PenAnchor[];
1301
+
1302
+ /** Options for {@link growRegion}. */
1303
+ interface GrowRegionOptions {
1304
+ /** How a convex corner turns. `'miter'` keeps it sharp, as a pseudo-distance
1305
+ * field draws it; `'round'` follows the true distance. Default `'miter'`. */
1306
+ join?: 'miter' | 'round';
1307
+ /** Past this ratio of miter length to distance a miter corner is beveled.
1308
+ * Default 4. */
1309
+ miterLimit?: number;
1310
+ /** How far a grown curve may stray from the true offset, in the path's
1311
+ * units. Default 0.1. */
1312
+ tolerance?: number;
1313
+ }
738
1314
  /**
739
- * Screen-pixel lengths in world units, per axis.
1315
+ * The region `path` fills under `'nonzero'`, grown by `distance` (> 0), as a
1316
+ * path that fills it under `'nonzero'`. Every subpath counts as closed. Each
1317
+ * contour is replaced by its offset, so where grown parts meet the contours
1318
+ * overlap rather than merge, and a hole grown shut winds back on itself and
1319
+ * fills. At an inside corner the two offset edges are cut back to where they
1320
+ * cross; where they do not, the gap is passed through the corner's original
1321
+ * point, which closes it with a loop inside the fill. `mergeRegion`
1322
+ * redraws the result as its outline alone, for a stroke.
740
1323
  *
741
- * Chrome declares its hit zones in screen pixels — an 8px handle stays 8px at
742
- * every zoom, because it paints in screen space. Converting one such length to
743
- * world units with a single scalar (see `meanScale`) is exact only under
744
- * uniform zoom; per-axis it is too generous on one axis and too mean on the
745
- * other, so the pickable region stops matching the painted one.
746
- *
747
- * Prefer {@link withinPxBox} / {@link withinPxRadius}, which compare in screen
748
- * space and so can't drift from the paint at all. {@link pxExtent} is for the
749
- * cases that must stay in world units — a tolerance handed to geometry that
750
- * doesn't know about the view.
751
- */
752
- interface Scale2 {
753
- x: number;
754
- y: number;
1324
+ * What it costs: one segment per curve, more where `tolerance` needs the curve
1325
+ * split; a miter corner between two straight edges costs nothing, one beside
1326
+ * a curve gains an anchor or two, a round corner an arc, and an inside corner
1327
+ * whose edges do not cross two.
1328
+ */
1329
+ declare function growRegion(path: Path, distance: number, opts?: GrowRegionOptions): PolygonPath;
1330
+
1331
+ /** Options for {@link mergeRegion}. */
1332
+ interface MergeRegionOptions {
1333
+ /** How far from an edge a point is taken to tell which side is filled, in
1334
+ * the path's units; a sliver of region thinner than this may be lost.
1335
+ * Default 0.01. */
1336
+ tolerance?: number;
755
1337
  }
756
- /** One screen-pixel length as world-space extents, per axis. `scale` is a
757
- * view's, so neither axis is zero (see `View`).
758
- *
759
- * With `rotation`, the axes are a frame turned that far from world, and each
760
- * extent is how far along it an edge across it must move to move `px` on
761
- * screen — which, under non-uniform zoom, is not the extent along the screen
762
- * axis nearest to it. */
763
- declare function pxExtent(px: number, scale: Scale2, rotation?: number): {
764
- x: number;
765
- y: number;
766
- };
767
- /** World delta → screen delta. Only the scale participates: translation
768
- * cancels in a difference, and the kit's views carry no skew. */
769
- declare function scaleDelta(dx: number, dy: number, scale: Scale2): {
770
- x: number;
771
- y: number;
772
- };
773
1338
  /**
774
- * Is a world-space delta inside a screen-space square of half-extent `px`?
775
- *
776
- * The square is axis-aligned **on screen**, which is what a handle painted in
777
- * screen space actually is — so this stays true under non-uniform zoom and
778
- * under a rotated target, where an axis-aligned world-space test is a rotated
779
- * rectangle on screen.
780
- */
781
- declare function withinPxBox(dx: number, dy: number, px: number, scale: Scale2): boolean;
782
- /** Is a world-space delta inside a screen-space circle of radius `px`? */
783
- declare function withinPxRadius(dx: number, dy: number, px: number, scale: Scale2): boolean;
1339
+ * The region `path` fills under `'nonzero'`, as contours that neither cross
1340
+ * nor overlap, wound so the fill lies on the same side of each as it does on
1341
+ * most of `path`. Stroking it traces only the region's edge. Every subpath
1342
+ * counts as closed. Answers `path`'s own contours, unchanged, where nothing
1343
+ * needs cutting or dropping.
1344
+ */
1345
+ declare function mergeRegion(path: Path, opts?: MergeRegionOptions): PolygonPath;
1346
+
1347
+ /**
1348
+ * Simplify only where `flatIndexes` say: each unbroken run of those anchors
1349
+ * along a subpath is refitted as one span by the fitter {@link simplifyPath}
1350
+ * uses (`simplifySpan`), so only anchors the shape does not need, within
1351
+ * `tolerance`, go. A run's first and last anchors stay, and every anchor
1352
+ * outside a run is left as it was. A closed subpath named whole is simplified
1353
+ * whole. Answers whether any anchor went; a run the fit cannot thin is left
1354
+ * untouched.
1355
+ */
1356
+ declare function simplifyAnchorsAt(set: AnchorSet, flatIndexes: Iterable<number>, tolerance: number, opts?: SimplifyPathOptions): boolean;
1357
+
1358
+ /**
1359
+ * Resample: a path's anchors spread evenly along it by arc length, and its
1360
+ * curves refitted through them.
1361
+ */
1362
+
1363
+ /** Options for {@link resamplePath}. */
1364
+ interface ResamplePathOptions {
1365
+ /** How many anchors the result holds across all its subpaths. Default: as
1366
+ * many as `path` has. Ignored when `spacing` is given. */
1367
+ count?: number;
1368
+ /** The distance along the path between neighboring anchors, in path units.
1369
+ * Each run between fixed anchors is cut into the whole number of equal
1370
+ * pieces nearest this. */
1371
+ spacing?: number;
1372
+ /** Keep every corner anchor (`isAnchorSmooth` false) where it is, with its
1373
+ * corner, and resample the runs between. Default `true`. Open ends are
1374
+ * kept either way. */
1375
+ keepCorners?: boolean;
1376
+ /** How far the result may stray from the original, in path units. A piece
1377
+ * that cannot follow the original this closely is halved, so the result can
1378
+ * hold more anchors than `count` asks for. Default 0.5. */
1379
+ tolerance?: number;
1380
+ }
784
1381
  /**
785
- * A world point pushed `px` screen pixels off an edge, along the edge's normal
786
- * as it lands on screen. `normal` is the edge's outward normal in world space.
787
- *
788
- * Scaling the world normal by the view is not the same thing: under
789
- * non-uniform zoom the image of a normal is no longer perpendicular to the
790
- * image of its edge, so chrome placed that way drifts sideways and sits closer
791
- * than `px`. Returns the point in world coords and the on-screen unit normal.
1382
+ * `path` with its anchors spread evenly along each run between fixed anchors
1383
+ * ({@link ResamplePathOptions}), each new anchor heading the way the original
1384
+ * does there. Anchors that were smooth stay smooth, and the curves between
1385
+ * are fitted to the original. A closed subpath with no fixed anchor keeps
1386
+ * its first one as the place the even spacing starts from. Fill rules carry
1387
+ * over.
792
1388
  */
793
- declare function standoff(anchor: {
794
- x: number;
795
- y: number;
796
- }, normal: {
797
- x: number;
798
- y: number;
799
- }, px: number, scale: Scale2): {
800
- x: number;
801
- y: number;
802
- nx: number;
803
- ny: number;
804
- };
805
- /** The screen angle a frame turned `rotation` from world lands its x axis at.
806
- * Equals `rotation` under uniform zoom; non-uniform zoom bends it. */
807
- declare function screenAngleOf(rotation: number, scale: Scale2): number;
1389
+ declare function resamplePath(path: PolygonPath, opts?: ResamplePathOptions): PolygonPath;
808
1390
 
1391
+ /** The parameters in (0, 1) where the segment from `a` to `b` turns in x or
1392
+ * y, ascending, or none for a straight segment. */
1393
+ declare function segmentExtremaTs(a: PenAnchor, b: PenAnchor): number[];
809
1394
  /**
810
- * Pure anchor-set edits on the model `pathToAnchors` produces: subpath-major
811
- * `PenAnchor[][]` plus a parallel `closed: boolean[]`. Every function here
812
- * mutates that structure in place; callers decode with `pathToAnchors`,
813
- * apply, and re-encode with `anchorsToPath` (see {@link editAnchorSet}).
814
- *
815
- * Callers address anchors by flat index — the sequential position in walk
816
- * order across all subpaths, which is what `enumerateAnchors` reports.
817
- * {@link locateAnchor} and {@link flatAnchorIndex} convert to and from the
818
- * `(sub, idx)` pair.
819
- *
820
- * The two orders agree because `pathToAnchors` and `enumerateAnchors`
821
- * walk the same command stream and emit one anchor per M/L/C/Q, less the
822
- * end of a closing curve that lands on its subpath's first point.
823
- * `countPathAnchors`, which sizes the renderer's per-anchor arrays, counts
824
- * that end too and so can be one higher per closed subpath.
1395
+ * Split every curved segment of `set` at its extremes
1396
+ * ({@link segmentExtremaTs}), in place. `include(sub, segIdx)` limits it to
1397
+ * some segments, named as `segmentEnds` names them; absent, every one.
1398
+ * Returns the new anchors' flat indices in the edited set. Each new anchor is
1399
+ * smooth, and every anchor after one moves up an index.
825
1400
  */
1401
+ declare function addExtremaAnchors(set: AnchorSet, include?: (sub: number, segIdx: number) => boolean): number[];
826
1402
 
827
- /** Subpath-major anchor model — the decoded form of a `PolygonPath`. */
828
- interface AnchorSet {
829
- anchors: PenAnchor[][];
830
- closed: boolean[];
831
- }
832
- /** A world-space rectangle, as produced by a drag-rect gesture. */
833
- interface AnchorRect {
834
- x: number;
835
- y: number;
836
- width: number;
837
- height: number;
838
- }
839
- /** Total anchors across every subpath. */
840
- declare function anchorCount(set: AnchorSet): number;
841
- /** Flat index → `(sub, idx)`. Returns null when out of range. */
842
- declare function locateAnchor(set: AnchorSet, flatIndex: number): {
843
- sub: number;
844
- idx: number;
845
- } | null;
846
- /** `(sub, idx)` → flat index. Returns -1 when out of range. */
847
- declare function flatAnchorIndex(set: AnchorSet, sub: number, idx: number): number;
848
- /** Resolve a flat index to the anchor itself. Null when out of range. */
849
- declare function anchorAt(set: AnchorSet, flatIndex: number): PenAnchor | null;
850
- /**
851
- * Decode `path`, hand the mutable anchor set to `edit`, and re-encode.
852
- * Returns null when `edit` returns `false` (it changed nothing), so callers
853
- * can skip a no-op commit.
854
- */
855
- declare function editAnchorSet(path: PolygonPath, edit: (set: AnchorSet) => boolean | void): PolygonPath | null;
856
- /** Translate an anchor and both of its handles by `(dx, dy)`. */
857
- declare function translateAnchorBy(set: AnchorSet, flatIndex: number, dx: number, dy: number): boolean;
858
1403
  /**
859
- * Move one control handle to an absolute world position. When the anchor was
860
- * smooth (handles collinear through the anchor) and `breakSmoothness` is
861
- * false, the opposite handle is mirrored so the curve stays smooth.
862
- */
863
- declare function moveHandleTo(set: AnchorSet, flatIndex: number, side: 'in' | 'out', toX: number, toY: number, breakSmoothness: boolean): boolean;
864
- /**
865
- * Split the segment `(sub, segIdx) → (sub, segIdx + 1)` at parameter `t`,
866
- * inserting a new anchor there. On a closed subpath `segIdx` may also name
867
- * the closing segment (`sub.length - 1`); its new anchor is appended.
1404
+ * Anchor selections walked along the path: grown or shrunk by one anchor,
1405
+ * every Nth anchor, anchors by kind, and the complement. Each takes the
1406
+ * decoded set and a selection as flat indices, and returns a new selection
1407
+ * as sorted flat indices; none of them edits the set.
868
1408
  *
869
- * A straight segment stays straight — the new anchor has no handles. A curved
870
- * one splits by de Casteljau, so the two halves trace the original path.
871
- *
872
- * Returns the new anchor's flat index, or -1 when the segment doesn't
873
- * exist.
1409
+ * "Along the path" means within a subpath: an anchor's neighbors are the
1410
+ * anchors before and after it there, and a closed subpath's first and last
1411
+ * anchors are neighbors.
874
1412
  */
875
- declare function insertAnchorOnSegment(set: AnchorSet, args: {
876
- sub: number;
877
- segIdx: number;
878
- t: number;
879
- }): number;
880
- /** A point on a segment, as {@link segmentAt} reports it. */
881
- interface SegmentHit {
882
- sub: number;
883
- segIdx: number;
884
- /** Parameter on the segment — what {@link insertAnchorOnSegment} takes. */
885
- t: number;
886
- /** The point on the path at `t`, in the set's own space. */
887
- x: number;
888
- y: number;
889
- }
890
- /**
891
- * The segment point under `(x, y)`, when it lies within `tolerancePx` of
892
- * the path on screen and no nearer than that to either of the segment's
893
- * own anchors — a press on an anchor is about the anchor, not the segment
894
- * beside it.
895
- *
896
- * `scale` is the view's, so the tolerance holds per axis under
897
- * non-uniform zoom. The search runs in screen-scaled space: scaling is
898
- * affine, so the curve's parameterization, and therefore `t`, carries
899
- * straight back to world space.
900
- */
901
- declare function segmentAt(set: AnchorSet, x: number, y: number, opts: {
902
- tolerancePx: number;
903
- scale?: Scale2;
904
- }): SegmentHit | null;
1413
+
1414
+ /** `selected` with each selected anchor's neighbors along the path added. */
1415
+ declare function growAnchorSelection(set: AnchorSet, selected: Iterable<number>): number[];
905
1416
  /**
906
- * Delete the anchors at `flatIndexes`. Where a deleted anchor had
907
- * neighbors on both sides — across the seam too, on a closed subpath — the
908
- * surviving segment is refitted to the two it replaces (`fitCubicThroughDeletion`)
909
- * so the path keeps its shape; a gap between two straight segments closes straight.
910
- *
911
- * Subpaths left with fewer than two anchors are dropped entirely. If that
912
- * would leave the path with no subpaths at all, the whole deletion is refused
913
- * (returns false, `set` untouched): an empty path leaves the node selected
914
- * and in the scene with nothing on screen and no anchors to grab it by.
1417
+ * `selected` less every anchor at the edge of a selected run: one with a
1418
+ * neighbor that is unselected, or none on one side, as an open subpath's ends
1419
+ * have. A closed subpath selected all the way round has no edge and stays.
915
1420
  */
916
- declare function deleteAnchorsAt(set: AnchorSet, flatIndexes: Iterable<number>): boolean;
1421
+ declare function shrinkAnchorSelection(set: AnchorSet, selected: Iterable<number>): number[];
917
1422
  /**
918
- * Scissors: open a closed subpath at the given anchor. The anchor list is
919
- * rotated to start there and a second anchor at the same point ends it, so
920
- * every segment survives and the two ends can be pulled apart. No-ops on an
921
- * already-open subpath — there's nothing to cut.
1423
+ * Every `n`th anchor along each subpath, counting from its first selected
1424
+ * anchor. With nothing selected, every subpath counts from its first anchor;
1425
+ * otherwise only subpaths holding a selected anchor take part. A closed
1426
+ * subpath is walked once round, so the count does not wrap onto itself.
922
1427
  */
923
- declare function openSubpathAt(set: AnchorSet, flatIndex: number): boolean;
924
- /** Flat indices of every anchor whose on-curve point falls inside `rect`. */
925
- declare function anchorsInRect(set: AnchorSet, rect: AnchorRect): number[];
1428
+ declare function everyNthAnchor(set: AnchorSet, n: number, selected?: Iterable<number>): number[];
1429
+ /** Every anchor `keep` says yes to. */
1430
+ declare function anchorsWhere(set: AnchorSet, keep: (anchor: PenAnchor) => boolean): number[];
1431
+ /** Every corner anchor: one whose handles are not collinear through it, or
1432
+ * that lacks one (`isAnchorSmooth` false). */
1433
+ declare function cornerAnchors(set: AnchorSet): number[];
1434
+ /** Every smooth anchor (`isAnchorSmooth`). */
1435
+ declare function smoothAnchors(set: AnchorSet): number[];
1436
+ /** Every anchor `selected` leaves out. */
1437
+ declare function invertAnchorSelection(set: AnchorSet, selected: Iterable<number>): number[];
926
1438
 
927
1439
  /**
928
1440
  * Average and Join: anchor-set edits that bring anchors together. Both mutate
@@ -939,6 +1451,13 @@ interface SubpathEnd {
939
1451
  sub: number;
940
1452
  end: 'first' | 'last';
941
1453
  }
1454
+ /** How {@link joinSubpathEnds} spans the gap between two ends apart. */
1455
+ interface JoinOptions {
1456
+ /** Absent, a straight segment. Given, a curve leaving each end along the
1457
+ * direction its path was heading there, each handle `tension` times the
1458
+ * gap long; `0` is a straight segment. */
1459
+ tension?: number;
1460
+ }
942
1461
  /**
943
1462
  * Move each anchor in `flatIndexes` to their mean position, along `axis`.
944
1463
  * Each anchor carries its handles with it. Returns false, changing nothing,
@@ -953,19 +1472,71 @@ declare function subpathEndAt(set: AnchorSet, flatIndex: number): SubpathEnd | n
953
1472
  * close it; ends of two subpaths make one subpath, `a`'s run followed by
954
1473
  * `b`'s, in the slot of whichever came first. Ends that coincide merge into
955
1474
  * one anchor, keeping the handle on either side; ends apart are bridged by a
956
- * straight segment. Returns false, changing nothing, when the ends are not
957
- * two distinct ends of open subpaths.
1475
+ * straight segment, or with `options.tension` by a curve meeting each end
1476
+ * tangentially. Returns false, changing nothing, when the ends are not two
1477
+ * distinct ends of open subpaths.
958
1478
  */
959
- declare function joinSubpathEnds(set: AnchorSet, a: SubpathEnd, b: SubpathEnd): boolean;
1479
+ declare function joinSubpathEnds(set: AnchorSet, a: SubpathEnd, b: SubpathEnd, options?: JoinOptions): boolean;
960
1480
  /** {@link joinSubpathEnds} for two anchors named by flat index, each the end
961
1481
  * of an open subpath. */
962
- declare function joinAnchorsAt(set: AnchorSet, flatA: number, flatB: number): boolean;
1482
+ declare function joinAnchorsAt(set: AnchorSet, flatA: number, flatB: number, options?: JoinOptions): boolean;
963
1483
  /**
964
1484
  * The two open-subpath ends nearest each other that `accept` allows, on two
965
1485
  * different subpaths. Null when there are no two such subpaths.
966
1486
  */
967
1487
  declare function closestOpenEnds(set: AnchorSet, accept?: (a: SubpathEnd, b: SubpathEnd) => boolean): [SubpathEnd, SubpathEnd] | null;
968
1488
 
1489
+ /**
1490
+ * Spiro curves as cubic paths, and back. A solved curve is written as cubics,
1491
+ * each spiral segment split into as many as it takes to stay within tolerance,
1492
+ * so most anchors of the path are not spiro points. `at` records which are:
1493
+ * `at[i]` is the flat anchor index of point `i`, counted across subpaths. The
1494
+ * points are then read back out of the path itself, so whatever moves the path
1495
+ * — a move, a resize, a rotation — moves them with it.
1496
+ */
1497
+
1498
+ /** One subpath of a spiro curve: its points, and whether it closes. */
1499
+ interface SpiroContour {
1500
+ points: SpiroPoint[];
1501
+ closed: boolean;
1502
+ }
1503
+ /** A spiro curve written as a cubic path, with the anchor each point became. */
1504
+ interface SpiroPath {
1505
+ path: PolygonPath;
1506
+ /** The flat anchor index of each point, in contour order. */
1507
+ at: number[];
1508
+ }
1509
+ /** Options for {@link spiroToPath}. */
1510
+ interface SpiroToPathOptions {
1511
+ /** The furthest a cubic may stray from its spiral, as a fraction of that
1512
+ * segment's arc length. Default `1e-4`. */
1513
+ tolerance?: number;
1514
+ /** The path being reshaped, whose fill rules the result keeps. */
1515
+ like?: PolygonPath;
1516
+ }
1517
+ /**
1518
+ * Solve each contour and write it as a cubic path. Straight segments carry no
1519
+ * handles.
1520
+ */
1521
+ declare function spiroToPath(contours: readonly SpiroContour[], options?: SpiroToPathOptions): SpiroPath;
1522
+ /**
1523
+ * The spiro points `path` holds, given the kind of each and the anchor each
1524
+ * became. Null when `kinds` and `at` do not describe `path`: the counts
1525
+ * differ, an index is out of order or out of range, or a subpath does not
1526
+ * start on a point.
1527
+ */
1528
+ declare function spiroContoursOf(path: PolygonPath, kinds: readonly SpiroKind[], at: readonly number[]): SpiroContour[] | null;
1529
+ /** The straight-sided path through each contour's points: what an editor
1530
+ * shows and moves in place of the curve. */
1531
+ declare function spiroControlPath(contours: readonly SpiroContour[]): PolygonPath;
1532
+ /**
1533
+ * Read an edited control path back as contours: every anchor is a point.
1534
+ * Kinds follow from `before`, the contours the edit started from: point for
1535
+ * point when the count is unchanged, else by position, with an anchor that
1536
+ * lands nowhere a point was taking `fallback`. Handles are ignored.
1537
+ */
1538
+ declare function spiroContoursFromControl(control: PolygonPath, before: readonly SpiroContour[], fallback?: SpiroKind): SpiroContour[];
1539
+
969
1540
  /**
970
1541
  * Path hit-testing: path-vs-point (filled region and stroke distance),
971
1542
  * path-vs-rect, and path-vs-polygon in both directions.
@@ -1020,15 +1591,15 @@ declare function pathContainsRect(path: Path, rect: Rect, opts?: PointInPathOpti
1020
1591
  /** Returns true if `rect` overlaps (intersects or contains) `path`. */
1021
1592
  declare function pathIntersectsRect(path: Path, rect: Rect, opts?: PointInPathOptions): boolean;
1022
1593
  /** Returns true if every vertex of `polygon` lies inside `path`. */
1023
- declare function pathContainsPolygon(path: Path, polygon: readonly Point$1[], opts?: PointInPathOptions): boolean;
1594
+ declare function pathContainsPolygon(path: Path, polygon: readonly Point[], opts?: PointInPathOptions): boolean;
1024
1595
  /** Returns true if `polygon` overlaps (intersects or is contained by) `path`. */
1025
- declare function pathIntersectsPolygon(path: Path, polygon: readonly Point$1[], opts?: PointInPathOptions): boolean;
1596
+ declare function pathIntersectsPolygon(path: Path, polygon: readonly Point[], opts?: PointInPathOptions): boolean;
1026
1597
  /**
1027
1598
  * Returns true if all of `path` — every subpath, open ones included, beziers
1028
1599
  * flattened — lies inside the closed `polygon`: the inverse of
1029
1600
  * {@link pathContainsPolygon}. A lasso enclosing a shape asks this.
1030
1601
  */
1031
- declare function polygonContainsPath(polygon: readonly Point$1[], path: Path, opts?: PointInPathOptions): boolean;
1602
+ declare function polygonContainsPath(polygon: readonly Point[], path: Path, opts?: PointInPathOptions): boolean;
1032
1603
  /**
1033
1604
  * Returns true if any of `path` meets the closed `polygon`: its filled region,
1034
1605
  * or the line of an open subpath, which encloses nothing. With `filled: false`
@@ -1036,7 +1607,16 @@ declare function polygonContainsPath(polygon: readonly Point$1[], path: Path, op
1036
1607
  * flattened, so a control point off the curve never counts. The companion of
1037
1608
  * {@link polygonContainsPath}; a lasso touching a shape asks this.
1038
1609
  */
1039
- declare function polygonIntersectsPath(polygon: readonly Point$1[], path: Path, opts?: PolygonIntersectsPathOptions): boolean;
1610
+ declare function polygonIntersectsPath(polygon: readonly Point[], path: Path, opts?: PolygonIntersectsPathOptions): boolean;
1611
+
1612
+ /**
1613
+ * The affine map carrying the points of `from` closest to those of `to`, by
1614
+ * least squares; both are interleaved `x, y` streams of the same length. When
1615
+ * the points lie on one line an affine map is not determined, and the
1616
+ * similarity (turn, even scale and move) is returned instead. Null for fewer
1617
+ * than two distinct points.
1618
+ */
1619
+ declare function fitAffine(from: ArrayLike<number>, to: ArrayLike<number>): Affine | null;
1040
1620
 
1041
1621
  /**
1042
1622
  * Ergonomic builders for tiny shape paths used by chrome / overlays / markers.
@@ -1394,6 +1974,20 @@ declare function rotatePathAround(path: Path, cx: number, cy: number, rotation:
1394
1974
  * rotation. Absent is the identity.
1395
1975
  */
1396
1976
  type PoseLinear = readonly [a: number, b: number, c: number, d: number];
1977
+ /**
1978
+ * Axis-aligned rectangle in world space. The optional `rotation` (radians,
1979
+ * around the AABB center) and `transform` (inside it, about the same center)
1980
+ * let chrome carry the frame a box is drawn in without a parallel type;
1981
+ * `poseFrameOf` composes the two. routing and core call it `Bounds`.
1982
+ */
1983
+ interface FramedBox {
1984
+ x: number;
1985
+ y: number;
1986
+ width: number;
1987
+ height: number;
1988
+ rotation?: number;
1989
+ transform?: PoseLinear;
1990
+ }
1397
1991
  /** `transform` when it changes anything, `null` for absent or the identity. */
1398
1992
  declare function poseLinearOf(pose: unknown): PoseLinear | null;
1399
1993
  /**
@@ -1412,7 +2006,17 @@ declare function poseFrameInverseOf(pose: unknown): Affine | null;
1412
2006
  /** `path`, given in the pose's unrotated box frame, as the node draws it. */
1413
2007
  declare function pathThroughPoseFrame(path: Path, pose: unknown): Path;
1414
2008
 
1415
- type Side = 'in' | 'out';
2009
+ /**
2010
+ * Flat indices of every anchor a round brush covers as it moves from `from` to
2011
+ * `to`: those within `radiusPx` of that segment, measured on screen. A dab is a
2012
+ * segment of zero length. `scale` is the view's, so the brush stays round on
2013
+ * screen under non-uniform zoom; omitted, one unit is one pixel.
2014
+ */
2015
+ declare function anchorsUnderBrush(set: AnchorSet, from: Point, to: Point, opts: {
2016
+ radiusPx: number;
2017
+ scale?: Scale2;
2018
+ }): number[];
2019
+
1416
2020
  /**
1417
2021
  * How a path maps onto itself under one transform `m`: `partners[i]` is the
1418
2022
  * flat index of the anchor that anchor `i` lands on, and `flips[i]` whether
@@ -1454,7 +2058,7 @@ declare function translateAnchorsSymmetric(set: AnchorSet, flats: readonly numbe
1454
2058
  * follow it. Every handle is written once, from its target, so no anchor
1455
2059
  * re-aims a handle another image already placed.
1456
2060
  */
1457
- declare function moveHandleSymmetric(set: AnchorSet, flat: number, side: Side, toX: number, toY: number, breakSmoothness: boolean, syms: readonly AnchorSymmetry[]): boolean;
2061
+ declare function moveHandleSymmetric(set: AnchorSet, flat: number, side: 'in' | 'out', toX: number, toY: number, breakSmoothness: boolean, syms: readonly AnchorSymmetry[]): boolean;
1458
2062
 
1459
2063
  /** Where on a segment a bend is held, as `segmentAt` reports it. */
1460
2064
  interface BendGrip {
@@ -1475,10 +2079,38 @@ interface BendGrip {
1475
2079
  */
1476
2080
  declare function bendSegment(set: AnchorSet, grip: BendGrip, dx: number, dy: number): boolean;
1477
2081
 
1478
- type Point = {
1479
- x: number;
1480
- y: number;
1481
- };
2082
+ /**
2083
+ * `smudgePath` — one dab of a smudge brush: the outline under a round brush
2084
+ * moved along the brush's motion, most at its center and not at all at its rim.
2085
+ */
2086
+
2087
+ /** Options for {@link smudgePath}. */
2088
+ interface SmudgePathOptions {
2089
+ /** The brush's center before this dab's motion. */
2090
+ center: Point;
2091
+ /** How far the brush moved. */
2092
+ delta: Point;
2093
+ /** The brush's radius, in the path's units. */
2094
+ radius: number;
2095
+ /** How much of `delta` a point under the brush's center moves: `1` all of it. Default 1. */
2096
+ strength?: number;
2097
+ /**
2098
+ * The longest a segment under the brush may be before an anchor is added at its
2099
+ * middle, in the path's units, so the brush has points to move where it needs
2100
+ * them. Default a third of `radius`; `Infinity` adds none.
2101
+ */
2102
+ detail?: number;
2103
+ }
2104
+ /**
2105
+ * `path` with the outline under the brush pushed along `delta`. A point at distance
2106
+ * `d` from `center` moves by `delta × strength × (1 − (d/radius)²)²`, and an anchor's
2107
+ * handles move with it, so a smooth anchor stays smooth. First, every segment that
2108
+ * passes under the brush and is longer than `detail` is split at its middle until it
2109
+ * is not, so a long straight edge bends where the brush meets it. Returns `path`
2110
+ * itself when nothing is under the brush.
2111
+ */
2112
+ declare function smudgePath(path: PolygonPath, opts: SmudgePathOptions): PolygonPath;
2113
+
1482
2114
  /**
1483
2115
  * Collapse the handles of the anchors at `flatIndexes` onto their anchors,
1484
2116
  * leaving sharp corners. A segment whose ends both lose their handles turns
@@ -1507,17 +2139,165 @@ declare function makeHandlesSymmetric(set: AnchorSet, flatIndexes: Iterable<numb
1507
2139
  * keep and follows `to` freely.
1508
2140
  */
1509
2141
  declare function handleAlongItsAngle(anchor: Point, handle: Point, to: Point): Point;
2142
+ /**
2143
+ * Where a handle lands when dragged toward `to` but held to its current
2144
+ * length from `anchor`: on the circle of that length, aimed at `to`. A `to`
2145
+ * on the anchor itself gives no direction, and leaves the handle where it is.
2146
+ */
2147
+ declare function handleAtItsLength(anchor: Point, handle: Point, to: Point): Point;
2148
+
2149
+ /**
2150
+ * Soft selection over an anchor set: how strongly an edit to some anchors
2151
+ * carries to the anchors near them, by distance measured along the path.
2152
+ *
2153
+ * Distance is arc length along the drawn curve, not a straight line, so two
2154
+ * anchors that sit close across a gap in a shape are as far apart as the
2155
+ * path between them. A `scale` measures it in screen pixels under a view's
2156
+ * zoom, per axis.
2157
+ */
2158
+
2159
+ /** How influence fades from 1 at a selected anchor to 0 at the radius:
2160
+ * `smooth` eases out and in, `linear` falls evenly, `sharp` drops fast and
2161
+ * tails off. */
2162
+ type SoftFalloff = 'smooth' | 'linear' | 'sharp';
2163
+ /**
2164
+ * The weight `falloff` gives a point `distance` from the selection, for a
2165
+ * radius of `radius`: 1 at distance 0, 0 at the radius and beyond.
2166
+ */
2167
+ declare function softFalloff(falloff: SoftFalloff, distance: number, radius: number): number;
2168
+ /** Arc length along one segment, sampled at evenly spaced curve parameters. */
2169
+ interface SegmentMeasure {
2170
+ /** Arc length from the subpath's start to each sample; sample `i` is at
2171
+ * parameter `i / (lengths.length - 1)`. */
2172
+ lengths: Float64Array;
2173
+ }
2174
+ /** Arc lengths along one subpath, as {@link measureAnchorPath} takes them. */
2175
+ interface AnchorSubpathMeasure {
2176
+ closed: boolean;
2177
+ /** Flat index of the subpath's first anchor. */
2178
+ first: number;
2179
+ /** Arc length from the subpath's start to each anchor. */
2180
+ at: Float64Array;
2181
+ /** Total length, the closing segment included on a closed subpath. */
2182
+ length: number;
2183
+ /** Segment `i` runs from anchor `i` to anchor `i + 1`, wrapping on a closed subpath. */
2184
+ segments: SegmentMeasure[];
2185
+ }
2186
+ /** Arc lengths along every subpath of an anchor set, as
2187
+ * {@link measureAnchorPath} takes them. Read it with
2188
+ * {@link softSelectionWeights} and {@link softSelectionBand}. */
2189
+ interface AnchorPathMeasure {
2190
+ readonly subpaths: readonly AnchorSubpathMeasure[];
2191
+ }
2192
+ /** Options for {@link measureAnchorPath}. */
2193
+ interface MeasureAnchorPathOptions {
2194
+ /** Per-axis factor applied before measuring — a view's scale, to measure in
2195
+ * screen pixels. Default 1 on both axes. */
2196
+ scale?: {
2197
+ x: number;
2198
+ y: number;
2199
+ };
2200
+ /** Samples taken along each curved segment. Default 24. */
2201
+ samples?: number;
2202
+ }
2203
+ /** Measure the arc length along every subpath of `set`. */
2204
+ declare function measureAnchorPath(set: AnchorSet, opts?: MeasureAnchorPathOptions): AnchorPathMeasure;
2205
+ /**
2206
+ * How much of an edit to the `selected` anchors each anchor receives: 1 for
2207
+ * a selected anchor, the falloff of its distance along the path for one
2208
+ * within `radius` of the nearest selected anchor on its subpath. Anchors
2209
+ * that receive nothing are absent, as are anchors on a subpath with no
2210
+ * selected anchor.
2211
+ */
2212
+ declare function softSelectionWeights(measure: AnchorPathMeasure, selected: Iterable<number>, radius: number, falloff: SoftFalloff): Map<number, number>;
2213
+ /**
2214
+ * The stretches of path within `radius` of the `selected` anchors, as world
2215
+ * polylines drawn on `set`. `measure` is of the set the distances are taken
2216
+ * on — the path as it was when the edit began — and `set` the geometry to
2217
+ * draw on, which must have the same anchors. A stretch crossing the seam of a
2218
+ * closed subpath comes back as one run.
2219
+ */
2220
+ declare function softSelectionBand(measure: AnchorPathMeasure, set: AnchorSet, selected: Iterable<number>, radius: number): Point[][];
2221
+
2222
+ /** A curved segment's balance line: from its first handle's tip to its
2223
+ * second's, with a grip at the middle. */
2224
+ interface HandleBalance {
2225
+ sub: number;
2226
+ segIdx: number;
2227
+ /** Flat index of the anchor the segment starts at, which names the segment
2228
+ * the way an anchor's flat index names the anchor. */
2229
+ flat: number;
2230
+ /** Tip of the segment's first handle, the start anchor's out-handle. */
2231
+ from: Point;
2232
+ /** Tip of the segment's second handle, the end anchor's in-handle. */
2233
+ to: Point;
2234
+ /** Midway between the two tips. */
2235
+ grip: Point;
2236
+ }
2237
+ /**
2238
+ * The balance line of every curved segment in `set` that has both handles
2239
+ * pulled off their anchors. Dragging a line's grip scales both handles
2240
+ * together ({@link scaleSegmentHandles}), which fills the curve out toward
2241
+ * its corner or flattens it toward its chord without turning either end.
2242
+ */
2243
+ declare function handleBalances(set: AnchorSet): HandleBalance[];
2244
+ /**
2245
+ * Scale both handles of segment `(sub, segIdx)` by `factor`, each along its
2246
+ * own direction, so the segment keeps its end tangents. A smooth anchor at
2247
+ * either end stays smooth: its other handle points the same way as before.
2248
+ * `factor` below zero counts as zero, which retracts both handles.
2249
+ *
2250
+ * Under `syms`, as `anchorSymmetries` gives them, every image of either handle
2251
+ * moves to the image of where that handle goes, the way `moveHandleSymmetric`
2252
+ * moves a dragged handle's.
2253
+ *
2254
+ * Returns false when the segment has no balance line or nothing moved.
2255
+ */
2256
+ declare function scaleSegmentHandles(set: AnchorSet, sub: number, segIdx: number, factor: number, syms?: readonly AnchorSymmetry[]): boolean;
2257
+ /**
2258
+ * The factor {@link scaleSegmentHandles} takes to bring segment
2259
+ * `(sub, segIdx)`'s grip as near `to` as scaling can: `to` projected onto the
2260
+ * line the grip slides along as both handles grow. 1 when the segment has no
2261
+ * balance line.
2262
+ */
2263
+ declare function balanceFactorToward(set: AnchorSet, sub: number, segIdx: number, to: Point): number;
2264
+ /**
2265
+ * Give both handles of segment `(sub, segIdx)` the same proportion: each
2266
+ * reaches the same fraction of the way from its anchor to the corner where
2267
+ * the two handle lines cross, that fraction being the mean of the two they
2268
+ * had. Where the lines don't cross ahead of both handles, both take the mean
2269
+ * length instead. Directions are kept either way.
2270
+ *
2271
+ * Returns false when the segment has no balance line or the handles already
2272
+ * match.
2273
+ */
2274
+ declare function equalizeSegmentHandles(set: AnchorSet, sub: number, segIdx: number): boolean;
2275
+
2276
+ /**
2277
+ * Make each smooth anchor at `flatIndexes` curvature-continuous: the curve
2278
+ * bends as tightly just after the anchor as just before it, so it shows no
2279
+ * kink in its curvature there. Only handle lengths change — each handle keeps
2280
+ * its direction, so the anchor stays smooth and the tangent stays put — and
2281
+ * the product of the two lengths is kept, so the anchor's pull on the curve
2282
+ * stays about as strong.
2283
+ *
2284
+ * Absent `flatIndexes`, every anchor in the set. Moving one anchor's handles
2285
+ * changes the curvature at its neighbors, so the fixes are repeated until
2286
+ * they settle.
2287
+ *
2288
+ * Skipped, because lengths alone cannot do it: a corner, an anchor missing a
2289
+ * handle, an end of an open subpath, and an anchor the curve bends opposite
2290
+ * ways either side of, or straight through on one side.
2291
+ *
2292
+ * Returns false when nothing changed.
2293
+ */
2294
+ declare function harmonizeAnchors(set: AnchorSet, flatIndexes?: Iterable<number>): boolean;
1510
2295
 
1511
2296
  /**
1512
2297
  * Where each point of an edited path came from, so an array kept per point (a skin's
1513
2298
  * weights) can follow an edit that inserts, deletes, or reorders points.
1514
2299
  */
1515
2300
 
1516
- /** The anchor model `pathToAnchors` produces; `AnchorSet` in `anchorEdits`. */
1517
- interface Anchors {
1518
- anchors: PenAnchor[][];
1519
- closed: boolean[];
1520
- }
1521
2301
  /**
1522
2302
  * Where a point of an edited path came from: point `a` of the path before the edit, or for a
1523
2303
  * point the edit made, a blend `t` of the way from point `a` to point `b`.
@@ -1526,6 +2306,8 @@ interface PointOrigin {
1526
2306
  a: number;
1527
2307
  b: number;
1528
2308
  t: number;
2309
+ /** On an anchor's own point: its subpath now runs the other way through it. */
2310
+ reversed?: true;
1529
2311
  }
1530
2312
  /**
1531
2313
  * `editAnchorSet`, answering also where each point of the new path came from.
@@ -1536,7 +2318,7 @@ interface PointOrigin {
1536
2318
  * of it in its subpath, by its distance to each, or a copy of the one it has; its origin is
1537
2319
  * `null` when its subpath has none.
1538
2320
  */
1539
- declare function editAnchorSetTracked(path: PolygonPath, edit: (set: Anchors) => boolean | void): {
2321
+ declare function editAnchorSetTracked(path: PolygonPath, edit: (set: AnchorSet) => boolean | void): {
1540
2322
  path: PolygonPath;
1541
2323
  origins: (PointOrigin | null)[];
1542
2324
  } | null;
@@ -1547,6 +2329,452 @@ declare function editAnchorSetTracked(path: PolygonPath, edit: (set: Anchors) =>
1547
2329
  */
1548
2330
  declare function remapPointValues(values: ArrayLike<number>, origins: readonly (PointOrigin | null)[]): number[];
1549
2331
 
2332
+ /**
2333
+ * Arrays kept per anchor of a path — vertex colors, stroke widths — carried through an edit
2334
+ * that `editAnchorSetTracked` reported.
2335
+ */
2336
+
2337
+ /**
2338
+ * Where each anchor of `after` came from, in anchors of `before` as `countPathAnchors` counts
2339
+ * them, given the point `origins` `editAnchorSetTracked` answered for the edit: anchor `a`, or
2340
+ * for an anchor the edit made, a blend `t` of the way from `a` to `b`. `reversed` marks an
2341
+ * anchor whose subpath now runs the other way through it. Null for an anchor with no origin.
2342
+ */
2343
+ declare function anchorOriginsOf(before: PolygonPath, after: PolygonPath, origins: readonly (PointOrigin | null)[]): (PointOrigin | null)[];
2344
+ /**
2345
+ * An array kept per anchor of a path, `stride` numbers each — four color channels, say —
2346
+ * carried through an edit from `before` to `after`, with `origins` as
2347
+ * `editAnchorSetTracked` answered. An anchor the edit kept keeps its numbers; one it
2348
+ * made blends those of the anchors it came between. An anchor with no origin reads 0. Anchors
2349
+ * are counted as `countPathAnchors` counts them.
2350
+ */
2351
+ declare function remapAnchorValues(values: ArrayLike<number>, stride: number, before: PolygonPath, after: PolygonPath, origins: readonly (PointOrigin | null)[]): number[];
2352
+
2353
+ /**
2354
+ * Geometric constraints on a path's anchors. Each names anchors by flat index,
2355
+ * the walk-order numbering `enumerateAnchors` and `anchorAt` use, and is plain
2356
+ * JSON, so a list of them can be kept in scene data and saved with it.
2357
+ */
2358
+ /** Two anchors by flat index: the straight line from the first to the second. */
2359
+ type AnchorPair = readonly [number, number];
2360
+ /**
2361
+ * One constraint. `fixed` holds an anchor where it was before an edit, so it
2362
+ * moves with its node but not with any edit of the path. `horizontal` and
2363
+ * `vertical` read the axes of the frame the solve is given; `length` is in
2364
+ * the path's own units. `tangent` keeps an anchor's two handles on one line
2365
+ * through it, pointing apart (G1 continuity), their lengths free; it needs
2366
+ * both handles. `onPath` holds an anchor on the path's segment from
2367
+ * `segment[0]` to `segment[1]`, anywhere along it.
2368
+ */
2369
+ type PathConstraint = {
2370
+ readonly kind: 'fixed' | 'tangent';
2371
+ readonly anchor: number;
2372
+ } | {
2373
+ readonly kind: 'horizontal' | 'vertical';
2374
+ readonly segment: AnchorPair;
2375
+ } | {
2376
+ readonly kind: 'parallel' | 'perpendicular' | 'equalLength';
2377
+ readonly segments: readonly [AnchorPair, AnchorPair];
2378
+ } | {
2379
+ readonly kind: 'length';
2380
+ readonly segment: AnchorPair;
2381
+ readonly length: number;
2382
+ } | {
2383
+ readonly kind: 'coincident';
2384
+ readonly anchors: AnchorPair;
2385
+ } | {
2386
+ readonly kind: 'onPath';
2387
+ readonly anchor: number;
2388
+ readonly segment: AnchorPair;
2389
+ };
2390
+ /** Every kind of {@link PathConstraint}. */
2391
+ type PathConstraintKind = PathConstraint['kind'];
2392
+ /** The anchors `c` reads, in the order it names them; an anchor named twice is listed twice. */
2393
+ declare function constraintAnchors(c: PathConstraint): number[];
2394
+ /**
2395
+ * `c` with every anchor index passed through `to`, or null when `to` answers
2396
+ * `undefined` for any of them — the anchor is gone, and so is the constraint.
2397
+ */
2398
+ declare function mapConstraintAnchors(c: PathConstraint, to: (anchor: number) => number | undefined): PathConstraint | null;
2399
+ /** Whether every anchor `c` names is an index below `count`. */
2400
+ declare function constraintFits(c: PathConstraint, count: number): boolean;
2401
+
2402
+ /**
2403
+ * The points a constraint solve reads, and the coordinate vector it works in:
2404
+ * anchors, then each anchor's handles as offsets from it (see `ResidualSpace`).
2405
+ */
2406
+
2407
+ /** An anchor the solver reads and writes, with its handles where it has them. */
2408
+ interface ConstraintPoint {
2409
+ x: number;
2410
+ y: number;
2411
+ inHandle?: {
2412
+ x: number;
2413
+ y: number;
2414
+ };
2415
+ outHandle?: {
2416
+ x: number;
2417
+ y: number;
2418
+ };
2419
+ }
2420
+ /** One handle of an anchor. */
2421
+ interface HandleRef {
2422
+ anchor: number;
2423
+ side: 'in' | 'out';
2424
+ }
2425
+ /**
2426
+ * Whether `c` can be solved over `points`: every anchor it names exists, and
2427
+ * a `tangent` anchor has both handles.
2428
+ */
2429
+ declare function constraintApplies(c: PathConstraint, points: readonly ConstraintPoint[]): boolean;
2430
+
2431
+ /**
2432
+ * A damped Gauss-Newton solve for anchor constraints: from the state an edit
2433
+ * left, the smallest weighted move of the anchors and handles that makes
2434
+ * every residual zero. Each step is the minimum-norm solution of the
2435
+ * linearized system, `Δ = -M Jᵀ (J M Jᵀ + λI)⁻¹ r`, where `M` weighs how
2436
+ * freely each coordinate may move; λ grows when a step makes things worse and
2437
+ * shrinks when it helps, which is the Levenberg-Marquardt schedule run on the
2438
+ * constraint side.
2439
+ *
2440
+ * A handle is a coordinate of its own only where a `tangent` reads it; any
2441
+ * other rides with its anchor, as an offset nothing changes.
2442
+ */
2443
+
2444
+ /** Options for {@link solveConstraints}. */
2445
+ interface SolveConstraintsOptions {
2446
+ /** Anchors the edit put where they are — the dragged ones. They move only when no other anchor can satisfy the constraints. */
2447
+ held?: Iterable<number>;
2448
+ /** Handles the edit put where they are, held the way `held` holds anchors. */
2449
+ heldHandles?: Iterable<HandleRef>;
2450
+ /** Where each anchor was before the edit, which is where a `fixed` constraint keeps it. Default: where it is now. */
2451
+ reference?: readonly (ConstraintPoint | undefined)[];
2452
+ /** Radians the frame `horizontal` and `vertical` read is turned from the world's axes. Default 0. */
2453
+ axisAngle?: number;
2454
+ /** A frame per constraint, by index, over `axisAngle` — for constraints gathered from paths drawn in different frames. */
2455
+ axisAngles?: readonly (number | undefined)[];
2456
+ /** Indices of constraints to leave out of the solve — ones already known not to hold. */
2457
+ skip?: Iterable<number>;
2458
+ /** Default 100. */
2459
+ maxIterations?: number;
2460
+ /** The largest residual the solve stops at. Default 1e-7. */
2461
+ tolerance?: number;
2462
+ }
2463
+ /** What {@link solveConstraints} answers. */
2464
+ interface SolveConstraintsResult {
2465
+ /** Every anchor, moved, with its handles. */
2466
+ points: ConstraintPoint[];
2467
+ /** Whether every constraint the solve took holds within its tolerance. */
2468
+ converged: boolean;
2469
+ iterations: number;
2470
+ /** Indices of the constraints that do not hold in `points`, skipped ones included. */
2471
+ unsatisfied: number[];
2472
+ }
2473
+ /**
2474
+ * Move `points` the least that makes `constraints` hold. Anchors named by a
2475
+ * `fixed` constraint go back to `reference` and stay there; `held` anchors
2476
+ * and `heldHandles` stay where they are when the rest can satisfy the
2477
+ * constraints, and give way as little as they must when not. When the
2478
+ * constraints cannot all hold, `converged` is false and `unsatisfied` names
2479
+ * the ones that do not.
2480
+ */
2481
+ declare function solveConstraints(points: readonly ConstraintPoint[], constraints: readonly PathConstraint[], opts?: SolveConstraintsOptions): SolveConstraintsResult;
2482
+
2483
+ /**
2484
+ * Whether constraints hold for a set of points, and whether a solve made them
2485
+ * hold only by collapsing what they measure.
2486
+ */
2487
+
2488
+ /** The residual, in the path's units, under which a constraint counts as holding. */
2489
+ declare const CONSTRAINT_TOLERANCE = 0.001;
2490
+ /** Options for {@link unsatisfiedConstraints}. */
2491
+ interface UnsatisfiedConstraintsOptions {
2492
+ axisAngle?: number;
2493
+ /** A frame per constraint, by index, over `axisAngle`. */
2494
+ axisAngles?: readonly (number | undefined)[];
2495
+ /** Where a `fixed` anchor belongs. Absent, a `fixed` constraint always holds. */
2496
+ reference?: readonly (ConstraintPoint | undefined)[];
2497
+ /** Default {@link CONSTRAINT_TOLERANCE}. */
2498
+ tolerance?: number;
2499
+ }
2500
+ /**
2501
+ * Indices of the constraints that do not hold for `points`: a residual past
2502
+ * the tolerance, an anchor index the points do not have, or a tangent on an
2503
+ * anchor missing a handle.
2504
+ */
2505
+ declare function unsatisfiedConstraints(points: readonly ConstraintPoint[], constraints: readonly PathConstraint[], opts?: UnsatisfiedConstraintsOptions): number[];
2506
+
2507
+ /**
2508
+ * Constraints on a `PolygonPath`: solving them over its anchors, and carrying
2509
+ * them through an edit that renumbers the anchors.
2510
+ */
2511
+
2512
+ /** Every anchor of `path`, by flat index, with the handles it has. */
2513
+ declare function pathAnchorPoints(path: PolygonPath): ConstraintPoint[];
2514
+ /** {@link solveConstraints} over `path`'s anchors, and `path` with them moved. */
2515
+ interface SolvePathConstraintsResult extends SolveConstraintsResult {
2516
+ /** `path` with each anchor moved where the solve put it, its handles moved with it; `path` itself when none moved. */
2517
+ path: PolygonPath;
2518
+ }
2519
+ /**
2520
+ * Solve `constraints` over the anchors of `path` and write the result back,
2521
+ * carrying each moved anchor's handles with it so its curves keep their
2522
+ * shape, except where a `tangent` turned them.
2523
+ */
2524
+ declare function solvePathConstraints(path: PolygonPath, constraints: readonly PathConstraint[], opts?: SolveConstraintsOptions): SolvePathConstraintsResult;
2525
+ /**
2526
+ * `path` with its anchors and handles where `to` puts them, given `from`,
2527
+ * where they are now; `path` itself when nothing moved.
2528
+ */
2529
+ declare function withAnchorPoints(path: PolygonPath, from: readonly ConstraintPoint[], to: readonly ConstraintPoint[]): PolygonPath;
2530
+ /**
2531
+ * For each anchor of `after`, the anchor of `before` it is: the one whose
2532
+ * point `origins` says it was copied from. An anchor the edit made has none.
2533
+ * `origins` is what `editAnchorSetTracked` answered for the edit.
2534
+ */
2535
+ declare function anchorsBefore(before: PolygonPath, after: PolygonPath, origins: readonly (PointOrigin | null)[]): (number | undefined)[];
2536
+ /**
2537
+ * `constraints` renumbered for the anchors of a path after an edit, given
2538
+ * `wasAnchor` — for each new anchor, the old one it is, as
2539
+ * {@link anchorsBefore} answers. A constraint naming an anchor the edit
2540
+ * removed is dropped; `from` holds each kept one's index in `constraints`.
2541
+ */
2542
+ declare function remapConstraints(constraints: readonly PathConstraint[], wasAnchor: readonly (number | undefined)[]): {
2543
+ constraints: PathConstraint[];
2544
+ from: number[];
2545
+ };
2546
+ /**
2547
+ * The segment of `path` joining anchors `a` and `b`, as the pair in the order
2548
+ * the path runs it, or null when no segment joins them.
2549
+ */
2550
+ declare function segmentBetween(path: PolygonPath, a: number, b: number): AnchorPair | null;
2551
+
2552
+ /**
2553
+ * Finishing an edit of constrained paths so their constraints hold: one path
2554
+ * on its own, or several solved together when links — constraints naming
2555
+ * anchors of more than one — tie them.
2556
+ */
2557
+
2558
+ /** Options for {@link constrainPathEdit}. */
2559
+ interface ConstrainPathEditOptions {
2560
+ /**
2561
+ * Where each point of the edited path came from, as `editAnchorSetTracked`
2562
+ * answers. Absent, the edit is taken to keep every anchor's number, and one
2563
+ * that changes the anchor count drops every constraint.
2564
+ */
2565
+ origins?: readonly (PointOrigin | null)[];
2566
+ /** See {@link SolveConstraintsOptions.axisAngle}. */
2567
+ axisAngle?: number;
2568
+ }
2569
+ /** What {@link constrainPathEdit} answers. */
2570
+ interface ConstrainedPathEdit {
2571
+ /** The edited path with the constraints holding again. */
2572
+ path: PolygonPath;
2573
+ /** The constraints renumbered for `path`'s anchors. */
2574
+ constraints: PathConstraint[];
2575
+ /** Whether every constraint that held before the edit holds after it. */
2576
+ converged: boolean;
2577
+ /** Indices into `constraints` of the ones that do not hold, including any that already did not before the edit. */
2578
+ unsatisfied: number[];
2579
+ }
2580
+ /** One path of a {@link constrainPathsEdit}: its edit, and its own constraints. */
2581
+ interface PathsEditItem extends ConstrainPathEditOptions {
2582
+ before: PolygonPath;
2583
+ /** `before` as the edit left it; `before` itself for a path the edit did not touch. */
2584
+ after: PolygonPath;
2585
+ constraints: readonly PathConstraint[];
2586
+ /** For a path the edit left alone: its anchors give way as freely as any the edit did not move, rather than only when the edited paths cannot. */
2587
+ yields?: boolean;
2588
+ }
2589
+ /**
2590
+ * A constraint across paths. Its anchors are numbered over the anchors of
2591
+ * `paths` — indices into the items — one after another in that order: with
2592
+ * `paths: [2, 0]` and a 5-anchor item 2, anchor 6 is item 0's anchor 1. Its
2593
+ * `horizontal` and `vertical` read the world's axes.
2594
+ */
2595
+ interface PathLink {
2596
+ constraint: PathConstraint;
2597
+ paths: readonly number[];
2598
+ }
2599
+ /** What {@link constrainPathsEdit} answers. */
2600
+ interface ConstrainedPathsEdit {
2601
+ /** Each item, in order: its path with the constraints holding, and its own constraints renumbered for it. */
2602
+ items: {
2603
+ path: PolygonPath;
2604
+ constraints: PathConstraint[];
2605
+ unsatisfied: number[];
2606
+ }[];
2607
+ /** Each link renumbered over its paths' anchors after the edit; null when the edit removed an anchor it names. */
2608
+ links: {
2609
+ constraint: PathConstraint | null;
2610
+ satisfied: boolean;
2611
+ }[];
2612
+ /** Whether every constraint that held before the edit holds after it. */
2613
+ converged: boolean;
2614
+ }
2615
+ /**
2616
+ * An edit of constrained paths, finished so their constraints and the links
2617
+ * between them hold, as one solve over every anchor: the anchors and handles
2618
+ * the edit moved are held, and so are the anchors of a path it left alone
2619
+ * (`after === before`), except one held on a segment or on a path that
2620
+ * `yields`; `fixed` anchors go
2621
+ * back to where they were, and the rest move the least they must. A constraint
2622
+ * that did not hold before the edit is left out of the solve, and reported.
2623
+ * Each item's own `horizontal` and `vertical` read its own `axisAngle`.
2624
+ */
2625
+ declare function constrainPathsEdit(items: readonly PathsEditItem[], links?: readonly PathLink[]): ConstrainedPathsEdit;
2626
+ /**
2627
+ * An edit of a constrained path, `before` → `after`, finished so its
2628
+ * constraints hold: the anchors and handles the edit moved are held, `fixed`
2629
+ * anchors go back to where they were, and the rest move the least they must.
2630
+ * A constraint that did not hold before the edit conflicts with the others
2631
+ * and is left out of the solve rather than allowed to pull them out of true;
2632
+ * `unsatisfied` reports it.
2633
+ */
2634
+ declare function constrainPathEdit(before: PolygonPath, after: PolygonPath, constraints: readonly PathConstraint[], opts?: ConstrainPathEditOptions): ConstrainedPathEdit;
2635
+
2636
+ /**
2637
+ * Which constraints conflict: not merely the ones a failed solve leaves
2638
+ * unsatisfied, but a smallest set that cannot all hold together, found by a
2639
+ * deletion filter — drop each member in turn, and keep it out when what is
2640
+ * left still fails. Every member of the answer is needed for the conflict.
2641
+ */
2642
+
2643
+ /** Options for {@link conflictingConstraints}. */
2644
+ interface ConflictingConstraintsOptions {
2645
+ /** Radians the frame `horizontal` and `vertical` read is turned from the world's axes. Default 0. */
2646
+ axisAngle?: number;
2647
+ /** A frame per constraint, by index, over `axisAngle`. */
2648
+ axisAngles?: readonly (number | undefined)[];
2649
+ /** Where each anchor belongs for a `fixed` constraint. Default: where it is now. */
2650
+ reference?: readonly (ConstraintPoint | undefined)[];
2651
+ }
2652
+ /**
2653
+ * The constraints of `constraints` that conflict over `points`: for every
2654
+ * group of them sharing anchors that cannot all hold, a smallest subset that
2655
+ * still cannot — each member needed, the later ones in the list kept in
2656
+ * preference to the earlier — and every constraint that cannot apply at all.
2657
+ * Sorted; empty when every constraint can hold at once.
2658
+ */
2659
+ declare function conflictingConstraints(points: readonly ConstraintPoint[], constraints: readonly PathConstraint[], opts?: ConflictingConstraintsOptions): number[];
2660
+
2661
+ /**
2662
+ * Edits to a path's order rather than its shape: where a subpath starts, and
2663
+ * which way it runs. Each mutates an `AnchorSet` in place, like the edits in
2664
+ * `anchorEdits`, and moves anchors whole, so anything an anchor carries beside
2665
+ * its point and handles travels with it.
2666
+ */
2667
+
2668
+ /**
2669
+ * Make the anchor at `flatIndex` its subpath's first. A closed subpath turns
2670
+ * so it starts there, keeping its direction. An open subpath can only start
2671
+ * at one of its ends: its last anchor makes it run the other way, and an
2672
+ * interior anchor changes nothing. Returns whether the set changed.
2673
+ */
2674
+ declare function setSubpathStart(set: AnchorSet, flatIndex: number): boolean;
2675
+ /**
2676
+ * Run each subpath in `subs` the other way, every one when `subs` is absent.
2677
+ * The shape is unchanged: each anchor's handles trade places. A closed
2678
+ * subpath keeps its start anchor, as `reversePath` does; an open one starts
2679
+ * where it used to end. Returns whether any subpath had a segment to turn.
2680
+ */
2681
+ declare function reverseSubpaths(set: AnchorSet, subs?: Iterable<number>): boolean;
2682
+ /**
2683
+ * Where each anchor at `flatIndexes` sits once `reverseSubpaths(set, subs)`
2684
+ * has run: an anchor keeps its point, so a selection can follow it. Indexes
2685
+ * outside the set are dropped.
2686
+ */
2687
+ declare function flatIndexesAfterReverse(set: AnchorSet, flatIndexes: Iterable<number>, subs?: Iterable<number>): number[];
2688
+ /** The subpaths holding the anchors at `flatIndexes`, each once, in order. */
2689
+ declare function subpathsOfAnchors(set: AnchorSet, flatIndexes: Iterable<number>): number[];
2690
+ /** A mark showing which way a path runs: a point on it and the unit vector of its heading there. */
2691
+ interface DirectionMark {
2692
+ x: number;
2693
+ y: number;
2694
+ dx: number;
2695
+ dy: number;
2696
+ /** The subpath the mark is on. */
2697
+ sub: number;
2698
+ }
2699
+ /**
2700
+ * One {@link DirectionMark} at the middle of every segment of `set`, closing
2701
+ * segments included, in walk order. A segment with no length gets none.
2702
+ */
2703
+ declare function directionMarks(set: AnchorSet): DirectionMark[];
2704
+
2705
+ /**
2706
+ * Straight and curved segments, converted in place. A segment runs from one
2707
+ * anchor to the next, the closing segment of a closed subpath included, and is
2708
+ * named `(sub, segIdx)` as `segmentAt` reports it.
2709
+ */
2710
+
2711
+ /** A segment of an `AnchorSet`: `segIdx === sub.length - 1` is a closed
2712
+ * subpath's closing segment. */
2713
+ interface SegmentRef {
2714
+ sub: number;
2715
+ segIdx: number;
2716
+ }
2717
+ /** What a segment is made: a line, a curve, or the other of what it is. */
2718
+ type SegmentType = 'line' | 'curve';
2719
+ /**
2720
+ * The segments both of whose ends are among `flatIndexes`, in walk order.
2721
+ * Two adjacent selected anchors select the segment between them; a closed
2722
+ * subpath with every anchor selected has all its segments.
2723
+ */
2724
+ declare function segmentsBetweenAnchors(set: AnchorSet, flatIndexes: Iterable<number>): SegmentRef[];
2725
+ /** Whether segment `seg` is straight, or null when it does not exist. */
2726
+ declare function isSegmentStraight(set: AnchorSet, seg: SegmentRef): boolean | null;
2727
+ /**
2728
+ * Make each segment in `segs` straight or curved without moving its anchors.
2729
+ * A line becomes a curve with its handles a third of the way in from each
2730
+ * end, which draws the same line; a curve becomes a line by dropping the two
2731
+ * handles that shape it, leaving the handles of the segments beside it alone.
2732
+ * With no `to`, every segment turns curved when any of them is straight, and
2733
+ * straight when all are curved: one press flips the lot.
2734
+ *
2735
+ * Returns whether any segment changed.
2736
+ */
2737
+ declare function convertSegments(set: AnchorSet, segs: readonly SegmentRef[], to?: SegmentType): boolean;
2738
+
2739
+ /**
2740
+ * Anchors as numbers a person types: the position of the selected anchors,
2741
+ * and for a lone anchor its handles' positions, angles and lengths. Reading
2742
+ * answers what a field shows; writing sets a value on every selected anchor,
2743
+ * or offsets each by an amount.
2744
+ */
2745
+
2746
+ /** One number of an anchor. Handle angles are degrees counterclockwise from
2747
+ * +x as drawn, where y grows downward; lengths and positions are in the
2748
+ * set's own units. */
2749
+ type AnchorField = 'x' | 'y' | 'inX' | 'inY' | 'inAngle' | 'inLength' | 'outX' | 'outY' | 'outAngle' | 'outLength';
2750
+ /** Every {@link AnchorField}, in the order a panel lists them. */
2751
+ declare const ANCHOR_FIELDS: readonly AnchorField[];
2752
+ /** What a typed field asks for: a value for every anchor, or an amount added to each one's own. */
2753
+ type NumberEntry = {
2754
+ to: number;
2755
+ } | {
2756
+ by: number;
2757
+ };
2758
+ /**
2759
+ * What each field shows for the anchors at `flatIndexes`: a number where
2760
+ * they agree, `null` where they differ, and no key for a field that does not
2761
+ * apply. Position applies to any selection; handle fields only to a single
2762
+ * anchor, and only for a handle it has.
2763
+ */
2764
+ type AnchorFieldValues = Partial<Record<AnchorField, number | null>>;
2765
+ /** The fields for the anchors at `flatIndexes`; `{}` when none of them exists. */
2766
+ declare function readAnchorFields(set: AnchorSet, flatIndexes: Iterable<number>): AnchorFieldValues;
2767
+ /**
2768
+ * Write `entry` into `field` of every anchor at `flatIndexes`. Moving an
2769
+ * anchor carries its handles. A handle field moves the handle as a drag to
2770
+ * the typed spot would (`moveHandleTo`): on a smooth anchor the opposite
2771
+ * handle mirrors it, taking its turn and its length, and on a corner it stays
2772
+ * where it is. An anchor without that handle is skipped. An angle keeps the
2773
+ * handle's length, and a length keeps its angle. Returns whether anything
2774
+ * moved.
2775
+ */
2776
+ declare function writeAnchorField(set: AnchorSet, flatIndexes: Iterable<number>, field: AnchorField, entry: NumberEntry): boolean;
2777
+
1550
2778
  /**
1551
2779
  * Anchor lookup across several paths, measured on screen: which existing
1552
2780
  * anchor is nearest a point, and whether it ends an open subpath. Feeds the
@@ -1671,4 +2899,4 @@ declare function reviveTypedArrays(value: unknown): unknown;
1671
2899
  /** `tagTypedArrays` as a `JSON.stringify` replacer. */
1672
2900
  declare function typedArrayReplacer(_key: string, value: unknown): unknown;
1673
2901
 
1674
- export { type Affine, type AnchorRect, type AnchorSet, type AnchorSymmetry, type AverageAxis, type BendGrip, type BezierEasing, type Box, type CubicCoords, type CurveNearest, DEFAULT_FLATTEN_TOLERANCE, EASINGS, EPS, type EasingFn, type EasingName, type EasingSpec, type GlMat3, type LineCoords, type NumberTypedArray, PATH_C, PATH_CMD_LENGTHS, PATH_COMMANDS, PATH_L, PATH_M, PATH_Q, PATH_Z, Path, type PathAnchorHit, PathBuilder, type PathCommandCode, type PathCommandName, PathFillRule, type PathInWorldPose, type PathNearest, PathOpenFill, type PathStation, type PenAnchor, type PlaceRectOptions, type PlacedRect, type Placement, type PlacementAlign, type PlacementSide, Point$1 as Point, type PointAlongPathOptions, type PointInPathOptions, type PointOrigin, type PolygonIntersectsPathOptions, PolygonPath, type PoseLinear, type PoseRotation, type QuadraticCoords, type Rect, RectPath, SPRING_PRESETS, type Scale2, type SegmentHit, type SimplifyPathOptions, type SpringPreset, type SpringPresetName, type StrokeHitTestOptions, type SubpathEnd, TYPED_ARRAY_CONSTRUCTORS, type TaggedTypedArray, type TypedArrayTag, type View, ZOOM_FLOOR, anchorAt, anchorCount, anchorSymmetries, anchorSymmetry, anchorsInRect, anchorsToPath, applyToPoint, approxEq, averageAnchorsAt, bendSegment, boundsOfCoords, boundsOfPath, boxContainsBox, boxContainsPoint, boxToBox, circlePath, clamp, clampRectWithin, closestOpenEnds, composePath, countPathAnchors, cross, cubicBezierEasing, cubicBounds, cubicEvalAt, decomposePath, defaultOpenFill, deleteAnchorsAt, dot, easeIn, easeInBack, easeInBounce, easeInCirc, easeInCubic, easeInElastic, easeInExpo, easeInOut, easeInOutBack, easeInOutBounce, easeInOutCirc, easeInOutCubic, easeInOutElastic, easeInOutExpo, easeInOutQuad, easeInOutQuart, easeInOutQuint, easeInOutSine, easeInQuad, easeInQuart, easeInQuint, easeInSine, easeOut, easeOutBack, easeOutBounce, easeOutCirc, easeOutCubic, easeOutElastic, easeOutExpo, easeOutQuad, easeOutQuart, easeOutQuint, easeOutSine, editAnchorSet, editAnchorSetTracked, elevateQuadraticToCubic, ellipsePath, fillsOpenSubpaths, fitCubicThroughDeletion, fitCubicWithTangents, flatAnchorIndex, flattenCubic, flattenCubicWithArcLen, flattenQuadratic, flattenQuadraticWithArcLen, forEachSegment, handleAlongItsAngle, hasOpenSubpath, identity$1 as identity, insertAnchorOnSegment, invert$1 as invert, isAnchorSmooth, isStraightSegment, joinAnchorsAt, joinSubpathEnds, len2, linePath, linear, locateAnchor, makeHandlesSymmetric, mat3, meanScale, moveHandleSymmetric, moveHandleTo, multiply$1 as multiply, nearestOnCubic, nearestOnLine, nearestOnPath, nearestOnQuadratic, nearestPathAnchor, nearestSegmentT, normalizeZoom, openSubpathAt, pathCommandCoordCount, pathContainsPoint, pathContainsPolygon, pathContainsRect, pathDistanceToPoint, pathFromD, pathInPoseFrame, pathInWorld, pathIntersectsPolygon, pathIntersectsRect, pathSignedArea, pathThroughPoseFrame, pathToAnchors, placeRect, pointAlongPath, pointInPath, pointInPolygon, pointSegmentDist2, polygonContainsPath, polygonFromPoints, polygonIntersectsPath, polylineFromPoints, portControls, portCurvePoints, poseFrameInverseOf, poseFrameOf, poseLinearOf, poseRotationOf, pxExtent, quadraticEvalAt, rectMarkerPath, rectPath, rectToContour, regularPolygonPath, remapPointValues, resolveEasing, retractHandles, reverseAnchors, reversePath, reviveTypedArrays, rotate, rotateAboutPoint, rotatePathAround, roundRectPath, scale, scaleDelta, scalePathToBounds, schneiderFit, screenAngleOf, segmentAt, segmentEnds, segmentsCross, setDefaultOpenFill, sign, simplifyPath, splitByClosure, splitCubicAt, splitLineAt, splitQuadraticAt, splitSubpaths, squarePath, standoff, starPath, strokeHitTest, sub, subpathEndAt, tagTypedArray, tagTypedArrays, transformCoords, transformPath, translate, translateAnchorBy, translateAnchorsSymmetric, translatePath, typedArrayReplacer, unionBoundsPath, unionBox, untagTypedArray, viewToMat3, withinPxBox, withinPxRadius, worldEditToStorage };
2902
+ export { ANCHOR_FIELDS, type Affine, type AnchorField, type AnchorFieldValues, type AnchorPair, type AnchorPathMeasure, AnchorSet, type AnchorSubpathMeasure, type AnchorSymmetry, type AverageAxis, type BendAlongPathOptions, type BendGrip, type BezierEasing, type BlendPathsOptions, type Box, CONSTRAINT_TOLERANCE, CORNER_RESTORE_TOLERANCE, type ConflictingConstraintsOptions, type ConstrainPathEditOptions, type ConstrainedPathEdit, type ConstrainedPathsEdit, type ConstraintPoint, type CornerCut, type CornerFrame, CornerPiece, CornerSpec, type CornerTrace, type CubicContour, type CubicCoords, type CubicSegment, type CurveNearest, DEFAULT_FLATTEN_TOLERANCE, type DirectionMark, EASINGS, EPS, type EasingFn, type EasingName, type EasingSpec, type ExtendToMeetOptions, type FramedBox, type GlMat3, type GrowRegionOptions, type HandleBalance, type HandleRef, type JoinOptions, type LengthenMode, type LineCoords, type MeasureAnchorPathOptions, type MeasurePathOptions, type MergeRegionOptions, type NumberEntry, type NumberTypedArray, type OpenPathEnd, PATH_C, PATH_CMD_LENGTHS, PATH_COMMANDS, PATH_L, PATH_M, PATH_Q, PATH_SNAP_KINDS, PATH_Z, Path, type PathAnchorHit, type PathAwayFromAnchors, type PathBlend, PathBuilder, type PathCommandCode, type PathCommandName, type PathConstraint, type PathConstraintKind, type PathCrossing, type PathEndFrame, PathFillRule, type PathInWorldPose, type PathLink, type PathMeasure, type PathNearest, type PathNearestStation, PathOpenFill, type PathSegment, type PathSnapHit, type PathSnapIndex, type PathSnapKind, type PathSnapQuery, type PathSnapTarget, type PathStation, type PathStop, type PathsEditItem, PenAnchor, type PlaceRectOptions, type PlacedRect, type Placement, type PlacementAlign, type PlacementSide, Point, type PointAlongPathOptions, type PointInPathOptions, type PointOrigin, type PolygonIntersectsPathOptions, PolygonPath, type PoseLinear, type PoseRotation, type QuadraticCoords, type Rect, RectPath, type RepeatAlongPathOptions, type RepeatStation, type ResamplePathOptions, type ResolvedCorners, SPRING_PRESETS, Scale2, type SegmentCrossing, type SegmentMeasure, type SegmentRef, type SegmentType, type SimplifyPathOptions, type SmudgePathOptions, type SoftFalloff, type SolveConstraintsOptions, type SolveConstraintsResult, type SolvePathConstraintsResult, type SpiroContour, SpiroKind, type SpiroPath, SpiroPoint, type SpiroToPathOptions, type SpringPreset, type SpringPresetName, type StaticPathSnapKind, type StrokeHitTestOptions, type SubpathEnd, TYPED_ARRAY_CONSTRUCTORS, type TaggedTypedArray, type TrimPathOptions, type TrimResult, type TypedArrayTag, type UnsatisfiedConstraintsOptions, type View, ZOOM_FLOOR, addExtremaAnchors, anchorOriginsOf, anchorSymmetries, anchorSymmetry, anchorsBefore, anchorsUnderBrush, anchorsWhere, applyToPoint, approxEq, asPolygonPath, averageAnchorsAt, balanceFactorToward, bendAlongPath, bendSegment, blendPaths, boundsOfCoords, boundsOfPath, boxContainsBox, boxContainsPoint, boxToBox, circlePath, clamp, clampRectWithin, closestOpenEnds, composePath, conflictingConstraints, constrainPathEdit, constrainPathsEdit, constraintAnchors, constraintApplies, constraintFits, convertSegments, cornerAnchors, cornerCuts, cornerFrameAt, cornerFrames, cornerTraces, createPathSnapIndex, cross, cubicAxisExtremaTs, cubicBezierEasing, cubicBounds, cubicContoursToPath, cubicEvalAt, decomposePath, defaultOpenFill, directionMarks, dot, easeIn, easeInBack, easeInBounce, easeInCirc, easeInCubic, easeInElastic, easeInExpo, easeInOut, easeInOutBack, easeInOutBounce, easeInOutCirc, easeInOutCubic, easeInOutElastic, easeInOutExpo, easeInOutQuad, easeInOutQuart, easeInOutQuint, easeInOutSine, easeInQuad, easeInQuart, easeInQuint, easeInSine, easeOut, easeOutBack, easeOutBounce, easeOutCirc, easeOutCubic, easeOutElastic, easeOutExpo, easeOutQuad, easeOutQuart, easeOutQuint, easeOutSine, editAnchorSetTracked, elevateQuadraticToCubic, ellipsePath, equalizeSegmentHandles, everyNthAnchor, extendToMeet, fillsOpenSubpaths, findPathSnap, findPathSnaps, fitAffine, fitCubicThroughDeletion, fitCubicWithTangents, flatIndexesAfterReverse, flattenCubic, flattenCubicWithArcLen, flattenQuadratic, flattenQuadraticWithArcLen, forEachSegment, growAnchorSelection, growRegion, handleAlongItsAngle, handleAtItsLength, handleBalances, harmonizeAnchors, hasOpenSubpath, identity$1 as identity, intersectSegments, invert$1 as invert, invertAnchorSelection, isSegmentStraight, joinAnchorsAt, joinSubpathEnds, keepCorners, len2, lengthToward, lengthenOpenEnd, lengthenPathEnd, linePath, linear, makeHandlesSymmetric, mapConstraintAnchors, mat3, meanScale, measureAnchorPath, measurePath, mergeRegion, moveHandleSymmetric, multiply$1 as multiply, nearestOnCubic, nearestOnLine, nearestOnPath, nearestOnQuadratic, nearestPathAnchor, normalizeZoom, offsetCornerTraces, openEndAt, openEndRay, openPathEnds, pathAnchorPoints, pathAwayFromAnchors, pathCommandCoordCount, pathContainsPoint, pathContainsPolygon, pathContainsRect, pathCrossings, pathDistanceToPoint, pathEndAnchorIndex, pathEndFrame, pathFromD, pathInPoseFrame, pathInWorld, pathIntersectsPolygon, pathIntersectsRect, pathSegments, pathSignedArea, pathThroughPoseFrame, pathToCubicContours, pathToD, placeRect, pointAlongPath, pointInPath, pointInPolygon, pointSegmentDist2, polygonContainsPath, polygonFromPoints, polygonIntersectsPath, polylineFromPoints, portControls, portCurvePoints, poseFrameInverseOf, poseFrameOf, poseLinearOf, poseRotationOf, prepareBlend, quadraticEvalAt, readAnchorFields, rectMarkerPath, rectPath, rectToContour, regularPolygonPath, remapAnchorValues, remapConstraints, remapPerAnchor, remapPointValues, repeatAlongPath, resamplePath, resolveCorners, resolveCornersWithSources, resolveEasing, restoreCorners, retractHandles, reverseAnchors, reversePath, reverseSubpaths, reviveTypedArrays, rotate, rotateAboutPoint, rotatePathAround, roundRectPath, scale, scalePathToBounds, scaleSegmentHandles, schneiderFit, segmentBetween, segmentExtremaTs, segmentsBetweenAnchors, segmentsCross, setDefaultOpenFill, setSubpathStart, shrinkAnchorSelection, sign, simplifyAnchorsAt, simplifyPath, simplifySpan, simplifySubpath, smoothAnchors, smudgePath, softFalloff, softSelectionBand, softSelectionWeights, solveConstraints, solvePathConstraints, spiroContoursFromControl, spiroContoursOf, spiroControlPath, spiroToPath, splitByClosure, splitCubicAt, splitLineAt, splitQuadraticAt, splitSubpaths, squarePath, starPath, stationsAlongPath, strokeHitTest, sub, subpathEndAt, subpathsOfAnchors, tagTypedArray, tagTypedArrays, transformCoords, transformPath, translate, translateAnchorsSymmetric, translatePath, trimPathAt, typedArrayReplacer, unionBoundsPath, unionBox, unsatisfiedConstraints, untagTypedArray, viewToMat3, withAnchorPoints, worldEditToStorage, writeAnchorField };