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
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, )
How construction and editing helpers reconcile segment endpoints.
pub type EndpointPolicy {
Strict
Wiggle
Bridge
WiggleThenBridge
}
Constructors
-
StrictEndpoints must already match exactly.
-
WiggleMove nearby endpoints together within the default wiggle tolerance.
-
BridgeKeep endpoints unchanged and insert a straight line if needed.
-
WiggleThenBridgeTry
Wiggle; if that fails, useBridge.
Errors returned by path construction and editing helpers.
pub type Error {
AlreadyClosed
ClosedEmptySubpath
Discontinuous(
previous_index: Int,
next_index: Int,
expected: vec2.Vec2(Float),
got: vec2.Vec2(Float),
distance: Float,
)
EmptySubpath
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)
InvalidCrossingSamples(samples: Int)
InvalidCrossingTolerance(tolerance: Float)
InvalidCrossingMaxIterations(max_iterations: Int)
CrossingMaxIterationsReached(estimate: Float, value: Float)
MultipleNonemptySubpaths
NotCloseEnough(
expected: vec2.Vec2(Float),
got: vec2.Vec2(Float),
tolerance: Float,
)
SplitOutsideSegment
}
Constructors
-
AlreadyClosedThe subpath is already closed and cannot accept more segments.
-
ClosedEmptySubpathAn operation would produce a closed subpath with no segments.
Empty open subpaths are valid, but this package does not represent a closed empty subpath.
-
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_indexis the segment whose end point was expected.next_indexis the segment whose start point did not match.distanceis the distance betweenexpectedandgot. -
EmptySubpathThe operation requires a non-empty subpath.
-
EmptyPathThe operation requires a path with at least one subpath.
-
EmptySubpathsThe operation requires a path with at least one non-empty subpath.
-
DegenerateArcThe arc cannot be converted to center-parameter form.
-
CannotMapArcNonlinearlyNonlinear point mapping cannot preserve an SVG arc segment.
-
A wiggle operation could not reconcile two horizontal line segments.
-
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
startis negative,deleteis negative, orstartis greater than the subpath length. -
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.
-
MultipleNonemptySubpathsThe path contains more than one non-empty subpath.
-
Two points were too far apart for a wiggle operation to merge them.
-
SplitOutsideSegmentThe requested split point is outside the segment’s
0.0..1.0parameter range.
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 straight line segment.
-
A quadratic Bezier curve segment.
-
CubicBezier( start: vec2.Vec2(Float), control1: vec2.Vec2(Float), control2: vec2.Vec2(Float), end: vec2.Vec2(Float), )A cubic Bezier curve segment.
-
Arc( start: vec2.Vec2(Float), radius: vec2.Vec2(Float), x_axis_rotation: Float, large_arc: Bool, sweep: Bool, end: vec2.Vec2(Float), )An elliptical arc segment.
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 arc(
start start: vec2.Vec2(Float),
radius radius: vec2.Vec2(Float),
x_axis_rotation x_axis_rotation: Float,
large_arc large_arc: Bool,
sweep sweep: Bool,
end end: vec2.Vec2(Float),
) -> Segment
Create an elliptical arc segment.
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.
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_with(
subpaths: List(Subpath),
policy endpoint_policy: EndpointPolicy,
) -> Subpath
Join open subpaths with an endpoint policy, panicking if 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 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 clean_subpath(subpath: Subpath) -> Subpath
Remove zero-length line segments from a subpath.
If the subpath contains only one zero-length line, it is preserved so the subpath does not become empty.
pub fn cubic_bezier(
start start: vec2.Vec2(Float),
control1 control1: vec2.Vec2(Float),
control2 control2: vec2.Vec2(Float),
end end: vec2.Vec2(Float),
) -> Segment
Create a cubic Bezier segment.
pub fn default_crossing_options() -> CrossingOptions
Return the default options for segment crossing detection.
pub fn end(subpath: Subpath) -> Result(vec2.Vec2(Float), Error)
Return the end point of a non-empty subpath.
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 are treated as identity values.
pub fn join_with(
subpaths: List(Subpath),
policy endpoint_policy: EndpointPolicy,
) -> Result(Subpath, Error)
Join open subpaths using the given endpoint policy.
pub fn line(
start start: vec2.Vec2(Float),
end end: vec2.Vec2(Float),
) -> Segment
Create a straight line segment.
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 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 non-empty subpath in a path.
pub fn path_start(path: Path) -> Result(vec2.Vec2(Float), Error)
Return the start point of the first non-empty 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 quadratic_bezier(
start start: vec2.Vec2(Float),
control control: vec2.Vec2(Float),
end end: vec2.Vec2(Float),
) -> Segment
Create a quadratic Bezier segment.
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_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_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_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 set_closed(
subpath: Subpath,
closed closed: Bool,
) -> Result(Subpath, Error)
Set a subpath’s semantic closed state.
Setting closed to False only clears the semantic closed flag. Setting it
to True requires the subpath’s end point to exactly match its start point.
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 only clears the semantic closed flag. Setting it
to True uses the given endpoint policy to reconcile the subpath’s end point
with its start point.
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 would make a closed subpath empty,
ClosedEmptySubpath is returned.
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 start(subpath: Subpath) -> Result(vec2.Vec2(Float), Error)
Return the start point of a non-empty subpath.
pub fn subpath(segments: List(Segment)) -> Result(Subpath, Error)
Create an open subpath from a continuous list of segments.
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.