@weasel-js/geom 1.10.1 → 1.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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 +15 -10
  6. package/dist/booleans/index.js +306 -353
  7. package/dist/booleans/index.js.map +1 -1
  8. package/dist/{chunk-7WFFCHRL.js → chunk-6XSJY3TC.js} +6 -37
  9. package/dist/chunk-6XSJY3TC.js.map +1 -0
  10. package/dist/chunk-7KLJZFBY.js +573 -0
  11. package/dist/chunk-7KLJZFBY.js.map +1 -0
  12. package/dist/chunk-B53BERKG.js +386 -0
  13. package/dist/chunk-B53BERKG.js.map +1 -0
  14. package/dist/chunk-CE7IY7TB.js +104 -0
  15. package/dist/chunk-CE7IY7TB.js.map +1 -0
  16. package/dist/chunk-HGF5OVEN.js +129 -0
  17. package/dist/chunk-HGF5OVEN.js.map +1 -0
  18. package/dist/chunk-J2O2B54M.js +800 -0
  19. package/dist/chunk-J2O2B54M.js.map +1 -0
  20. package/dist/chunk-Q66NA2FU.js +174 -0
  21. package/dist/chunk-Q66NA2FU.js.map +1 -0
  22. package/dist/chunk-SASMXDBE.js +443 -0
  23. package/dist/chunk-SASMXDBE.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 +1468 -284
  31. package/dist/index.js +5450 -2672
  32. package/dist/index.js.map +1 -1
  33. package/dist/nd/index.d.ts +91 -27
  34. package/dist/nd/index.js +282 -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 +252 -0
  42. package/dist/warp/index.js +1316 -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
 
@@ -545,6 +676,48 @@ declare function reversePath(path: PolygonPath): PolygonPath;
545
676
  */
546
677
  declare function pathFromD(d: string, onWarn?: (message: string) => void): ReturnType<PathBuilder['build']>;
547
678
 
679
+ /**
680
+ * A path measured once by arc length, so many stations along it cost a binary
681
+ * search each rather than a fresh flatten: what `pointAlongPath` answers one
682
+ * fraction at a time, and what anything placing or bending geometry along a
683
+ * path reads many times over.
684
+ */
685
+
686
+ /** A point on a path and its heading there. */
687
+ interface PathStation {
688
+ point: Point;
689
+ /** Unit vector along the path at `point`, pointing toward the end. */
690
+ tangent: Point;
691
+ }
692
+ /** Options for {@link measurePath}. */
693
+ interface MeasurePathOptions {
694
+ /** Curve flattening tolerance, in world units. Default 0.5. */
695
+ flattenTolerance?: number;
696
+ }
697
+ /** A measured path: its length, and the station at any distance along it. */
698
+ interface PathMeasure {
699
+ /** Total arc length, every subpath counted in order. */
700
+ readonly length: number;
701
+ /** True when the path is a single closed contour, so a distance past the
702
+ * end can wrap round to the start. */
703
+ readonly closed: boolean;
704
+ /**
705
+ * The station `s` along the path, `s` clamped to `0..length`.
706
+ *
707
+ * The tangent is the heading of the flattened segment under `s`. With
708
+ * `smooth`, it is instead blended across each segment from the heading at
709
+ * one vertex to the next, so geometry bent along it turns without facets.
710
+ */
711
+ at(s: number, smooth?: boolean): PathStation;
712
+ }
713
+ /**
714
+ * Measure `path` by arc length. Subpaths are measured in order and treated as
715
+ * one run, the way a browser measures a whole `<path>`. Returns `null` for a
716
+ * path with no points; a path of zero length answers at its single point,
717
+ * heading along +X.
718
+ */
719
+ declare function measurePath(path: Path, opts?: MeasurePathOptions): PathMeasure | null;
720
+
548
721
  /**
549
722
  * A station along a path: where it is at a fraction of its length, and which
550
723
  * way it is heading there.
@@ -552,20 +725,12 @@ declare function pathFromD(d: string, onWarn?: (message: string) => void): Retur
552
725
  * For anything positioned *along* geometry rather than beside it — a label on a
553
726
  * routed edge, a tick on a curve, a badge near an arrowhead. Curves are
554
727
  * 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.
728
+ * than a curve parameter, which is what makes 0.5 look like the middle. For
729
+ * many stations along one path, measure it once with `measurePath`.
556
730
  */
557
731
 
558
- /** The answer `pointAlongPath` gives: a point on the path and its heading there. */
559
- interface PathStation {
560
- point: Point$1;
561
- /** Unit vector along the path at `point`, pointing toward the end. */
562
- tangent: Point$1;
563
- }
564
732
  /** Options for `pointAlongPath`. */
565
- interface PointAlongPathOptions {
566
- /** Curve flattening tolerance, in world units. Default 0.5. */
567
- flattenTolerance?: number;
568
- }
733
+ type PointAlongPathOptions = MeasurePathOptions;
569
734
  /**
570
735
  * Where `path` is at `t` of its total length, and its heading there.
571
736
  *
@@ -576,6 +741,144 @@ interface PointAlongPathOptions {
576
741
  */
577
742
  declare function pointAlongPath(path: Path, t: number, opts?: PointAlongPathOptions): PathStation | null;
578
743
 
744
+ /** One cubic segment, `[x0, y0, x1, y1, x2, y2, x3, y3]`, and whether it was
745
+ * drawn straight. A straight one keeps its controls at its thirds, so it
746
+ * interpolates and warps as a line would. */
747
+ interface CubicSegment {
748
+ c: [number, number, number, number, number, number, number, number];
749
+ line: boolean;
750
+ }
751
+ /** One contour of segments, each starting where the one before it ends. */
752
+ interface CubicContour {
753
+ segs: CubicSegment[];
754
+ closed: boolean;
755
+ }
756
+ /**
757
+ * `path`'s contours as cubic segments. A closed contour whose last point
758
+ * stops short of its first gains the straight closing edge it is drawn with;
759
+ * zero-length straight segments are dropped. A contour with no segments is a
760
+ * lone point and is left out. Corner specs are expanded first.
761
+ */
762
+ declare function pathToCubicContours(path: Path): CubicContour[];
763
+ /** The path drawing `contours`: a straight segment as `L`, the rest as `C`. */
764
+ declare function cubicContoursToPath(contours: readonly CubicContour[], fillRule?: PathFillRule): PolygonPath;
765
+
766
+ /**
767
+ * Shape interpolation between two paths: the steps of a blend, or the frames
768
+ * of a morph.
769
+ *
770
+ * The two shapes are matched once — contour to contour, then segment to
771
+ * segment — and every step is a straight lerp of the matched control points.
772
+ * Where one contour has fewer segments, its longest ones are split in half
773
+ * until the counts agree, which adds anchors without moving the outline.
774
+ */
775
+
776
+ /** How a blend matches the second shape's anchors to the first's. */
777
+ interface BlendPathsOptions {
778
+ /**
779
+ * Choose, for each pair of contours, the start point (and, when `reverse`
780
+ * is unset, the direction) of the second that keeps matched anchors
781
+ * closest, with both contours centered on their own middles first so that
782
+ * where the shapes sit does not decide it. Default `true`.
783
+ */
784
+ autoAlign?: boolean;
785
+ /**
786
+ * Turn the second shape's start point this many anchors further round each
787
+ * closed contour, after any `autoAlign` choice. Negative turns it back.
788
+ * Default 0.
789
+ */
790
+ startOffset?: number;
791
+ /** Run the second shape's contours backwards. Unset, `autoAlign` decides;
792
+ * without it, they run as drawn. */
793
+ reverse?: boolean;
794
+ }
795
+ /** Two shapes matched for interpolation. */
796
+ interface PathBlend {
797
+ /** The shape `t` of the way from the first to the second: exactly the
798
+ * first at 0 and the second at 1, up to the anchors matching added. */
799
+ at(t: number): PolygonPath;
800
+ /** Segments per matched pair of contours. */
801
+ readonly segmentCounts: readonly number[];
802
+ }
803
+ /** The shape `t` of the way from `a` to `b`. Matching once with
804
+ * {@link prepareBlend} is cheaper when several steps are wanted. */
805
+ declare function blendPaths(a: Path, b: Path, t: number, opts?: BlendPathsOptions): PolygonPath;
806
+ /** Match `a` to `b` for interpolation. */
807
+ declare function prepareBlend(a: Path, b: Path, opts?: BlendPathsOptions): PathBlend;
808
+
809
+ /**
810
+ * Bend a shape along a spine: the shape's x becomes distance along the spine
811
+ * and its y distance off it, along the spine's normal. A straight edge of the
812
+ * shape comes out curved wherever the spine bends, so each segment is
813
+ * sampled through the warp and refit to cubics within a tolerance; anchors
814
+ * stay where they were, so a corner of the shape stays a corner.
815
+ */
816
+
817
+ /** How a shape is laid along its spine. */
818
+ interface BendAlongPathOptions {
819
+ /**
820
+ * `'stretch'`, the default, spreads the shape's width over the spine's
821
+ * whole length. `'natural'` keeps its width: one unit across the shape is
822
+ * one unit along the spine, starting at the spine's start, and a shape
823
+ * longer than the spine runs on straight past its end.
824
+ */
825
+ fit?: 'stretch' | 'natural';
826
+ /** Where across the shape's height the spine runs, 0 at its top and 1 at
827
+ * its bottom. Default 0.5, the middle. */
828
+ baseline?: number;
829
+ /** Lay the shape on the other side of the spine, mirrored across it. */
830
+ flip?: boolean;
831
+ /** How far the refit curves may stray from the exact bend, in world
832
+ * units. Default 0.5. */
833
+ tolerance?: number;
834
+ }
835
+ /**
836
+ * `shape` bent along `spine`. A spine heading left to right keeps the shape
837
+ * upright; one heading the other way turns it over, as a road sign painted
838
+ * along a lane does. Returns `null` when the spine has no length or the shape
839
+ * nothing to bend.
840
+ */
841
+ declare function bendAlongPath(shape: Path, spine: Path, opts?: BendAlongPathOptions): PolygonPath | null;
842
+
843
+ /** How copies are spaced along a path. */
844
+ interface RepeatAlongPathOptions {
845
+ /**
846
+ * How many copies. With no `spacing`, they spread evenly over the whole
847
+ * path — end to end on an open one, evenly round a closed one — and the
848
+ * default is 5. With a `spacing`, it caps the run; unset, as many as fit.
849
+ */
850
+ count?: number;
851
+ /** Distance along the path from one copy's center to the next. */
852
+ spacing?: number;
853
+ /** Where a spaced run that is shorter than the path sits on it. Default
854
+ * `'start'`. */
855
+ align?: 'start' | 'center' | 'end';
856
+ /** Slide every copy this far along the path. On an open path a copy slid
857
+ * off either end is dropped; round a closed one it wraps. Default 0. */
858
+ offset?: number;
859
+ /** Turn each copy to the path's heading where it sits. Default `true`. */
860
+ orient?: boolean;
861
+ /** Curve flattening tolerance for measuring the path. Default 0.5. */
862
+ flattenTolerance?: number;
863
+ }
864
+ /** Where one copy sits. */
865
+ interface RepeatStation {
866
+ point: Point;
867
+ /** The path's heading there, radians clockwise from +X in a y-down frame. */
868
+ angle: number;
869
+ /** Arc length from the path's start. */
870
+ distance: number;
871
+ }
872
+ /** The stations copies sit at along `path`, in order. Empty for a path with
873
+ * no points. */
874
+ declare function stationsAlongPath(path: Path, opts?: RepeatAlongPathOptions): RepeatStation[];
875
+ /**
876
+ * Copies of `shape`, each centered on a station along `path` — its bounding
877
+ * box's middle on the path — and, with `orient`, turned to the heading
878
+ * there. The shape's own +X runs along the path.
879
+ */
880
+ declare function repeatAlongPath(shape: Path, path: Path, opts?: RepeatAlongPathOptions): Path[];
881
+
579
882
  /**
580
883
  * Pure-geometry distance from a point to a path's boundary (stroke), with
581
884
  * no fill-side logic. Used by pickers that want to know "how close is this
@@ -593,88 +896,312 @@ declare function pointAlongPath(path: Path, t: number, opts?: PointAlongPathOpti
593
896
  * combine with `pathContainsPoint` at the call site. */
594
897
  declare function pathDistanceToPoint(path: Path, px: number, py: number): number;
595
898
 
899
+ /** Where two Bézier segments cross, by subdivision then Newton refinement. */
900
+
901
+ /** One crossing of segments `a` and `b`: the parameter on each, and the point. */
902
+ interface SegmentCrossing {
903
+ ta: number;
904
+ tb: number;
905
+ x: number;
906
+ y: number;
907
+ }
596
908
  /**
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.
909
+ * Every point where segment `a` crosses or touches segment `b` — each a line,
910
+ * quadratic or cubic given by its control points — with the parameter on
911
+ * each. Two lines are solved exactly; a curve is subdivided until its pieces
912
+ * are flat, their chords crossed, and the answer refined against the curves.
913
+ * Segments that overlap along a stretch report at most a few points of it.
914
+ * Sorted by `ta`.
605
915
  */
916
+ declare function intersectSegments(a: Point[], b: Point[]): SegmentCrossing[];
917
+
918
+ /** A path's stroke as a flat list of segments, each knowing where it sits. */
606
919
 
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 {
920
+ /** One segment of a path's stroke, in the order the path draws them. */
921
+ interface PathSegment {
922
+ /** Control points: 2 for a line, 3 for a quadratic, 4 for a cubic. */
923
+ pts: Point[];
924
+ /** Index of its subpath among the path's subpaths. */
925
+ sub: number;
926
+ /** Index within its subpath. */
927
+ index: number;
928
+ /** Segments in its subpath. */
929
+ count: number;
930
+ /** Whether its subpath is closed, so its last segment meets its first. */
931
+ closed: boolean;
932
+ /** Axis-aligned box of the control points, which holds the segment. */
933
+ box: {
934
+ x0: number;
935
+ y0: number;
936
+ x1: number;
937
+ y1: number;
938
+ };
939
+ }
940
+ /** `path`'s stroke as segments: a closed subpath includes its closing edge,
941
+ * an open one does not, and a zero-length line is left out. */
942
+ declare function pathSegments(path: Path): PathSegment[];
943
+
944
+ /** Where paths cross one another and themselves. */
945
+
946
+ /** A place on a path's stroke: which segment, and how far along it. */
947
+ interface PathStop {
948
+ /** Index of the path in the list it came from. */
949
+ path: number;
950
+ sub: number;
951
+ /** Segment index within the subpath. */
952
+ index: number;
953
+ /** Parameter on that segment, in [0, 1]. */
954
+ t: number;
955
+ }
956
+ /** A point where two strokes cross or touch, and where it falls on each. */
957
+ interface PathCrossing {
611
958
  x: number;
612
959
  y: number;
613
- inHandle?: {
614
- x: number;
615
- y: number;
616
- };
617
- outHandle?: {
960
+ a: PathStop;
961
+ b: PathStop;
962
+ }
963
+ /**
964
+ * Every crossing among `paths`: between each pair, and — unless `self` is
965
+ * false — of a path with itself, leaving out the joint where one segment
966
+ * meets the next. Points where strokes merely touch count too. With `of`,
967
+ * only the crossings involving that one path.
968
+ */
969
+ declare function pathCrossings(paths: readonly Path[], opts?: {
970
+ self?: boolean;
971
+ of?: number;
972
+ }): PathCrossing[];
973
+
974
+ /**
975
+ * Geometric snapping onto paths: the points on a set of strokes a drawn or
976
+ * dragged point can lock to, and which of them a probe lands on.
977
+ */
978
+
979
+ /**
980
+ * What a snap target is.
981
+ *
982
+ * - `anchor` — an end of a segment: a path's anchors, a box's corners.
983
+ * - `center` — a point a caller names as the middle of something: a text or
984
+ * image box's center, given to {@link createPathSnapIndex} as a target.
985
+ * - `intersection` — where two strokes cross, or one crosses itself.
986
+ * - `tangent` — where a line from the query's origin touches a curve.
987
+ * - `perpendicular` — where a line from the origin meets a stroke square on.
988
+ * - `midpoint` — the middle of a segment by length.
989
+ * - `extremum` — on a curve, where its tangent turns horizontal or vertical.
990
+ * - `quadrant` — where a closed subpath crosses the horizontal and vertical
991
+ * lines through the center of its box: a circle's four compass points.
992
+ * - `nearest` — the closest point on any stroke, when nothing else is in range.
993
+ */
994
+ type PathSnapKind = 'anchor' | 'center' | 'intersection' | 'tangent' | 'perpendicular' | 'midpoint' | 'extremum' | 'quadrant' | 'nearest';
995
+ /** Every snap kind, in the order a picker lists them. */
996
+ declare const PATH_SNAP_KINDS: readonly PathSnapKind[];
997
+ /** The kinds whose targets stand whatever the probe. */
998
+ type StaticPathSnapKind = 'anchor' | 'center' | 'intersection' | 'midpoint' | 'extremum' | 'quadrant';
999
+ /** A target the probe landed on. */
1000
+ interface PathSnapHit {
1001
+ kind: PathSnapKind;
1002
+ x: number;
1003
+ y: number;
1004
+ /** Distance from the probe, in the query's `radius` units. */
1005
+ distance: number;
1006
+ /** Indices of the paths that make the target: two for a crossing between
1007
+ * paths, one otherwise. */
1008
+ paths: readonly number[];
1009
+ }
1010
+ /** A query for {@link findPathSnap}. */
1011
+ interface PathSnapQuery {
1012
+ /** How far from the probe a target may be, in the paths' units times
1013
+ * `scale`. */
1014
+ radius: number;
1015
+ /** Per-axis scale from the paths' units to the units `radius` is in — a
1016
+ * view's, to measure the radius in screen pixels under any zoom. Default
1017
+ * `{ x: 1, y: 1 }`. */
1018
+ scale?: {
618
1019
  x: number;
619
1020
  y: number;
620
1021
  };
1022
+ /** Kinds to consider. Absent, all of them. */
1023
+ kinds?: Iterable<PathSnapKind>;
1024
+ /** Where the line being drawn starts. Tangent and perpendicular targets are
1025
+ * measured from it, and there are none without it. */
1026
+ origin?: Point;
1027
+ /** Paths by index that offer no targets — the ones a drag is moving. */
1028
+ skip?: (path: number) => boolean;
1029
+ }
1030
+ /** A target that stands whatever the probe: an anchor, a center, a crossing,
1031
+ * a midpoint, an extremum or a quadrant point. */
1032
+ interface PathSnapTarget {
1033
+ kind: StaticPathSnapKind;
1034
+ x: number;
1035
+ y: number;
1036
+ paths: readonly number[];
621
1037
  }
1038
+ /** A set of paths, prepared for repeated snapping. Static targets are
1039
+ * computed on first use and kept. */
1040
+ interface PathSnapIndex {
1041
+ readonly paths: readonly Path[];
1042
+ /** Each path's segments. */
1043
+ readonly segments: readonly (readonly PathSegment[])[];
1044
+ /** The targets that do not depend on the probe, of one kind. */
1045
+ targets(kind: StaticPathSnapKind): readonly PathSnapTarget[];
1046
+ }
1047
+ /** Prepare `paths` for {@link findPathSnap}. Build one per set of paths and
1048
+ * reuse it while they stand: a crossing search is quadratic in segments.
1049
+ * `extra` adds targets of the caller's own — the center of a box, a point
1050
+ * with no segment at it — each naming the path it belongs to. */
1051
+ declare function createPathSnapIndex(paths: readonly Path[], extra?: readonly PathSnapTarget[]): PathSnapIndex;
622
1052
  /**
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
- };
1053
+ * The snap target nearest `probe` within `query.radius`, or null when none
1054
+ * is in range. Every enabled kind competes on distance, except `nearest`,
1055
+ * which answers only when no other target is in range.
1056
+ */
1057
+ declare function findPathSnap(index: PathSnapIndex, probe: Point, query: PathSnapQuery): PathSnapHit | null;
637
1058
  /**
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.
1059
+ * Every snap target within `query.radius` of `probe`, unsorted. `nearest`
1060
+ * hits appear only when no other target is in range. Tangent and perpendicular targets
1061
+ * closer to the origin than the radius are dropped, so a line cannot snap
1062
+ * back onto its own start.
644
1063
  */
645
- declare function anchorsToPath(anchors: PenAnchor[][], closed: boolean[], like?: PolygonPath): PolygonPath;
1064
+ declare function findPathSnaps(index: PathSnapIndex, probe: Point, query: PathSnapQuery): PathSnapHit[];
1065
+
1066
+ /**
1067
+ * Trim: remove the piece of a stroke between the crossings on either side of
1068
+ * a point, as a drafting trim does.
1069
+ */
1070
+
1071
+ /** Options for {@link trimPathAt}. */
1072
+ interface TrimPathOptions {
1073
+ /** How far from the stroke `probe` may be. Default: any distance. */
1074
+ radius?: number;
1075
+ }
1076
+ /** What {@link trimPathAt} did. */
1077
+ interface TrimResult {
1078
+ /** The path with the piece gone; it has no commands when nothing is left. */
1079
+ path: PolygonPath;
1080
+ /** The piece removed, as an open path. */
1081
+ removed: PolygonPath;
1082
+ }
646
1083
  /**
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.
1084
+ * Remove the piece of `path`'s stroke that `probe` is nearest, bounded by the
1085
+ * nearest crossings on either side — with any of `cutters`, or with the path
1086
+ * itself. On an open subpath an end with no crossing before it bounds the
1087
+ * piece too, so a subpath touched only at its ends goes whole; a closed
1088
+ * subpath is opened, and one crossed at a single point is removed whole.
650
1089
  *
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[]): {
1090
+ * Returns null when the probe is further than `radius` from the stroke, or
1091
+ * when nothing crosses or touches the subpath it is on. Curves are split where they are
1092
+ * cut and keep their type; other subpaths are left as they were.
1093
+ */
1094
+ declare function trimPathAt(path: Path, cutters: readonly Path[], probe: Point, opts?: TrimPathOptions): TrimResult | null;
1095
+
1096
+ /** What stays put of a path while some of its anchors move. */
1097
+ interface PathAwayFromAnchors {
1098
+ /** The segments touching none of the moving anchors, as open runs; a
1099
+ * subpath none of them is on stays as it was. */
1100
+ path: PolygonPath;
1101
+ /** Every anchor that is not moving, a lone one with no segment left at it
1102
+ * included. */
1103
+ anchors: Point[];
1104
+ }
1105
+ /**
1106
+ * The part of `path` that holds still while the anchors at `moving` (flat
1107
+ * indices, as anchor editing numbers them) are dragged: every segment with a
1108
+ * moving anchor at either end is dropped, and so are the moving anchors.
1109
+ */
1110
+ declare function pathAwayFromAnchors(path: PolygonPath, moving: Iterable<number>): PathAwayFromAnchors;
1111
+
1112
+ /**
1113
+ * Growing an open end of a path along its tangent: by a distance, or until it
1114
+ * meets another stroke.
1115
+ */
1116
+
1117
+ /** One end of an open subpath. `sub` counts subpaths as the path's anchor set
1118
+ * (`pathToAnchors`) does, a bare `M` included. */
1119
+ interface OpenPathEnd {
674
1120
  sub: number;
675
- segIdx: number;
676
- t: number;
1121
+ end: 'first' | 'last';
1122
+ }
1123
+ /** Every end of every open subpath of `path` that has a direction to grow in. */
1124
+ declare function openPathEnds(path: Path): OpenPathEnd[];
1125
+ /** Where `end` sits and the unit direction it points out along, or null when
1126
+ * it is no open end or has no direction there. */
1127
+ declare function openEndRay(path: Path, end: OpenPathEnd): {
1128
+ at: Point;
1129
+ dir: Point;
677
1130
  } | null;
1131
+ /**
1132
+ * `path` with `end` carried `distance` further along its tangent, by
1133
+ * `lengthenPathEnd` in `'tangent'` mode: a straight end segment grows longer,
1134
+ * and a curved one gains a straight segment, which keeps the tangent
1135
+ * continuous. Null when the end is not open or has no direction, or
1136
+ * `distance` is not positive.
1137
+ */
1138
+ declare function lengthenOpenEnd(path: Path, end: OpenPathEnd, distance: number): PolygonPath | null;
1139
+ /** Options for {@link extendToMeet}. */
1140
+ interface ExtendToMeetOptions {
1141
+ /** The furthest the end may travel. Default: as far as any stroke reaches. */
1142
+ maxDistance?: number;
1143
+ }
1144
+ /**
1145
+ * Extend `end` of `path` along its tangent to the first stroke it meets —
1146
+ * one of `boundaries`, or `path`'s own other segments. Returns the extended
1147
+ * path, the point it now ends at and how far it went, or null when the
1148
+ * tangent meets nothing.
1149
+ */
1150
+ declare function extendToMeet(path: Path, boundaries: readonly Path[], end: OpenPathEnd, opts?: ExtendToMeetOptions): {
1151
+ path: PolygonPath;
1152
+ at: Point;
1153
+ distance: number;
1154
+ } | null;
1155
+
1156
+ /**
1157
+ * Grow or trim an open subpath at one of its ends. Lengthen drags this, and
1158
+ * Extend to next path reaches it through `lengthenOpenEnd`.
1159
+ *
1160
+ * A positive distance extends the end outward: straight along the end tangent,
1161
+ * or along a circular arc with the curvature the end has, which meets the path
1162
+ * with matching direction and curvature. A straight end segment is lengthened
1163
+ * in place; a curved one is continued with a new segment. A negative distance
1164
+ * trims the path back along itself by arc length, whichever way it would have
1165
+ * grown.
1166
+ *
1167
+ * The arc rather than extrapolating the end cubic past t = 1: a cubic's
1168
+ * leading term takes over beyond its range, so a continued curve swings off
1169
+ * and curls on itself within a segment's length, while the arc keeps the
1170
+ * curvature the end shows for as long as it is drawn.
1171
+ */
1172
+
1173
+ /** How `lengthenPathEnd` grows an end: straight on, or bending as the end bends. */
1174
+ type LengthenMode = 'tangent' | 'curvature';
1175
+ /** Where an end is, which way it heads out of the path, and how it bends there. */
1176
+ interface PathEndFrame {
1177
+ point: Point;
1178
+ /** Unit vector pointing out of the path. */
1179
+ tangent: Point;
1180
+ /** Signed curvature along `tangent`: positive turns toward `(-tangent.y, tangent.x)`. */
1181
+ curvature: number;
1182
+ }
1183
+ /** The end of an open subpath that the anchor at `flatIndex` is, or null when it is
1184
+ * an inner anchor, on a closed subpath, or alone in its subpath. */
1185
+ declare function openEndAt(set: AnchorSet, flatIndex: number): OpenPathEnd | null;
1186
+ /** Flat index of the anchor at `end`, or -1 when there is none. */
1187
+ declare function pathEndAnchorIndex(set: AnchorSet, end: OpenPathEnd): number;
1188
+ /** The frame at `end`, or null when it is not the end of an open subpath of two or
1189
+ * more anchors, or the path has no direction there. */
1190
+ declare function pathEndFrame(set: AnchorSet, end: OpenPathEnd): PathEndFrame | null;
1191
+ /**
1192
+ * Lengthen `end` by `distance` (see the module comment), in place. A curvature arc
1193
+ * stops at one full turn. Returns false when `end` is not the end of an open
1194
+ * subpath or nothing changed.
1195
+ */
1196
+ declare function lengthenPathEnd(set: AnchorSet, end: OpenPathEnd, distance: number, mode: LengthenMode): boolean;
1197
+ /**
1198
+ * The distance `lengthenPathEnd` takes for its new end to land nearest `point`: the
1199
+ * point projected onto the end tangent, or for a curvature lengthening, measured
1200
+ * around the circle of curvature. A measurement around the circle can name the
1201
+ * same spot a turn apart; it answers the one nearest `near`, so a drag passing
1202
+ * half a turn keeps going instead of jumping back.
1203
+ */
1204
+ declare function lengthToward(set: AnchorSet, end: OpenPathEnd, mode: LengthenMode, point: Point, near?: number): number;
678
1205
 
679
1206
  /**
680
1207
  * Controls for the one cubic that replaces `prev → removed → next` when
@@ -685,8 +1212,8 @@ declare function nearestSegmentT(anchors: PenAnchor[][], wx: number, wy: number,
685
1212
  * cubic, the original cubic comes back.
686
1213
  */
687
1214
  declare function fitCubicThroughDeletion(prev: PenAnchor, removed: PenAnchor, next: PenAnchor): {
688
- c1: Point$1;
689
- c2: Point$1;
1215
+ c1: Point;
1216
+ c2: Point;
690
1217
  };
691
1218
 
692
1219
  /**
@@ -698,7 +1225,7 @@ declare function fitCubicThroughDeletion(prev: PenAnchor, removed: PenAnchor, ne
698
1225
  * `C` cubic segments. For colinear / two-point inputs, returns a single
699
1226
  * degenerate cubic. For empty input, returns an empty polygon path.
700
1227
  */
701
- declare function schneiderFit(samples: ReadonlyArray<Point$1>, errorTolerance: number): PolygonPath;
1228
+ declare function schneiderFit(samples: ReadonlyArray<Point>, errorTolerance: number): PolygonPath;
702
1229
  /**
703
1230
  * The single cubic from the first sample to the last that best fits the
704
1231
  * samples between, with its control points held to the given unit tangents:
@@ -709,12 +1236,12 @@ declare function schneiderFit(samples: ReadonlyArray<Point$1>, errorTolerance: n
709
1236
  * omitted; `passes` is how many times those are refined and the lengths
710
1237
  * solved again.
711
1238
  */
712
- declare function fitCubicWithTangents(samples: ReadonlyArray<Point$1>, tStart: Point$1, tEnd: Point$1, opts?: {
1239
+ declare function fitCubicWithTangents(samples: ReadonlyArray<Point>, tStart: Point, tEnd: Point, opts?: {
713
1240
  params?: ReadonlyArray<number>;
714
1241
  passes?: number;
715
1242
  }): {
716
- cp1: Point$1;
717
- cp2: Point$1;
1243
+ cp1: Point;
1244
+ cp2: Point;
718
1245
  };
719
1246
 
720
1247
  /** Options for {@link simplifyPath}. */
@@ -734,195 +1261,139 @@ interface SimplifyPathOptions {
734
1261
  * becomes one straight segment. Fill rules carry over.
735
1262
  */
736
1263
  declare function simplifyPath(path: PolygonPath, tolerance: number, opts?: SimplifyPathOptions): PolygonPath;
737
-
738
- /**
739
- * Screen-pixel lengths in world units, per axis.
740
- *
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;
1264
+ /** One subpath of {@link simplifyPath}: its anchors refitted, corners and
1265
+ * open ends kept. */
1266
+ declare function simplifySubpath(sub: PenAnchor[], closed: boolean, tolerance: number, opts?: SimplifyPathOptions): PenAnchor[];
1267
+ /**
1268
+ * The anchors of `sub` from index `from` to `to`, refitted the way
1269
+ * {@link simplifyPath} refits a subpath: as few as hold the span within
1270
+ * `tolerance`, corners inside it kept. Indices run modulo the subpath's
1271
+ * length, so on a closed subpath `to` may pass its end and wrap; the span is
1272
+ * shorter than one full turn. The two end anchors stay where they are and
1273
+ * keep their handles facing out of the span. Answers the anchors from `from`
1274
+ * to `to`, both included, to splice in place of the originals.
1275
+ */
1276
+ declare function simplifySpan(sub: PenAnchor[], closed: boolean, from: number, to: number, tolerance: number, opts?: SimplifyPathOptions): PenAnchor[];
1277
+
1278
+ /** Options for {@link growRegion}. */
1279
+ interface GrowRegionOptions {
1280
+ /** How a convex corner turns. `'miter'` keeps it sharp, as a pseudo-distance
1281
+ * field draws it; `'round'` follows the true distance. Default `'miter'`. */
1282
+ join?: 'miter' | 'round';
1283
+ /** Past this ratio of miter length to distance a miter corner is beveled.
1284
+ * Default 4. */
1285
+ miterLimit?: number;
1286
+ /** How far a grown curve may stray from the true offset, in the path's
1287
+ * units. Default 0.1. */
1288
+ tolerance?: number;
755
1289
  }
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
1290
  /**
774
- * Is a world-space delta inside a screen-space square of half-extent `px`?
1291
+ * The region `path` fills under `'nonzero'`, grown by `distance` (> 0), as a
1292
+ * path that fills it under `'nonzero'`. Every subpath counts as closed. Each
1293
+ * contour is replaced by its offset, so where grown parts meet the contours
1294
+ * overlap rather than merge, and a hole grown shut winds back on itself and
1295
+ * fills. At an inside corner the two offset edges are cut back to where they
1296
+ * cross; where they do not, the gap is passed through the corner's original
1297
+ * point, which closes it with a loop inside the fill.
775
1298
  *
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;
1299
+ * What it costs: one segment per curve, more where `tolerance` needs the curve
1300
+ * split; a miter corner between two straight edges costs nothing, one beside
1301
+ * a curve gains an anchor or two, a round corner an arc, and an inside corner
1302
+ * whose edges do not cross two.
1303
+ */
1304
+ declare function growRegion(path: Path, distance: number, opts?: GrowRegionOptions): PolygonPath;
1305
+
1306
+ /**
1307
+ * Simplify only where `flatIndexes` say: each unbroken run of those anchors
1308
+ * along a subpath is refitted as one span by the fitter {@link simplifyPath}
1309
+ * uses (`simplifySpan`), so only anchors the shape does not need, within
1310
+ * `tolerance`, go. A run's first and last anchors stay, and every anchor
1311
+ * outside a run is left as it was. A closed subpath named whole is simplified
1312
+ * whole. Answers whether any anchor went; a run the fit cannot thin is left
1313
+ * untouched.
1314
+ */
1315
+ declare function simplifyAnchorsAt(set: AnchorSet, flatIndexes: Iterable<number>, tolerance: number, opts?: SimplifyPathOptions): boolean;
1316
+
1317
+ /**
1318
+ * Resample: a path's anchors spread evenly along it by arc length, and its
1319
+ * curves refitted through them.
1320
+ */
1321
+
1322
+ /** Options for {@link resamplePath}. */
1323
+ interface ResamplePathOptions {
1324
+ /** How many anchors the result holds across all its subpaths. Default: as
1325
+ * many as `path` has. Ignored when `spacing` is given. */
1326
+ count?: number;
1327
+ /** The distance along the path between neighboring anchors, in path units.
1328
+ * Each run between fixed anchors is cut into the whole number of equal
1329
+ * pieces nearest this. */
1330
+ spacing?: number;
1331
+ /** Keep every corner anchor (`isAnchorSmooth` false) where it is, with its
1332
+ * corner, and resample the runs between. Default `true`. Open ends are
1333
+ * kept either way. */
1334
+ keepCorners?: boolean;
1335
+ /** How far the result may stray from the original, in path units. A piece
1336
+ * that cannot follow the original this closely is halved, so the result can
1337
+ * hold more anchors than `count` asks for. Default 0.5. */
1338
+ tolerance?: number;
1339
+ }
784
1340
  /**
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.
1341
+ * `path` with its anchors spread evenly along each run between fixed anchors
1342
+ * ({@link ResamplePathOptions}), each new anchor heading the way the original
1343
+ * does there. Anchors that were smooth stay smooth, and the curves between
1344
+ * are fitted to the original. A closed subpath with no fixed anchor keeps
1345
+ * its first one as the place the even spacing starts from. Fill rules carry
1346
+ * over.
792
1347
  */
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;
1348
+ declare function resamplePath(path: PolygonPath, opts?: ResamplePathOptions): PolygonPath;
808
1349
 
1350
+ /** The parameters in (0, 1) where the segment from `a` to `b` turns in x or
1351
+ * y, ascending, or none for a straight segment. */
1352
+ declare function segmentExtremaTs(a: PenAnchor, b: PenAnchor): number[];
809
1353
  /**
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.
1354
+ * Split every curved segment of `set` at its extremes
1355
+ * ({@link segmentExtremaTs}), in place. `include(sub, segIdx)` limits it to
1356
+ * some segments, named as `segmentEnds` names them; absent, every one.
1357
+ * Returns the new anchors' flat indices in the edited set. Each new anchor is
1358
+ * smooth, and every anchor after one moves up an index.
825
1359
  */
1360
+ declare function addExtremaAnchors(set: AnchorSet, include?: (sub: number, segIdx: number) => boolean): number[];
826
1361
 
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
1362
  /**
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.
868
- *
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.
1363
+ * Anchor selections walked along the path: grown or shrunk by one anchor,
1364
+ * every Nth anchor, anchors by kind, and the complement. Each takes the
1365
+ * decoded set and a selection as flat indices, and returns a new selection
1366
+ * as sorted flat indices; none of them edits the set.
871
1367
  *
872
- * Returns the new anchor's flat index, or -1 when the segment doesn't
873
- * exist.
1368
+ * "Along the path" means within a subpath: an anchor's neighbors are the
1369
+ * anchors before and after it there, and a closed subpath's first and last
1370
+ * anchors are neighbors.
874
1371
  */
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;
1372
+
1373
+ /** `selected` with each selected anchor's neighbors along the path added. */
1374
+ declare function growAnchorSelection(set: AnchorSet, selected: Iterable<number>): number[];
905
1375
  /**
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.
1376
+ * `selected` less every anchor at the edge of a selected run: one with a
1377
+ * neighbor that is unselected, or none on one side, as an open subpath's ends
1378
+ * have. A closed subpath selected all the way round has no edge and stays.
915
1379
  */
916
- declare function deleteAnchorsAt(set: AnchorSet, flatIndexes: Iterable<number>): boolean;
1380
+ declare function shrinkAnchorSelection(set: AnchorSet, selected: Iterable<number>): number[];
917
1381
  /**
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.
1382
+ * Every `n`th anchor along each subpath, counting from its first selected
1383
+ * anchor. With nothing selected, every subpath counts from its first anchor;
1384
+ * otherwise only subpaths holding a selected anchor take part. A closed
1385
+ * subpath is walked once round, so the count does not wrap onto itself.
922
1386
  */
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[];
1387
+ declare function everyNthAnchor(set: AnchorSet, n: number, selected?: Iterable<number>): number[];
1388
+ /** Every anchor `keep` says yes to. */
1389
+ declare function anchorsWhere(set: AnchorSet, keep: (anchor: PenAnchor) => boolean): number[];
1390
+ /** Every corner anchor: one whose handles are not collinear through it, or
1391
+ * that lacks one (`isAnchorSmooth` false). */
1392
+ declare function cornerAnchors(set: AnchorSet): number[];
1393
+ /** Every smooth anchor (`isAnchorSmooth`). */
1394
+ declare function smoothAnchors(set: AnchorSet): number[];
1395
+ /** Every anchor `selected` leaves out. */
1396
+ declare function invertAnchorSelection(set: AnchorSet, selected: Iterable<number>): number[];
926
1397
 
927
1398
  /**
928
1399
  * Average and Join: anchor-set edits that bring anchors together. Both mutate
@@ -939,6 +1410,13 @@ interface SubpathEnd {
939
1410
  sub: number;
940
1411
  end: 'first' | 'last';
941
1412
  }
1413
+ /** How {@link joinSubpathEnds} spans the gap between two ends apart. */
1414
+ interface JoinOptions {
1415
+ /** Absent, a straight segment. Given, a curve leaving each end along the
1416
+ * direction its path was heading there, each handle `tension` times the
1417
+ * gap long; `0` is a straight segment. */
1418
+ tension?: number;
1419
+ }
942
1420
  /**
943
1421
  * Move each anchor in `flatIndexes` to their mean position, along `axis`.
944
1422
  * Each anchor carries its handles with it. Returns false, changing nothing,
@@ -953,19 +1431,71 @@ declare function subpathEndAt(set: AnchorSet, flatIndex: number): SubpathEnd | n
953
1431
  * close it; ends of two subpaths make one subpath, `a`'s run followed by
954
1432
  * `b`'s, in the slot of whichever came first. Ends that coincide merge into
955
1433
  * 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.
1434
+ * straight segment, or with `options.tension` by a curve meeting each end
1435
+ * tangentially. Returns false, changing nothing, when the ends are not two
1436
+ * distinct ends of open subpaths.
958
1437
  */
959
- declare function joinSubpathEnds(set: AnchorSet, a: SubpathEnd, b: SubpathEnd): boolean;
1438
+ declare function joinSubpathEnds(set: AnchorSet, a: SubpathEnd, b: SubpathEnd, options?: JoinOptions): boolean;
960
1439
  /** {@link joinSubpathEnds} for two anchors named by flat index, each the end
961
1440
  * of an open subpath. */
962
- declare function joinAnchorsAt(set: AnchorSet, flatA: number, flatB: number): boolean;
1441
+ declare function joinAnchorsAt(set: AnchorSet, flatA: number, flatB: number, options?: JoinOptions): boolean;
963
1442
  /**
964
1443
  * The two open-subpath ends nearest each other that `accept` allows, on two
965
1444
  * different subpaths. Null when there are no two such subpaths.
966
1445
  */
967
1446
  declare function closestOpenEnds(set: AnchorSet, accept?: (a: SubpathEnd, b: SubpathEnd) => boolean): [SubpathEnd, SubpathEnd] | null;
968
1447
 
1448
+ /**
1449
+ * Spiro curves as cubic paths, and back. A solved curve is written as cubics,
1450
+ * each spiral segment split into as many as it takes to stay within tolerance,
1451
+ * so most anchors of the path are not spiro points. `at` records which are:
1452
+ * `at[i]` is the flat anchor index of point `i`, counted across subpaths. The
1453
+ * points are then read back out of the path itself, so whatever moves the path
1454
+ * — a move, a resize, a rotation — moves them with it.
1455
+ */
1456
+
1457
+ /** One subpath of a spiro curve: its points, and whether it closes. */
1458
+ interface SpiroContour {
1459
+ points: SpiroPoint[];
1460
+ closed: boolean;
1461
+ }
1462
+ /** A spiro curve written as a cubic path, with the anchor each point became. */
1463
+ interface SpiroPath {
1464
+ path: PolygonPath;
1465
+ /** The flat anchor index of each point, in contour order. */
1466
+ at: number[];
1467
+ }
1468
+ /** Options for {@link spiroToPath}. */
1469
+ interface SpiroToPathOptions {
1470
+ /** The furthest a cubic may stray from its spiral, as a fraction of that
1471
+ * segment's arc length. Default `1e-4`. */
1472
+ tolerance?: number;
1473
+ /** The path being reshaped, whose fill rules the result keeps. */
1474
+ like?: PolygonPath;
1475
+ }
1476
+ /**
1477
+ * Solve each contour and write it as a cubic path. Straight segments carry no
1478
+ * handles.
1479
+ */
1480
+ declare function spiroToPath(contours: readonly SpiroContour[], options?: SpiroToPathOptions): SpiroPath;
1481
+ /**
1482
+ * The spiro points `path` holds, given the kind of each and the anchor each
1483
+ * became. Null when `kinds` and `at` do not describe `path`: the counts
1484
+ * differ, an index is out of order or out of range, or a subpath does not
1485
+ * start on a point.
1486
+ */
1487
+ declare function spiroContoursOf(path: PolygonPath, kinds: readonly SpiroKind[], at: readonly number[]): SpiroContour[] | null;
1488
+ /** The straight-sided path through each contour's points: what an editor
1489
+ * shows and moves in place of the curve. */
1490
+ declare function spiroControlPath(contours: readonly SpiroContour[]): PolygonPath;
1491
+ /**
1492
+ * Read an edited control path back as contours: every anchor is a point.
1493
+ * Kinds follow from `before`, the contours the edit started from: point for
1494
+ * point when the count is unchanged, else by position, with an anchor that
1495
+ * lands nowhere a point was taking `fallback`. Handles are ignored.
1496
+ */
1497
+ declare function spiroContoursFromControl(control: PolygonPath, before: readonly SpiroContour[], fallback?: SpiroKind): SpiroContour[];
1498
+
969
1499
  /**
970
1500
  * Path hit-testing: path-vs-point (filled region and stroke distance),
971
1501
  * path-vs-rect, and path-vs-polygon in both directions.
@@ -1020,15 +1550,15 @@ declare function pathContainsRect(path: Path, rect: Rect, opts?: PointInPathOpti
1020
1550
  /** Returns true if `rect` overlaps (intersects or contains) `path`. */
1021
1551
  declare function pathIntersectsRect(path: Path, rect: Rect, opts?: PointInPathOptions): boolean;
1022
1552
  /** Returns true if every vertex of `polygon` lies inside `path`. */
1023
- declare function pathContainsPolygon(path: Path, polygon: readonly Point$1[], opts?: PointInPathOptions): boolean;
1553
+ declare function pathContainsPolygon(path: Path, polygon: readonly Point[], opts?: PointInPathOptions): boolean;
1024
1554
  /** Returns true if `polygon` overlaps (intersects or is contained by) `path`. */
1025
- declare function pathIntersectsPolygon(path: Path, polygon: readonly Point$1[], opts?: PointInPathOptions): boolean;
1555
+ declare function pathIntersectsPolygon(path: Path, polygon: readonly Point[], opts?: PointInPathOptions): boolean;
1026
1556
  /**
1027
1557
  * Returns true if all of `path` — every subpath, open ones included, beziers
1028
1558
  * flattened — lies inside the closed `polygon`: the inverse of
1029
1559
  * {@link pathContainsPolygon}. A lasso enclosing a shape asks this.
1030
1560
  */
1031
- declare function polygonContainsPath(polygon: readonly Point$1[], path: Path, opts?: PointInPathOptions): boolean;
1561
+ declare function polygonContainsPath(polygon: readonly Point[], path: Path, opts?: PointInPathOptions): boolean;
1032
1562
  /**
1033
1563
  * Returns true if any of `path` meets the closed `polygon`: its filled region,
1034
1564
  * or the line of an open subpath, which encloses nothing. With `filled: false`
@@ -1036,7 +1566,16 @@ declare function polygonContainsPath(polygon: readonly Point$1[], path: Path, op
1036
1566
  * flattened, so a control point off the curve never counts. The companion of
1037
1567
  * {@link polygonContainsPath}; a lasso touching a shape asks this.
1038
1568
  */
1039
- declare function polygonIntersectsPath(polygon: readonly Point$1[], path: Path, opts?: PolygonIntersectsPathOptions): boolean;
1569
+ declare function polygonIntersectsPath(polygon: readonly Point[], path: Path, opts?: PolygonIntersectsPathOptions): boolean;
1570
+
1571
+ /**
1572
+ * The affine map carrying the points of `from` closest to those of `to`, by
1573
+ * least squares; both are interleaved `x, y` streams of the same length. When
1574
+ * the points lie on one line an affine map is not determined, and the
1575
+ * similarity (turn, even scale and move) is returned instead. Null for fewer
1576
+ * than two distinct points.
1577
+ */
1578
+ declare function fitAffine(from: ArrayLike<number>, to: ArrayLike<number>): Affine | null;
1040
1579
 
1041
1580
  /**
1042
1581
  * Ergonomic builders for tiny shape paths used by chrome / overlays / markers.
@@ -1394,6 +1933,20 @@ declare function rotatePathAround(path: Path, cx: number, cy: number, rotation:
1394
1933
  * rotation. Absent is the identity.
1395
1934
  */
1396
1935
  type PoseLinear = readonly [a: number, b: number, c: number, d: number];
1936
+ /**
1937
+ * Axis-aligned rectangle in world space. The optional `rotation` (radians,
1938
+ * around the AABB center) and `transform` (inside it, about the same center)
1939
+ * let chrome carry the frame a box is drawn in without a parallel type;
1940
+ * `poseFrameOf` composes the two. routing and core call it `Bounds`.
1941
+ */
1942
+ interface FramedBox {
1943
+ x: number;
1944
+ y: number;
1945
+ width: number;
1946
+ height: number;
1947
+ rotation?: number;
1948
+ transform?: PoseLinear;
1949
+ }
1397
1950
  /** `transform` when it changes anything, `null` for absent or the identity. */
1398
1951
  declare function poseLinearOf(pose: unknown): PoseLinear | null;
1399
1952
  /**
@@ -1412,7 +1965,17 @@ declare function poseFrameInverseOf(pose: unknown): Affine | null;
1412
1965
  /** `path`, given in the pose's unrotated box frame, as the node draws it. */
1413
1966
  declare function pathThroughPoseFrame(path: Path, pose: unknown): Path;
1414
1967
 
1415
- type Side = 'in' | 'out';
1968
+ /**
1969
+ * Flat indices of every anchor a round brush covers as it moves from `from` to
1970
+ * `to`: those within `radiusPx` of that segment, measured on screen. A dab is a
1971
+ * segment of zero length. `scale` is the view's, so the brush stays round on
1972
+ * screen under non-uniform zoom; omitted, one unit is one pixel.
1973
+ */
1974
+ declare function anchorsUnderBrush(set: AnchorSet, from: Point, to: Point, opts: {
1975
+ radiusPx: number;
1976
+ scale?: Scale2;
1977
+ }): number[];
1978
+
1416
1979
  /**
1417
1980
  * How a path maps onto itself under one transform `m`: `partners[i]` is the
1418
1981
  * flat index of the anchor that anchor `i` lands on, and `flips[i]` whether
@@ -1454,7 +2017,7 @@ declare function translateAnchorsSymmetric(set: AnchorSet, flats: readonly numbe
1454
2017
  * follow it. Every handle is written once, from its target, so no anchor
1455
2018
  * re-aims a handle another image already placed.
1456
2019
  */
1457
- declare function moveHandleSymmetric(set: AnchorSet, flat: number, side: Side, toX: number, toY: number, breakSmoothness: boolean, syms: readonly AnchorSymmetry[]): boolean;
2020
+ declare function moveHandleSymmetric(set: AnchorSet, flat: number, side: 'in' | 'out', toX: number, toY: number, breakSmoothness: boolean, syms: readonly AnchorSymmetry[]): boolean;
1458
2021
 
1459
2022
  /** Where on a segment a bend is held, as `segmentAt` reports it. */
1460
2023
  interface BendGrip {
@@ -1475,10 +2038,38 @@ interface BendGrip {
1475
2038
  */
1476
2039
  declare function bendSegment(set: AnchorSet, grip: BendGrip, dx: number, dy: number): boolean;
1477
2040
 
1478
- type Point = {
1479
- x: number;
1480
- y: number;
1481
- };
2041
+ /**
2042
+ * `smudgePath` — one dab of a smudge brush: the outline under a round brush
2043
+ * moved along the brush's motion, most at its center and not at all at its rim.
2044
+ */
2045
+
2046
+ /** Options for {@link smudgePath}. */
2047
+ interface SmudgePathOptions {
2048
+ /** The brush's center before this dab's motion. */
2049
+ center: Point;
2050
+ /** How far the brush moved. */
2051
+ delta: Point;
2052
+ /** The brush's radius, in the path's units. */
2053
+ radius: number;
2054
+ /** How much of `delta` a point under the brush's center moves: `1` all of it. Default 1. */
2055
+ strength?: number;
2056
+ /**
2057
+ * The longest a segment under the brush may be before an anchor is added at its
2058
+ * middle, in the path's units, so the brush has points to move where it needs
2059
+ * them. Default a third of `radius`; `Infinity` adds none.
2060
+ */
2061
+ detail?: number;
2062
+ }
2063
+ /**
2064
+ * `path` with the outline under the brush pushed along `delta`. A point at distance
2065
+ * `d` from `center` moves by `delta × strength × (1 − (d/radius)²)²`, and an anchor's
2066
+ * handles move with it, so a smooth anchor stays smooth. First, every segment that
2067
+ * passes under the brush and is longer than `detail` is split at its middle until it
2068
+ * is not, so a long straight edge bends where the brush meets it. Returns `path`
2069
+ * itself when nothing is under the brush.
2070
+ */
2071
+ declare function smudgePath(path: PolygonPath, opts: SmudgePathOptions): PolygonPath;
2072
+
1482
2073
  /**
1483
2074
  * Collapse the handles of the anchors at `flatIndexes` onto their anchors,
1484
2075
  * leaving sharp corners. A segment whose ends both lose their handles turns
@@ -1507,17 +2098,165 @@ declare function makeHandlesSymmetric(set: AnchorSet, flatIndexes: Iterable<numb
1507
2098
  * keep and follows `to` freely.
1508
2099
  */
1509
2100
  declare function handleAlongItsAngle(anchor: Point, handle: Point, to: Point): Point;
2101
+ /**
2102
+ * Where a handle lands when dragged toward `to` but held to its current
2103
+ * length from `anchor`: on the circle of that length, aimed at `to`. A `to`
2104
+ * on the anchor itself gives no direction, and leaves the handle where it is.
2105
+ */
2106
+ declare function handleAtItsLength(anchor: Point, handle: Point, to: Point): Point;
2107
+
2108
+ /**
2109
+ * Soft selection over an anchor set: how strongly an edit to some anchors
2110
+ * carries to the anchors near them, by distance measured along the path.
2111
+ *
2112
+ * Distance is arc length along the drawn curve, not a straight line, so two
2113
+ * anchors that sit close across a gap in a shape are as far apart as the
2114
+ * path between them. A `scale` measures it in screen pixels under a view's
2115
+ * zoom, per axis.
2116
+ */
2117
+
2118
+ /** How influence fades from 1 at a selected anchor to 0 at the radius:
2119
+ * `smooth` eases out and in, `linear` falls evenly, `sharp` drops fast and
2120
+ * tails off. */
2121
+ type SoftFalloff = 'smooth' | 'linear' | 'sharp';
2122
+ /**
2123
+ * The weight `falloff` gives a point `distance` from the selection, for a
2124
+ * radius of `radius`: 1 at distance 0, 0 at the radius and beyond.
2125
+ */
2126
+ declare function softFalloff(falloff: SoftFalloff, distance: number, radius: number): number;
2127
+ /** Arc length along one segment, sampled at evenly spaced curve parameters. */
2128
+ interface SegmentMeasure {
2129
+ /** Arc length from the subpath's start to each sample; sample `i` is at
2130
+ * parameter `i / (lengths.length - 1)`. */
2131
+ lengths: Float64Array;
2132
+ }
2133
+ /** Arc lengths along one subpath, as {@link measureAnchorPath} takes them. */
2134
+ interface AnchorSubpathMeasure {
2135
+ closed: boolean;
2136
+ /** Flat index of the subpath's first anchor. */
2137
+ first: number;
2138
+ /** Arc length from the subpath's start to each anchor. */
2139
+ at: Float64Array;
2140
+ /** Total length, the closing segment included on a closed subpath. */
2141
+ length: number;
2142
+ /** Segment `i` runs from anchor `i` to anchor `i + 1`, wrapping on a closed subpath. */
2143
+ segments: SegmentMeasure[];
2144
+ }
2145
+ /** Arc lengths along every subpath of an anchor set, as
2146
+ * {@link measureAnchorPath} takes them. Read it with
2147
+ * {@link softSelectionWeights} and {@link softSelectionBand}. */
2148
+ interface AnchorPathMeasure {
2149
+ readonly subpaths: readonly AnchorSubpathMeasure[];
2150
+ }
2151
+ /** Options for {@link measureAnchorPath}. */
2152
+ interface MeasureAnchorPathOptions {
2153
+ /** Per-axis factor applied before measuring — a view's scale, to measure in
2154
+ * screen pixels. Default 1 on both axes. */
2155
+ scale?: {
2156
+ x: number;
2157
+ y: number;
2158
+ };
2159
+ /** Samples taken along each curved segment. Default 24. */
2160
+ samples?: number;
2161
+ }
2162
+ /** Measure the arc length along every subpath of `set`. */
2163
+ declare function measureAnchorPath(set: AnchorSet, opts?: MeasureAnchorPathOptions): AnchorPathMeasure;
2164
+ /**
2165
+ * How much of an edit to the `selected` anchors each anchor receives: 1 for
2166
+ * a selected anchor, the falloff of its distance along the path for one
2167
+ * within `radius` of the nearest selected anchor on its subpath. Anchors
2168
+ * that receive nothing are absent, as are anchors on a subpath with no
2169
+ * selected anchor.
2170
+ */
2171
+ declare function softSelectionWeights(measure: AnchorPathMeasure, selected: Iterable<number>, radius: number, falloff: SoftFalloff): Map<number, number>;
2172
+ /**
2173
+ * The stretches of path within `radius` of the `selected` anchors, as world
2174
+ * polylines drawn on `set`. `measure` is of the set the distances are taken
2175
+ * on — the path as it was when the edit began — and `set` the geometry to
2176
+ * draw on, which must have the same anchors. A stretch crossing the seam of a
2177
+ * closed subpath comes back as one run.
2178
+ */
2179
+ declare function softSelectionBand(measure: AnchorPathMeasure, set: AnchorSet, selected: Iterable<number>, radius: number): Point[][];
2180
+
2181
+ /** A curved segment's balance line: from its first handle's tip to its
2182
+ * second's, with a grip at the middle. */
2183
+ interface HandleBalance {
2184
+ sub: number;
2185
+ segIdx: number;
2186
+ /** Flat index of the anchor the segment starts at, which names the segment
2187
+ * the way an anchor's flat index names the anchor. */
2188
+ flat: number;
2189
+ /** Tip of the segment's first handle, the start anchor's out-handle. */
2190
+ from: Point;
2191
+ /** Tip of the segment's second handle, the end anchor's in-handle. */
2192
+ to: Point;
2193
+ /** Midway between the two tips. */
2194
+ grip: Point;
2195
+ }
2196
+ /**
2197
+ * The balance line of every curved segment in `set` that has both handles
2198
+ * pulled off their anchors. Dragging a line's grip scales both handles
2199
+ * together ({@link scaleSegmentHandles}), which fills the curve out toward
2200
+ * its corner or flattens it toward its chord without turning either end.
2201
+ */
2202
+ declare function handleBalances(set: AnchorSet): HandleBalance[];
2203
+ /**
2204
+ * Scale both handles of segment `(sub, segIdx)` by `factor`, each along its
2205
+ * own direction, so the segment keeps its end tangents. A smooth anchor at
2206
+ * either end stays smooth: its other handle points the same way as before.
2207
+ * `factor` below zero counts as zero, which retracts both handles.
2208
+ *
2209
+ * Under `syms`, as `anchorSymmetries` gives them, every image of either handle
2210
+ * moves to the image of where that handle goes, the way `moveHandleSymmetric`
2211
+ * moves a dragged handle's.
2212
+ *
2213
+ * Returns false when the segment has no balance line or nothing moved.
2214
+ */
2215
+ declare function scaleSegmentHandles(set: AnchorSet, sub: number, segIdx: number, factor: number, syms?: readonly AnchorSymmetry[]): boolean;
2216
+ /**
2217
+ * The factor {@link scaleSegmentHandles} takes to bring segment
2218
+ * `(sub, segIdx)`'s grip as near `to` as scaling can: `to` projected onto the
2219
+ * line the grip slides along as both handles grow. 1 when the segment has no
2220
+ * balance line.
2221
+ */
2222
+ declare function balanceFactorToward(set: AnchorSet, sub: number, segIdx: number, to: Point): number;
2223
+ /**
2224
+ * Give both handles of segment `(sub, segIdx)` the same proportion: each
2225
+ * reaches the same fraction of the way from its anchor to the corner where
2226
+ * the two handle lines cross, that fraction being the mean of the two they
2227
+ * had. Where the lines don't cross ahead of both handles, both take the mean
2228
+ * length instead. Directions are kept either way.
2229
+ *
2230
+ * Returns false when the segment has no balance line or the handles already
2231
+ * match.
2232
+ */
2233
+ declare function equalizeSegmentHandles(set: AnchorSet, sub: number, segIdx: number): boolean;
2234
+
2235
+ /**
2236
+ * Make each smooth anchor at `flatIndexes` curvature-continuous: the curve
2237
+ * bends as tightly just after the anchor as just before it, so it shows no
2238
+ * kink in its curvature there. Only handle lengths change — each handle keeps
2239
+ * its direction, so the anchor stays smooth and the tangent stays put — and
2240
+ * the product of the two lengths is kept, so the anchor's pull on the curve
2241
+ * stays about as strong.
2242
+ *
2243
+ * Absent `flatIndexes`, every anchor in the set. Moving one anchor's handles
2244
+ * changes the curvature at its neighbors, so the fixes are repeated until
2245
+ * they settle.
2246
+ *
2247
+ * Skipped, because lengths alone cannot do it: a corner, an anchor missing a
2248
+ * handle, an end of an open subpath, and an anchor the curve bends opposite
2249
+ * ways either side of, or straight through on one side.
2250
+ *
2251
+ * Returns false when nothing changed.
2252
+ */
2253
+ declare function harmonizeAnchors(set: AnchorSet, flatIndexes?: Iterable<number>): boolean;
1510
2254
 
1511
2255
  /**
1512
2256
  * Where each point of an edited path came from, so an array kept per point (a skin's
1513
2257
  * weights) can follow an edit that inserts, deletes, or reorders points.
1514
2258
  */
1515
2259
 
1516
- /** The anchor model `pathToAnchors` produces; `AnchorSet` in `anchorEdits`. */
1517
- interface Anchors {
1518
- anchors: PenAnchor[][];
1519
- closed: boolean[];
1520
- }
1521
2260
  /**
1522
2261
  * Where a point of an edited path came from: point `a` of the path before the edit, or for a
1523
2262
  * point the edit made, a blend `t` of the way from point `a` to point `b`.
@@ -1526,6 +2265,8 @@ interface PointOrigin {
1526
2265
  a: number;
1527
2266
  b: number;
1528
2267
  t: number;
2268
+ /** On an anchor's own point: its subpath now runs the other way through it. */
2269
+ reversed?: true;
1529
2270
  }
1530
2271
  /**
1531
2272
  * `editAnchorSet`, answering also where each point of the new path came from.
@@ -1536,7 +2277,7 @@ interface PointOrigin {
1536
2277
  * of it in its subpath, by its distance to each, or a copy of the one it has; its origin is
1537
2278
  * `null` when its subpath has none.
1538
2279
  */
1539
- declare function editAnchorSetTracked(path: PolygonPath, edit: (set: Anchors) => boolean | void): {
2280
+ declare function editAnchorSetTracked(path: PolygonPath, edit: (set: AnchorSet) => boolean | void): {
1540
2281
  path: PolygonPath;
1541
2282
  origins: (PointOrigin | null)[];
1542
2283
  } | null;
@@ -1547,6 +2288,449 @@ declare function editAnchorSetTracked(path: PolygonPath, edit: (set: Anchors) =>
1547
2288
  */
1548
2289
  declare function remapPointValues(values: ArrayLike<number>, origins: readonly (PointOrigin | null)[]): number[];
1549
2290
 
2291
+ /**
2292
+ * Arrays kept per anchor of a path — vertex colors, stroke widths — carried through an edit
2293
+ * that `editAnchorSetTracked` reported.
2294
+ */
2295
+
2296
+ /**
2297
+ * Where each anchor of `after` came from, in anchors of `before` as `countPathAnchors` counts
2298
+ * them, given the point `origins` `editAnchorSetTracked` answered for the edit: anchor `a`, or
2299
+ * for an anchor the edit made, a blend `t` of the way from `a` to `b`. `reversed` marks an
2300
+ * anchor whose subpath now runs the other way through it. Null for an anchor with no origin.
2301
+ */
2302
+ declare function anchorOriginsOf(before: PolygonPath, after: PolygonPath, origins: readonly (PointOrigin | null)[]): (PointOrigin | null)[];
2303
+ /**
2304
+ * An array kept per anchor of a path, `stride` numbers each — four color channels, say —
2305
+ * carried through an edit from `before` to `after`, with `origins` as
2306
+ * `editAnchorSetTracked` answered. An anchor the edit kept keeps its numbers; one it
2307
+ * made blends those of the anchors it came between. An anchor with no origin reads 0. Anchors
2308
+ * are counted as `countPathAnchors` counts them.
2309
+ */
2310
+ declare function remapAnchorValues(values: ArrayLike<number>, stride: number, before: PolygonPath, after: PolygonPath, origins: readonly (PointOrigin | null)[]): number[];
2311
+
2312
+ /**
2313
+ * Geometric constraints on a path's anchors. Each names anchors by flat index,
2314
+ * the walk-order numbering `enumerateAnchors` and `anchorAt` use, and is plain
2315
+ * JSON, so a list of them can be kept in scene data and saved with it.
2316
+ */
2317
+ /** Two anchors by flat index: the straight line from the first to the second. */
2318
+ type AnchorPair = readonly [number, number];
2319
+ /**
2320
+ * One constraint. `fixed` holds an anchor where it was before an edit, so it
2321
+ * moves with its node but not with any edit of the path. `horizontal` and
2322
+ * `vertical` read the axes of the frame the solve is given; `length` is in
2323
+ * the path's own units. `tangent` keeps an anchor's two handles on one line
2324
+ * through it, pointing apart (G1 continuity), their lengths free; it needs
2325
+ * both handles. `onPath` holds an anchor on the path's segment from
2326
+ * `segment[0]` to `segment[1]`, anywhere along it.
2327
+ */
2328
+ type PathConstraint = {
2329
+ readonly kind: 'fixed' | 'tangent';
2330
+ readonly anchor: number;
2331
+ } | {
2332
+ readonly kind: 'horizontal' | 'vertical';
2333
+ readonly segment: AnchorPair;
2334
+ } | {
2335
+ readonly kind: 'parallel' | 'perpendicular' | 'equalLength';
2336
+ readonly segments: readonly [AnchorPair, AnchorPair];
2337
+ } | {
2338
+ readonly kind: 'length';
2339
+ readonly segment: AnchorPair;
2340
+ readonly length: number;
2341
+ } | {
2342
+ readonly kind: 'coincident';
2343
+ readonly anchors: AnchorPair;
2344
+ } | {
2345
+ readonly kind: 'onPath';
2346
+ readonly anchor: number;
2347
+ readonly segment: AnchorPair;
2348
+ };
2349
+ /** Every kind of {@link PathConstraint}. */
2350
+ type PathConstraintKind = PathConstraint['kind'];
2351
+ /** The anchors `c` reads, in the order it names them; an anchor named twice is listed twice. */
2352
+ declare function constraintAnchors(c: PathConstraint): number[];
2353
+ /**
2354
+ * `c` with every anchor index passed through `to`, or null when `to` answers
2355
+ * `undefined` for any of them — the anchor is gone, and so is the constraint.
2356
+ */
2357
+ declare function mapConstraintAnchors(c: PathConstraint, to: (anchor: number) => number | undefined): PathConstraint | null;
2358
+ /** Whether every anchor `c` names is an index below `count`. */
2359
+ declare function constraintFits(c: PathConstraint, count: number): boolean;
2360
+
2361
+ /**
2362
+ * The points a constraint solve reads, and the coordinate vector it works in:
2363
+ * anchors, then each anchor's handles as offsets from it (see `ResidualSpace`).
2364
+ */
2365
+
2366
+ /** An anchor the solver reads and writes, with its handles where it has them. */
2367
+ interface ConstraintPoint {
2368
+ x: number;
2369
+ y: number;
2370
+ inHandle?: {
2371
+ x: number;
2372
+ y: number;
2373
+ };
2374
+ outHandle?: {
2375
+ x: number;
2376
+ y: number;
2377
+ };
2378
+ }
2379
+ /** One handle of an anchor. */
2380
+ interface HandleRef {
2381
+ anchor: number;
2382
+ side: 'in' | 'out';
2383
+ }
2384
+ /**
2385
+ * Whether `c` can be solved over `points`: every anchor it names exists, and
2386
+ * a `tangent` anchor has both handles.
2387
+ */
2388
+ declare function constraintApplies(c: PathConstraint, points: readonly ConstraintPoint[]): boolean;
2389
+
2390
+ /**
2391
+ * A damped Gauss-Newton solve for anchor constraints: from the state an edit
2392
+ * left, the smallest weighted move of the anchors and handles that makes
2393
+ * every residual zero. Each step is the minimum-norm solution of the
2394
+ * linearized system, `Δ = -M Jᵀ (J M Jᵀ + λI)⁻¹ r`, where `M` weighs how
2395
+ * freely each coordinate may move; λ grows when a step makes things worse and
2396
+ * shrinks when it helps, which is the Levenberg-Marquardt schedule run on the
2397
+ * constraint side.
2398
+ *
2399
+ * A handle is a coordinate of its own only where a `tangent` reads it; any
2400
+ * other rides with its anchor, as an offset nothing changes.
2401
+ */
2402
+
2403
+ /** Options for {@link solveConstraints}. */
2404
+ interface SolveConstraintsOptions {
2405
+ /** Anchors the edit put where they are — the dragged ones. They move only when no other anchor can satisfy the constraints. */
2406
+ held?: Iterable<number>;
2407
+ /** Handles the edit put where they are, held the way `held` holds anchors. */
2408
+ heldHandles?: Iterable<HandleRef>;
2409
+ /** Where each anchor was before the edit, which is where a `fixed` constraint keeps it. Default: where it is now. */
2410
+ reference?: readonly (ConstraintPoint | undefined)[];
2411
+ /** Radians the frame `horizontal` and `vertical` read is turned from the world's axes. Default 0. */
2412
+ axisAngle?: number;
2413
+ /** A frame per constraint, by index, over `axisAngle` — for constraints gathered from paths drawn in different frames. */
2414
+ axisAngles?: readonly (number | undefined)[];
2415
+ /** Indices of constraints to leave out of the solve — ones already known not to hold. */
2416
+ skip?: Iterable<number>;
2417
+ /** Default 100. */
2418
+ maxIterations?: number;
2419
+ /** The largest residual the solve stops at. Default 1e-7. */
2420
+ tolerance?: number;
2421
+ }
2422
+ /** What {@link solveConstraints} answers. */
2423
+ interface SolveConstraintsResult {
2424
+ /** Every anchor, moved, with its handles. */
2425
+ points: ConstraintPoint[];
2426
+ /** Whether every constraint the solve took holds within its tolerance. */
2427
+ converged: boolean;
2428
+ iterations: number;
2429
+ /** Indices of the constraints that do not hold in `points`, skipped ones included. */
2430
+ unsatisfied: number[];
2431
+ }
2432
+ /**
2433
+ * Move `points` the least that makes `constraints` hold. Anchors named by a
2434
+ * `fixed` constraint go back to `reference` and stay there; `held` anchors
2435
+ * and `heldHandles` stay where they are when the rest can satisfy the
2436
+ * constraints, and give way as little as they must when not. When the
2437
+ * constraints cannot all hold, `converged` is false and `unsatisfied` names
2438
+ * the ones that do not.
2439
+ */
2440
+ declare function solveConstraints(points: readonly ConstraintPoint[], constraints: readonly PathConstraint[], opts?: SolveConstraintsOptions): SolveConstraintsResult;
2441
+
2442
+ /**
2443
+ * Whether constraints hold for a set of points, and whether a solve made them
2444
+ * hold only by collapsing what they measure.
2445
+ */
2446
+
2447
+ /** The residual, in the path's units, under which a constraint counts as holding. */
2448
+ declare const CONSTRAINT_TOLERANCE = 0.001;
2449
+ /** Options for {@link unsatisfiedConstraints}. */
2450
+ interface UnsatisfiedConstraintsOptions {
2451
+ axisAngle?: number;
2452
+ /** A frame per constraint, by index, over `axisAngle`. */
2453
+ axisAngles?: readonly (number | undefined)[];
2454
+ /** Where a `fixed` anchor belongs. Absent, a `fixed` constraint always holds. */
2455
+ reference?: readonly (ConstraintPoint | undefined)[];
2456
+ /** Default {@link CONSTRAINT_TOLERANCE}. */
2457
+ tolerance?: number;
2458
+ }
2459
+ /**
2460
+ * Indices of the constraints that do not hold for `points`: a residual past
2461
+ * the tolerance, an anchor index the points do not have, or a tangent on an
2462
+ * anchor missing a handle.
2463
+ */
2464
+ declare function unsatisfiedConstraints(points: readonly ConstraintPoint[], constraints: readonly PathConstraint[], opts?: UnsatisfiedConstraintsOptions): number[];
2465
+
2466
+ /**
2467
+ * Constraints on a `PolygonPath`: solving them over its anchors, and carrying
2468
+ * them through an edit that renumbers the anchors.
2469
+ */
2470
+
2471
+ /** Every anchor of `path`, by flat index, with the handles it has. */
2472
+ declare function pathAnchorPoints(path: PolygonPath): ConstraintPoint[];
2473
+ /** {@link solveConstraints} over `path`'s anchors, and `path` with them moved. */
2474
+ interface SolvePathConstraintsResult extends SolveConstraintsResult {
2475
+ /** `path` with each anchor moved where the solve put it, its handles moved with it; `path` itself when none moved. */
2476
+ path: PolygonPath;
2477
+ }
2478
+ /**
2479
+ * Solve `constraints` over the anchors of `path` and write the result back,
2480
+ * carrying each moved anchor's handles with it so its curves keep their
2481
+ * shape, except where a `tangent` turned them.
2482
+ */
2483
+ declare function solvePathConstraints(path: PolygonPath, constraints: readonly PathConstraint[], opts?: SolveConstraintsOptions): SolvePathConstraintsResult;
2484
+ /**
2485
+ * `path` with its anchors and handles where `to` puts them, given `from`,
2486
+ * where they are now; `path` itself when nothing moved.
2487
+ */
2488
+ declare function withAnchorPoints(path: PolygonPath, from: readonly ConstraintPoint[], to: readonly ConstraintPoint[]): PolygonPath;
2489
+ /**
2490
+ * For each anchor of `after`, the anchor of `before` it is: the one whose
2491
+ * point `origins` says it was copied from. An anchor the edit made has none.
2492
+ * `origins` is what `editAnchorSetTracked` answered for the edit.
2493
+ */
2494
+ declare function anchorsBefore(before: PolygonPath, after: PolygonPath, origins: readonly (PointOrigin | null)[]): (number | undefined)[];
2495
+ /**
2496
+ * `constraints` renumbered for the anchors of a path after an edit, given
2497
+ * `wasAnchor` — for each new anchor, the old one it is, as
2498
+ * {@link anchorsBefore} answers. A constraint naming an anchor the edit
2499
+ * removed is dropped; `from` holds each kept one's index in `constraints`.
2500
+ */
2501
+ declare function remapConstraints(constraints: readonly PathConstraint[], wasAnchor: readonly (number | undefined)[]): {
2502
+ constraints: PathConstraint[];
2503
+ from: number[];
2504
+ };
2505
+ /**
2506
+ * The segment of `path` joining anchors `a` and `b`, as the pair in the order
2507
+ * the path runs it, or null when no segment joins them.
2508
+ */
2509
+ declare function segmentBetween(path: PolygonPath, a: number, b: number): AnchorPair | null;
2510
+
2511
+ /**
2512
+ * Finishing an edit of constrained paths so their constraints hold: one path
2513
+ * on its own, or several solved together when links — constraints naming
2514
+ * anchors of more than one — tie them.
2515
+ */
2516
+
2517
+ /** Options for {@link constrainPathEdit}. */
2518
+ interface ConstrainPathEditOptions {
2519
+ /**
2520
+ * Where each point of the edited path came from, as `editAnchorSetTracked`
2521
+ * answers. Absent, the edit is taken to keep every anchor's number, and one
2522
+ * that changes the anchor count drops every constraint.
2523
+ */
2524
+ origins?: readonly (PointOrigin | null)[];
2525
+ /** See {@link SolveConstraintsOptions.axisAngle}. */
2526
+ axisAngle?: number;
2527
+ }
2528
+ /** What {@link constrainPathEdit} answers. */
2529
+ interface ConstrainedPathEdit {
2530
+ /** The edited path with the constraints holding again. */
2531
+ path: PolygonPath;
2532
+ /** The constraints renumbered for `path`'s anchors. */
2533
+ constraints: PathConstraint[];
2534
+ /** Whether every constraint that held before the edit holds after it. */
2535
+ converged: boolean;
2536
+ /** Indices into `constraints` of the ones that do not hold, including any that already did not before the edit. */
2537
+ unsatisfied: number[];
2538
+ }
2539
+ /** One path of a {@link constrainPathsEdit}: its edit, and its own constraints. */
2540
+ interface PathsEditItem extends ConstrainPathEditOptions {
2541
+ before: PolygonPath;
2542
+ /** `before` as the edit left it; `before` itself for a path the edit did not touch. */
2543
+ after: PolygonPath;
2544
+ constraints: readonly PathConstraint[];
2545
+ }
2546
+ /**
2547
+ * A constraint across paths. Its anchors are numbered over the anchors of
2548
+ * `paths` — indices into the items — one after another in that order: with
2549
+ * `paths: [2, 0]` and a 5-anchor item 2, anchor 6 is item 0's anchor 1. Its
2550
+ * `horizontal` and `vertical` read the world's axes.
2551
+ */
2552
+ interface PathLink {
2553
+ constraint: PathConstraint;
2554
+ paths: readonly number[];
2555
+ }
2556
+ /** What {@link constrainPathsEdit} answers. */
2557
+ interface ConstrainedPathsEdit {
2558
+ /** Each item, in order: its path with the constraints holding, and its own constraints renumbered for it. */
2559
+ items: {
2560
+ path: PolygonPath;
2561
+ constraints: PathConstraint[];
2562
+ unsatisfied: number[];
2563
+ }[];
2564
+ /** Each link renumbered over its paths' anchors after the edit; null when the edit removed an anchor it names. */
2565
+ links: {
2566
+ constraint: PathConstraint | null;
2567
+ satisfied: boolean;
2568
+ }[];
2569
+ /** Whether every constraint that held before the edit holds after it. */
2570
+ converged: boolean;
2571
+ }
2572
+ /**
2573
+ * An edit of constrained paths, finished so their constraints and the links
2574
+ * between them hold, as one solve over every anchor: the anchors and handles
2575
+ * the edit moved are held, and so are the anchors of a path it left alone
2576
+ * (`after === before`), except one held on a segment; `fixed` anchors go
2577
+ * back to where they were, and the rest move the least they must. A constraint
2578
+ * that did not hold before the edit is left out of the solve, and reported.
2579
+ * Each item's own `horizontal` and `vertical` read its own `axisAngle`.
2580
+ */
2581
+ declare function constrainPathsEdit(items: readonly PathsEditItem[], links?: readonly PathLink[]): ConstrainedPathsEdit;
2582
+ /**
2583
+ * An edit of a constrained path, `before` → `after`, finished so its
2584
+ * constraints hold: the anchors and handles the edit moved are held, `fixed`
2585
+ * anchors go back to where they were, and the rest move the least they must.
2586
+ * A constraint that did not hold before the edit conflicts with the others
2587
+ * and is left out of the solve rather than allowed to pull them out of true;
2588
+ * `unsatisfied` reports it.
2589
+ */
2590
+ declare function constrainPathEdit(before: PolygonPath, after: PolygonPath, constraints: readonly PathConstraint[], opts?: ConstrainPathEditOptions): ConstrainedPathEdit;
2591
+
2592
+ /**
2593
+ * Which constraints conflict: not merely the ones a failed solve leaves
2594
+ * unsatisfied, but a smallest set that cannot all hold together, found by a
2595
+ * deletion filter — drop each member in turn, and keep it out when what is
2596
+ * left still fails. Every member of the answer is needed for the conflict.
2597
+ */
2598
+
2599
+ /** Options for {@link conflictingConstraints}. */
2600
+ interface ConflictingConstraintsOptions {
2601
+ /** Radians the frame `horizontal` and `vertical` read is turned from the world's axes. Default 0. */
2602
+ axisAngle?: number;
2603
+ /** A frame per constraint, by index, over `axisAngle`. */
2604
+ axisAngles?: readonly (number | undefined)[];
2605
+ /** Where each anchor belongs for a `fixed` constraint. Default: where it is now. */
2606
+ reference?: readonly (ConstraintPoint | undefined)[];
2607
+ }
2608
+ /**
2609
+ * The constraints of `constraints` that conflict over `points`: for every
2610
+ * group of them sharing anchors that cannot all hold, a smallest subset that
2611
+ * still cannot — each member needed, the later ones in the list kept in
2612
+ * preference to the earlier — and every constraint that cannot apply at all.
2613
+ * Sorted; empty when every constraint can hold at once.
2614
+ */
2615
+ declare function conflictingConstraints(points: readonly ConstraintPoint[], constraints: readonly PathConstraint[], opts?: ConflictingConstraintsOptions): number[];
2616
+
2617
+ /**
2618
+ * Edits to a path's order rather than its shape: where a subpath starts, and
2619
+ * which way it runs. Each mutates an `AnchorSet` in place, like the edits in
2620
+ * `anchorEdits`, and moves anchors whole, so anything an anchor carries beside
2621
+ * its point and handles travels with it.
2622
+ */
2623
+
2624
+ /**
2625
+ * Make the anchor at `flatIndex` its subpath's first. A closed subpath turns
2626
+ * so it starts there, keeping its direction. An open subpath can only start
2627
+ * at one of its ends: its last anchor makes it run the other way, and an
2628
+ * interior anchor changes nothing. Returns whether the set changed.
2629
+ */
2630
+ declare function setSubpathStart(set: AnchorSet, flatIndex: number): boolean;
2631
+ /**
2632
+ * Run each subpath in `subs` the other way, every one when `subs` is absent.
2633
+ * The shape is unchanged: each anchor's handles trade places. A closed
2634
+ * subpath keeps its start anchor, as `reversePath` does; an open one starts
2635
+ * where it used to end. Returns whether any subpath had a segment to turn.
2636
+ */
2637
+ declare function reverseSubpaths(set: AnchorSet, subs?: Iterable<number>): boolean;
2638
+ /**
2639
+ * Where each anchor at `flatIndexes` sits once `reverseSubpaths(set, subs)`
2640
+ * has run: an anchor keeps its point, so a selection can follow it. Indexes
2641
+ * outside the set are dropped.
2642
+ */
2643
+ declare function flatIndexesAfterReverse(set: AnchorSet, flatIndexes: Iterable<number>, subs?: Iterable<number>): number[];
2644
+ /** The subpaths holding the anchors at `flatIndexes`, each once, in order. */
2645
+ declare function subpathsOfAnchors(set: AnchorSet, flatIndexes: Iterable<number>): number[];
2646
+ /** A mark showing which way a path runs: a point on it and the unit vector of its heading there. */
2647
+ interface DirectionMark {
2648
+ x: number;
2649
+ y: number;
2650
+ dx: number;
2651
+ dy: number;
2652
+ /** The subpath the mark is on. */
2653
+ sub: number;
2654
+ }
2655
+ /**
2656
+ * One {@link DirectionMark} at the middle of every segment of `set`, closing
2657
+ * segments included, in walk order. A segment with no length gets none.
2658
+ */
2659
+ declare function directionMarks(set: AnchorSet): DirectionMark[];
2660
+
2661
+ /**
2662
+ * Straight and curved segments, converted in place. A segment runs from one
2663
+ * anchor to the next, the closing segment of a closed subpath included, and is
2664
+ * named `(sub, segIdx)` as `segmentAt` reports it.
2665
+ */
2666
+
2667
+ /** A segment of an `AnchorSet`: `segIdx === sub.length - 1` is a closed
2668
+ * subpath's closing segment. */
2669
+ interface SegmentRef {
2670
+ sub: number;
2671
+ segIdx: number;
2672
+ }
2673
+ /** What a segment is made: a line, a curve, or the other of what it is. */
2674
+ type SegmentType = 'line' | 'curve';
2675
+ /**
2676
+ * The segments both of whose ends are among `flatIndexes`, in walk order.
2677
+ * Two adjacent selected anchors select the segment between them; a closed
2678
+ * subpath with every anchor selected has all its segments.
2679
+ */
2680
+ declare function segmentsBetweenAnchors(set: AnchorSet, flatIndexes: Iterable<number>): SegmentRef[];
2681
+ /** Whether segment `seg` is straight, or null when it does not exist. */
2682
+ declare function isSegmentStraight(set: AnchorSet, seg: SegmentRef): boolean | null;
2683
+ /**
2684
+ * Make each segment in `segs` straight or curved without moving its anchors.
2685
+ * A line becomes a curve with its handles a third of the way in from each
2686
+ * end, which draws the same line; a curve becomes a line by dropping the two
2687
+ * handles that shape it, leaving the handles of the segments beside it alone.
2688
+ * With no `to`, every segment turns curved when any of them is straight, and
2689
+ * straight when all are curved: one press flips the lot.
2690
+ *
2691
+ * Returns whether any segment changed.
2692
+ */
2693
+ declare function convertSegments(set: AnchorSet, segs: readonly SegmentRef[], to?: SegmentType): boolean;
2694
+
2695
+ /**
2696
+ * Anchors as numbers a person types: the position of the selected anchors,
2697
+ * and for a lone anchor its handles' positions, angles and lengths. Reading
2698
+ * answers what a field shows; writing sets a value on every selected anchor,
2699
+ * or offsets each by an amount.
2700
+ */
2701
+
2702
+ /** One number of an anchor. Handle angles are degrees counterclockwise from
2703
+ * +x as drawn, where y grows downward; lengths and positions are in the
2704
+ * set's own units. */
2705
+ type AnchorField = 'x' | 'y' | 'inX' | 'inY' | 'inAngle' | 'inLength' | 'outX' | 'outY' | 'outAngle' | 'outLength';
2706
+ /** Every {@link AnchorField}, in the order a panel lists them. */
2707
+ declare const ANCHOR_FIELDS: readonly AnchorField[];
2708
+ /** What a typed field asks for: a value for every anchor, or an amount added to each one's own. */
2709
+ type NumberEntry = {
2710
+ to: number;
2711
+ } | {
2712
+ by: number;
2713
+ };
2714
+ /**
2715
+ * What each field shows for the anchors at `flatIndexes`: a number where
2716
+ * they agree, `null` where they differ, and no key for a field that does not
2717
+ * apply. Position applies to any selection; handle fields only to a single
2718
+ * anchor, and only for a handle it has.
2719
+ */
2720
+ type AnchorFieldValues = Partial<Record<AnchorField, number | null>>;
2721
+ /** The fields for the anchors at `flatIndexes`; `{}` when none of them exists. */
2722
+ declare function readAnchorFields(set: AnchorSet, flatIndexes: Iterable<number>): AnchorFieldValues;
2723
+ /**
2724
+ * Write `entry` into `field` of every anchor at `flatIndexes`. Moving an
2725
+ * anchor carries its handles. A handle field moves the handle as a drag to
2726
+ * the typed spot would (`moveHandleTo`): on a smooth anchor the opposite
2727
+ * handle mirrors it, taking its turn and its length, and on a corner it stays
2728
+ * where it is. An anchor without that handle is skipped. An angle keeps the
2729
+ * handle's length, and a length keeps its angle. Returns whether anything
2730
+ * moved.
2731
+ */
2732
+ declare function writeAnchorField(set: AnchorSet, flatIndexes: Iterable<number>, field: AnchorField, entry: NumberEntry): boolean;
2733
+
1550
2734
  /**
1551
2735
  * Anchor lookup across several paths, measured on screen: which existing
1552
2736
  * anchor is nearest a point, and whether it ends an open subpath. Feeds the
@@ -1671,4 +2855,4 @@ declare function reviveTypedArrays(value: unknown): unknown;
1671
2855
  /** `tagTypedArrays` as a `JSON.stringify` replacer. */
1672
2856
  declare function typedArrayReplacer(_key: string, value: unknown): unknown;
1673
2857
 
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 };
2858
+ 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 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, 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, 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, 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 };