svg_path

Core SVG path data structures and constructors.

This module models paths as a list of subpaths, and subpaths as continuous segment lists. Use svg_path/parse and svg_path/serialize when working directly with SVG path data strings.

Types

An axis-aligned bounding box.

pub type BoundingBox {
  BoundingBox(min: vec2.Vec2(Float), max: vec2.Vec2(Float))
}

Constructors

Options for detecting scalar zero crossings along a segment.

pub type CrossingOptions {
  CrossingOptions(
    samples: Int,
    tolerance: Float,
    max_iterations: Int,
  )
}

Constructors

  • CrossingOptions(
      samples: Int,
      tolerance: Float,
      max_iterations: Int,
    )

Options for finding the distance from a point to a segment.

pub type DistanceOptions {
  DistanceOptions(
    samples: Int,
    tolerance: Float,
    max_iterations: Int,
  )
}

Constructors

  • DistanceOptions(
      samples: Int,
      tolerance: Float,
      max_iterations: Int,
    )

How construction and editing helpers reconcile segment endpoints.

pub type EndpointPolicy {
  Strict
  Wiggle
  Bridge
  WiggleThenBridge
  Custom(fn(Segment, Segment) -> #(Segment, Segment))
}

Constructors

  • Strict

    Endpoints must already match exactly.

  • Wiggle

    Move nearby endpoints together within the default wiggle tolerance.

  • Bridge

    Keep endpoints unchanged and insert a straight line if needed.

  • WiggleThenBridge

    Try Wiggle; if that fails, use Bridge.

  • Custom(fn(Segment, Segment) -> #(Segment, Segment))

    Reconcile non-matching adjacent segments with a caller-provided function.

Errors returned by path construction and editing helpers.

pub type Error {
  AlreadyClosed
  Discontinuous(
    previous_index: Int,
    next_index: Int,
    expected: vec2.Vec2(Float),
    got: vec2.Vec2(Float),
    distance: Float,
  )
  EmptySubpath
  NotClosed
  EmptyPath
  EmptySubpaths
  DegenerateArc
  CannotMapArcNonlinearly
  IncompatibleHorizontalWiggle(
    previous_end: vec2.Vec2(Float),
    next_start: vec2.Vec2(Float),
  )
  IncompatibleVerticalWiggle(
    previous_end: vec2.Vec2(Float),
    next_start: vec2.Vec2(Float),
  )
  InvalidSplice(start: Int, delete: Int, length: Int)
  InvalidOpenIndex(index: Int, length: Int)
  InvalidSubpathParameter(
    segment_index: Int,
    t: Float,
    length: Int,
  )
  InvalidSubpathInterval(
    from: SubpathParameter,
    to: SubpathParameter,
  )
  InvalidCrossingSamples(samples: Int)
  InvalidCrossingTolerance(tolerance: Float)
  InvalidCrossingMaxIterations(max_iterations: Int)
  CrossingMaxIterationsReached(estimate: Float, value: Float)
  InvalidMinimizeSamples(samples: Int)
  InvalidMinimizeTolerance(tolerance: Float)
  InvalidMinimizeMaxIterations(max_iterations: Int)
  MinimizeMaxIterationsReached(estimate: Float, value: Float)
  InvalidDistanceSamples(samples: Int)
  InvalidDistanceTolerance(tolerance: Float)
  InvalidDistanceMaxIterations(max_iterations: Int)
  DistanceMaxIterationsReached(estimate: Float, value: Float)
  InvalidIntersectionTolerance(tolerance: Float)
  InvalidIntersectionMaxDepth(max_depth: Int)
  OverlappingSegments
  MultipleNonemptySubpaths
  NotCloseEnough(
    expected: vec2.Vec2(Float),
    got: vec2.Vec2(Float),
    tolerance: Float,
  )
  SplitOutsideSegment
}

Constructors

  • AlreadyClosed

    The subpath is already closed and cannot accept more segments.

  • Discontinuous(
      previous_index: Int,
      next_index: Int,
      expected: vec2.Vec2(Float),
      got: vec2.Vec2(Float),
      distance: Float,
    )

    A segment starts somewhere other than the previous segment’s end point.

    previous_index is the segment whose end point was expected. next_index is the segment whose start point did not match. distance is the distance between expected and got.

  • EmptySubpath

    The operation requires a non-empty subpath.

  • NotClosed

    The operation requires a closed subpath.

  • EmptyPath

    The operation requires a path with at least one subpath.

  • EmptySubpaths

    The operation requires a path with at least one non-empty subpath.

  • DegenerateArc

    The arc cannot be converted to center-parameter form.

  • CannotMapArcNonlinearly

    Nonlinear point mapping cannot preserve an SVG arc segment.

  • IncompatibleHorizontalWiggle(
      previous_end: vec2.Vec2(Float),
      next_start: vec2.Vec2(Float),
    )

    A wiggle operation could not reconcile two horizontal line segments.

  • IncompatibleVerticalWiggle(
      previous_end: vec2.Vec2(Float),
      next_start: vec2.Vec2(Float),
    )

    A wiggle operation could not reconcile two vertical line segments.

  • InvalidSplice(start: Int, delete: Int, length: Int)

    A splice was requested with invalid bounds.

    This is returned when start is negative, delete is negative, or start is greater than the subpath length.

  • InvalidOpenIndex(index: Int, length: Int)

    An open index was outside the valid range for a closed subpath.

    index must be between -length and length, inclusive.

  • InvalidSubpathParameter(
      segment_index: Int,
      t: Float,
      length: Int,
    )

    A subpath parameter was outside the valid segment index or 0.0..1.0 range.

  • InvalidSubpathInterval(
      from: SubpathParameter,
      to: SubpathParameter,
    )

    A subpath interval would not produce a positive-length piece.

  • InvalidCrossingSamples(samples: Int)

    The number of crossing scan samples must be greater than zero.

  • InvalidCrossingTolerance(tolerance: Float)

    The crossing tolerance must be greater than zero.

  • InvalidCrossingMaxIterations(max_iterations: Int)

    The crossing bisection iteration limit must be greater than zero.

  • CrossingMaxIterationsReached(estimate: Float, value: Float)

    A bracketed crossing could not be refined within the iteration limit.

  • InvalidMinimizeSamples(samples: Int)

    The number of minimization scan samples must be greater than zero.

  • InvalidMinimizeTolerance(tolerance: Float)

    The minimization tolerance must be greater than zero.

  • InvalidMinimizeMaxIterations(max_iterations: Int)

    The minimization iteration limit must be greater than zero.

  • MinimizeMaxIterationsReached(estimate: Float, value: Float)

    A minimization window could not be refined within the iteration limit.

  • InvalidDistanceSamples(samples: Int)

    The number of distance scan samples must be greater than zero.

  • InvalidDistanceTolerance(tolerance: Float)

    The distance tolerance must be greater than zero.

  • InvalidDistanceMaxIterations(max_iterations: Int)

    The distance bisection iteration limit must be greater than zero.

  • DistanceMaxIterationsReached(estimate: Float, value: Float)

    A bracketed distance candidate could not be refined within the iteration limit.

  • InvalidIntersectionTolerance(tolerance: Float)

    The intersection tolerance must be greater than zero.

  • InvalidIntersectionMaxDepth(max_depth: Int)

    The intersection subdivision depth must be greater than zero.

  • OverlappingSegments

    The two segments overlap in more than a single point.

  • MultipleNonemptySubpaths

    The path contains more than one non-empty subpath.

  • NotCloseEnough(
      expected: vec2.Vec2(Float),
      got: vec2.Vec2(Float),
      tolerance: Float,
    )

    Two points were too far apart for a wiggle operation to merge them.

  • SplitOutsideSegment

    The requested split point is outside the segment’s 0.0..1.0 parameter range.

Options for finding segment intersections.

pub type IntersectionOptions {
  IntersectionOptions(tolerance: Float, max_depth: Int)
}

Constructors

  • IntersectionOptions(tolerance: Float, max_depth: Int)

Options for minimizing a scalar function along a segment.

pub type MinimizeOptions {
  MinimizeOptions(
    samples: Int,
    tolerance: Float,
    max_iterations: Int,
  )
}

Constructors

  • MinimizeOptions(
      samples: Int,
      tolerance: Float,
      max_iterations: Int,
    )

An SVG path, made of zero or more subpaths.

pub type Path {
  Path(subpaths: List(Subpath))
}

Constructors

A 2D point.

This is a vec.Vec2(Float), so its coordinates are available as .x and .y.

pub type Point =
  vec2.Vec2(Float)

A single SVG path segment.

pub type Segment {
  Line(start: vec2.Vec2(Float), end: vec2.Vec2(Float))
  QuadraticBezier(
    start: vec2.Vec2(Float),
    control: vec2.Vec2(Float),
    end: vec2.Vec2(Float),
  )
  CubicBezier(
    start: vec2.Vec2(Float),
    control1: vec2.Vec2(Float),
    control2: vec2.Vec2(Float),
    end: vec2.Vec2(Float),
  )
  Arc(
    start: vec2.Vec2(Float),
    radius: vec2.Vec2(Float),
    x_axis_rotation: Float,
    large_arc: Bool,
    sweep: Bool,
    end: vec2.Vec2(Float),
  )
}

Constructors

A point intersection between two segments.

pub type SegmentIntersection {
  SegmentIntersection(
    left_t: Float,
    right_t: Float,
    point: vec2.Vec2(Float),
  )
}

Constructors

  • SegmentIntersection(
      left_t: Float,
      right_t: Float,
      point: vec2.Vec2(Float),
    )

A positioned sequence of path segments, optionally closed.

The first segment, when present, starts at the subpath start point. The last segment of a closed subpath, when present, also ends at the subpath start point. Empty subpaths may be open or closed.

The constructor is opaque so that these invariants are maintained. Use subpath, empty_subpath, append_segment, or their _with variants to build values.

pub opaque type Subpath

A local address on a subpath segment.

segment_index addresses a segment in the subpath, and t is that segment’s local parameter. Subpath APIs require t to be inside 0.0..1.0; unlike segment APIs, subpath parameters do not extrapolate.

pub type SubpathParameter {
  SubpathParameter(segment_index: Int, t: Float)
}

Constructors

  • SubpathParameter(segment_index: Int, t: Float)

Values

pub fn append_segment(
  subpath: Subpath,
  segment: Segment,
) -> Result(Subpath, Error)

Append a segment to an open subpath.

The new segment must start exactly at the current end point.

pub fn append_segment_with(
  subpath: Subpath,
  segment: Segment,
  policy endpoint_policy: EndpointPolicy,
) -> Result(Subpath, Error)

Append a segment to an open subpath using the given endpoint policy.

pub fn append_subpath(path: Path, subpath: Subpath) -> Path

Append a subpath to the end of a path.

pub fn arc_from_center_data(
  data: ellipse.CenterArcData,
) -> Segment

Create an elliptical arc segment from center-parameter arc data.

pub fn arc_from_endpoint_data(
  data: ellipse.EndpointArcData,
) -> Segment

Create an elliptical arc segment from endpoint-parameter arc data.

pub fn as_subpath(path: Path) -> Result(Subpath, Error)

Convert a path with zero or one non-empty subpaths into a subpath.

Empty subpaths are ignored. If more than one non-empty subpath is present, this returns MultipleNonemptySubpaths. If a path has only empty subpaths, the first empty subpath is returned.

pub fn assert_append_segment(
  subpath: Subpath,
  segment: Segment,
) -> Subpath

Append a segment to an open subpath, panicking if invalid.

pub fn assert_append_segment_with(
  subpath: Subpath,
  segment: Segment,
  policy endpoint_policy: EndpointPolicy,
) -> Subpath

Append a segment with an endpoint policy, panicking if invalid.

pub fn assert_join(subpaths: List(Subpath)) -> Subpath

Join open subpaths, panicking if invalid.

pub fn assert_join_with(
  subpaths: List(Subpath),
  policy endpoint_policy: EndpointPolicy,
) -> Subpath

Join open subpaths with an endpoint policy, panicking if invalid.

pub fn assert_polygon(points: List(vec2.Vec2(Float))) -> Subpath

Create a closed polygon subpath, panicking if the point list is invalid.

pub fn assert_polyline(points: List(vec2.Vec2(Float))) -> Subpath

Create an open polyline subpath, panicking if the point list is invalid.

pub fn assert_set_closed(
  subpath: Subpath,
  closed closed: Bool,
) -> Subpath

Set a subpath’s semantic closed state, panicking if invalid.

pub fn assert_set_closed_with(
  subpath: Subpath,
  closed closed: Bool,
  policy endpoint_policy: EndpointPolicy,
) -> Subpath

Set a subpath’s semantic closed state with an endpoint policy, panicking if invalid.

pub fn assert_splice(
  subpath: Subpath,
  start start: Int,
  delete delete: Int,
  insert insert: List(Segment),
) -> Subpath

Replace a range of segments, panicking if the splice is invalid.

pub fn assert_splice_with(
  subpath: Subpath,
  start start: Int,
  delete delete: Int,
  insert insert: List(Segment),
  policy endpoint_policy: EndpointPolicy,
) -> Subpath

Replace a range of segments with an endpoint policy, panicking if invalid.

pub fn assert_subpath(segments: List(Segment)) -> Subpath

Create an open subpath from a non-empty continuous list of segments, panicking if the segments are invalid.

This is useful for hand-authored paths where invalid continuity would be a programmer error. Use subpath when you want to handle construction errors.

pub fn assert_subpath_with(
  segments: List(Segment),
  policy endpoint_policy: EndpointPolicy,
) -> Subpath

Create an open subpath with an endpoint policy, panicking if construction fails.

pub fn bounding_box_center(box: BoundingBox) -> vec2.Vec2(Float)

Return the center point of a bounding box.

pub fn bounding_box_diameter(box: BoundingBox) -> Float

Return the taxicab diameter of a bounding box.

This is the box width plus the box height.

pub fn bounding_box_height(box: BoundingBox) -> Float

Return the height of a bounding box.

pub fn bounding_box_union(
  first: BoundingBox,
  second: BoundingBox,
) -> BoundingBox

Return the smallest axis-aligned bounding box containing both boxes.

pub fn bounding_box_union_many(
  boxes: List(BoundingBox),
) -> Result(BoundingBox, Nil)

Return the smallest axis-aligned bounding box containing every box.

pub fn bounding_box_width(box: BoundingBox) -> Float

Return the width of a bounding box.

pub fn clean_subpath(subpath: Subpath) -> Subpath

Remove zero-length line segments from a subpath.

If cleanup would remove every segment, one zero-length line is preserved so a zero-length drawing subpath does not become a move-only subpath.

pub fn combine_paths(paths: List(Path)) -> Path

Combine paths by concatenating their subpaths.

pub fn compare_subpath_parameters(
  a: SubpathParameter,
  b: SubpathParameter,
) -> order.Order

Compare two subpath parameters by segment index and then local t.

pub fn default_crossing_options() -> CrossingOptions

Return the default options for segment crossing detection.

pub fn default_distance_options() -> DistanceOptions

Return the default options for point-to-segment distance measurement.

pub fn default_intersection_options() -> IntersectionOptions

Return the default options for segment intersection detection.

pub fn default_minimize_options() -> MinimizeOptions

Return the default options for segment minimization.

pub fn empty_path() -> Path

Create an empty path.

pub fn empty_subpath(at start: vec2.Vec2(Float)) -> Subpath

Create an empty open subpath at a start point.

This represents a move-only subpath such as M 0 0.

pub fn end(subpath: Subpath) -> Result(vec2.Vec2(Float), Error)

Return the end point of a subpath.

pub fn from_subpath(subpath: Subpath) -> Path

Create a path containing a single subpath.

pub fn is_closed(subpath: Subpath) -> Bool

Check whether a subpath is closed.

pub fn join(subpaths: List(Subpath)) -> Result(Subpath, Error)

Join open subpaths into one open subpath.

Each subpath’s end point must exactly match the next subpath’s start point. Empty open subpaths can act as identity values when their start points line up with their neighbors.

pub fn join_with(
  subpaths: List(Subpath),
  policy endpoint_policy: EndpointPolicy,
) -> Result(Subpath, Error)

Join open subpaths using the given endpoint policy.

pub fn map_path_points(
  path: Path,
  with f: fn(vec2.Vec2(Float)) -> vec2.Vec2(Float),
) -> Result(Path, Error)

Map the defining points of every segment in a path.

Each subpath’s closed state is preserved. For nonlinear functions, this maps endpoints and control points, not the exact image of every point on each rendered curve. If any segment is an arc, this returns CannotMapArcNonlinearly.

pub fn map_segment_points(
  segment: Segment,
  with f: fn(vec2.Vec2(Float)) -> vec2.Vec2(Float),
) -> Result(Segment, Error)

Map the defining points of a segment.

Lines, quadratic Beziers, and cubic Beziers are mapped by applying f to their endpoints and control points. For nonlinear functions, this is not the exact image of every point on the rendered curve. Arc segments return CannotMapArcNonlinearly because an arbitrary nonlinear mapping does not generally preserve SVG arc parameters.

pub fn map_subpath_points(
  subpath: Subpath,
  with f: fn(vec2.Vec2(Float)) -> vec2.Vec2(Float),
) -> Result(Subpath, Error)

Map the defining points of every segment in a subpath.

The subpath’s closed state is preserved. For nonlinear functions, this maps endpoints and control points, not the exact image of every point on each rendered curve. If any segment is an arc, this returns CannotMapArcNonlinearly.

pub fn open_at(
  subpath: Subpath,
  index index: Int,
) -> Result(Subpath, Error)

Break open a closed subpath at the given segment index.

The index denotes the segment that will become the first segment of the returned open subpath. Negative indices count from the end. index must be between -length and length, inclusive, where length is the number of segments in the subpath. After validation, the index is taken modulo the length, so length, 0, and -length all open at the first segment. Opening a closed empty subpath at index 0 returns an open empty subpath with the same start point.

pub fn path_arcs_to_cubic_beziers(path: Path) -> Path

Convert every arc in a path to cubic Bezier curves.

This applies subpath_arcs_to_cubic_beziers to each subpath.

pub fn path_bounding_box(
  path: Path,
) -> Result(BoundingBox, Error)

Return the exact axis-aligned bounding box of all non-empty subpaths.

pub fn path_end(path: Path) -> Result(vec2.Vec2(Float), Error)

Return the end point of the last subpath in a path.

pub fn path_filter_subpaths(
  path: Path,
  keeping predicate: fn(Subpath) -> Bool,
) -> Path

Keep only the subpaths that satisfy a predicate.

pub fn path_map_subpaths(
  path: Path,
  with f: fn(Subpath) -> Subpath,
) -> Path

Map over the subpaths in a path.

pub fn path_start(path: Path) -> Result(vec2.Vec2(Float), Error)

Return the start point of the first subpath in a path.

pub fn path_to_cubic_beziers(path: Path) -> Path

Convert every segment in a path to cubic Bezier curves.

This applies subpath_to_cubic_beziers to each subpath.

pub fn point(x: Float, y: Float) -> vec2.Vec2(Float)

Create a point from x and y coordinates.

pub fn points_bounding_box(
  points: List(vec2.Vec2(Float)),
) -> Result(BoundingBox, Nil)

Return the smallest axis-aligned bounding box containing every point.

pub fn polygon(
  points: List(vec2.Vec2(Float)),
) -> Result(Subpath, Error)

Create a closed subpath connecting the given points with line segments.

The input must contain at least two points. If the last point equals the first point, no extra zero-length closing line is added.

This is equivalent to constructing a polyline from the same points and closing it with set_closed_with(..., policy: Bridge).

pub fn polyline(
  points: List(vec2.Vec2(Float)),
) -> Result(Subpath, Error)

Create an open subpath connecting the given points with line segments.

The input must contain at least two points.

pub fn reverse_path(path: Path) -> Path

Reverse the traversal direction of a path.

This reverses each subpath and reverses the path’s subpath order.

pub fn reverse_segment(segment: Segment) -> Segment

Reverse the traversal direction of a segment.

pub fn reverse_subpath(subpath: Subpath) -> Subpath

Reverse the traversal direction of every segment in a subpath.

The subpath’s closed state is preserved.

pub fn segment_arcs_to_cubic_beziers(
  segment: Segment,
) -> List(Segment)

Convert an arc segment to cubic Bezier curves, preserving other segments.

Non-arc segments are returned unchanged as a single-item list. An arc may become several cubic Bezier segments.

pub fn segment_bounding_box(
  segment: Segment,
) -> Result(BoundingBox, Error)

Return a segment’s exact axis-aligned bounding box.

pub fn segment_crossings(
  segment: Segment,
  where f: fn(vec2.Vec2(Float)) -> Float,
) -> Result(List(Float), Error)

Find scalar sign-change crossings along a segment using default options.

This samples t in 0.0..1.0, detects sign changes of f(segment_point(t)), and refines each bracket with bisection. It finds crossings visible at the configured sampling resolution; tangent roots and pairs of crossings inside one sample window may be missed.

pub fn segment_crossings_with(
  segment: Segment,
  where f: fn(vec2.Vec2(Float)) -> Float,
  options options: CrossingOptions,
) -> Result(List(Float), Error)

Find scalar sign-change crossings along a segment using explicit options.

pub fn segment_derivative(
  segment: Segment,
  at t: Float,
) -> Result(vec2.Vec2(Float), Error)

Return a segment’s derivative with respect to parameter t.

t is not clamped.

pub fn segment_distance(
  point: vec2.Vec2(Float),
  to segment: Segment,
) -> Result(Float, Error)

Return the shortest distance from a point to a segment.

Lines are measured exactly. Quadratic Beziers, cubic Beziers, and arcs are measured by finding stationary points of squared distance in 0.0..1.0.

pub fn segment_distance_with(
  point: vec2.Vec2(Float),
  to segment: Segment,
  options options: DistanceOptions,
) -> Result(Float, Error)

Return the shortest distance from a point to a segment using explicit options.

pub fn segment_end(segment: Segment) -> vec2.Vec2(Float)

Return the end point of a segment.

pub fn segment_intersections(
  left: Segment,
  right: Segment,
) -> Result(List(SegmentIntersection), Error)

Return point intersections between two segments.

Overlapping segments return OverlappingSegments, since they have more than a finite list of point intersections.

pub fn segment_intersections_with(
  left: Segment,
  right: Segment,
  options options: IntersectionOptions,
) -> Result(List(SegmentIntersection), Error)

Return point intersections between two segments using explicit options.

pub fn segment_minimize(
  segment: Segment,
  measure f: fn(vec2.Vec2(Float)) -> Float,
) -> Result(Float, Error)

Return the segment parameter where a scalar function is minimized.

This numerically minimizes f(segment_point(t)) for t in 0.0..1.0.

pub fn segment_minimize_with(
  segment: Segment,
  measure f: fn(vec2.Vec2(Float)) -> Float,
  options options: MinimizeOptions,
) -> Result(Float, Error)

Return the segment parameter where a scalar function is minimized using explicit options.

pub fn segment_point(
  segment: Segment,
  at t: Float,
) -> Result(vec2.Vec2(Float), Error)

Evaluate a segment at parameter t.

t is not clamped. Values outside 0.0..1.0 extrapolate along the same segment.

pub fn segment_start(segment: Segment) -> vec2.Vec2(Float)

Return the start point of a segment.

pub fn segment_to_cubic_beziers(
  segment: Segment,
) -> List(Segment)

Convert a segment to one or more cubic Bezier curves.

Lines and quadratic Beziers are converted exactly. Cubic Beziers are returned unchanged. Arcs may become several cubic Bezier segments.

pub fn segments(subpath: Subpath) -> List(Segment)

Return the segments in a subpath.

pub fn set_closed(
  subpath: Subpath,
  closed closed: Bool,
) -> Result(Subpath, Error)

Set a subpath’s semantic closed state.

Setting closed to False always succeeds. Setting it to True requires a non-empty subpath’s end point to exactly match its start point. Empty subpaths may be closed.

pub fn set_closed_with(
  subpath: Subpath,
  closed closed: Bool,
  policy endpoint_policy: EndpointPolicy,
) -> Result(Subpath, Error)

Set a subpath’s semantic closed state with an endpoint policy.

Setting closed to False always succeeds. Setting it to True uses the given endpoint policy to reconcile a non-empty subpath’s end point with its start point. Empty subpaths may be closed.

pub fn splice(
  subpath: Subpath,
  start start: Int,
  delete delete: Int,
  insert insert: List(Segment),
) -> Result(Subpath, Error)

Replace a range of segments in a subpath.

start is a zero-based segment index and delete is the number of segments to remove. If start + delete extends past the end of the subpath, everything from start onward is deleted. Negative start, negative delete, and start greater than the subpath length return InvalidSplice.

The edited subpath must remain continuous. Closed subpaths preserve their closed state. If the splice result is nonempty, the subpath start is updated to the first resulting segment’s start point. If the splice result is empty, the previous start point is preserved.

pub fn splice_with(
  subpath: Subpath,
  start start: Int,
  delete delete: Int,
  insert insert: List(Segment),
  policy endpoint_policy: EndpointPolicy,
) -> Result(Subpath, Error)

Replace a range of segments in a subpath using the given endpoint policy.

pub fn split_segment(
  segment: Segment,
  at t: Float,
) -> Result(#(Segment, Segment), Error)

Split a segment at parameter t.

t is not clamped. Values outside 0.0..1.0 extrapolate along the same segment.

pub fn split_segment_inside(
  segment: Segment,
  at t: Float,
) -> Result(#(Segment, Segment), Error)

Split a segment at parameter t, returning an error outside 0.0..1.0.

Values exactly at 0.0 or 1.0 are accepted and produce one zero-length segment.

pub fn split_subpath(
  subpath: Subpath,
  at at: SubpathParameter,
) -> Result(#(Subpath, Subpath), Error)

Split an open subpath at a subpath parameter.

The split point must be inside the subpath: it cannot be the first point, the last point, outside the segment list, or outside the addressed segment’s 0.0..1.0 parameter range. Closed and empty subpaths are rejected.

pub fn start(subpath: Subpath) -> Result(vec2.Vec2(Float), Error)

Return the start point of a subpath.

pub fn sub_segment(
  segment: Segment,
  from from: Float,
  to to: Float,
) -> Result(Segment, Error)

Return the portion of a segment between two parameters.

from and to are not clamped. Values outside 0.0..1.0 extrapolate along the same segment. If from is greater than to, the returned segment traverses the interval in reverse.

pub fn sub_segment_inside(
  segment: Segment,
  from from: Float,
  to to: Float,
) -> Result(Segment, Error)

Return the portion of a segment between two parameters.

from and to must be inside 0.0..1.0, inclusive. If from is greater than to, the returned segment traverses the interval in reverse.

pub fn sub_segments(
  segment: Segment,
  between points: List(Float),
) -> Result(List(Segment), Error)

Return segment portions between adjacent parameters.

Parameters are not clamped. Values outside 0.0..1.0 extrapolate along the same segment. Empty and singleton lists return an empty list.

pub fn sub_segments_inside(
  segment: Segment,
  between points: List(Float),
) -> Result(List(Segment), Error)

Return segment portions between adjacent parameters.

All parameters must be inside 0.0..1.0, inclusive. Empty and singleton lists return an empty list.

pub fn sub_subpath(
  subpath: Subpath,
  from from: SubpathParameter,
  to to: SubpathParameter,
) -> Result(Subpath, Error)

Return the open subpath between two subpath parameters.

Parameters must be valid for the subpath and must describe a positive-length interval. Open subpaths reject reversed intervals. Closed subpaths allow wrapped intervals, but equal parameters are still rejected.

pub fn sub_subpaths(
  subpath: Subpath,
  between points: List(SubpathParameter),
) -> Result(List(Subpath), Error)

Split a subpath at multiple subpath parameters.

Open subpaths return the outer pieces as well as the pieces between split points, so an empty split list returns the original subpath. Open split points must be strictly increasing and cannot include the very start or very end. Closed split points must be cyclically increasing and distinct; empty split lists return an empty list.

pub fn subpath(segments: List(Segment)) -> Result(Subpath, Error)

Create an open subpath from a non-empty continuous list of segments.

Returns EmptySubpath if the segment list is empty. Use empty_subpath when you need to represent a move-only subpath.

Returns Discontinuous if any segment starts somewhere other than the previous segment’s end point. The error includes the two segment indices that failed to meet.

pub fn subpath_arcs_to_cubic_beziers(subpath: Subpath) -> Subpath

Convert every arc in a subpath to cubic Bezier curves.

Lines, quadratic Beziers, and cubic Beziers are preserved. Elliptical arcs are approximated with one or more cubic Beziers, split into chunks of at most a quarter turn. Degenerate arcs fall back to a straight-line cubic Bezier between their endpoints.

pub fn subpath_bounding_box(
  subpath: Subpath,
) -> Result(BoundingBox, Error)

Return a non-empty subpath’s exact axis-aligned bounding box.

pub fn subpath_to_cubic_beziers(subpath: Subpath) -> Subpath

Convert every segment in a subpath to cubic Bezier curves.

Lines and quadratic Beziers are converted exactly. Cubic Beziers are preserved. Elliptical arcs are approximated with one or more cubic Beziers, split into chunks of at most a quarter turn.

pub fn subpath_with(
  segments: List(Segment),
  policy endpoint_policy: EndpointPolicy,
) -> Result(Subpath, Error)

Create an open subpath using the given endpoint reconciliation policy.

Empty segment lists still return EmptySubpath.

pub fn subpaths(path: Path) -> List(Subpath)

Return the subpaths in a path.

Search Document