Blendend.Path (blendend v0.2.0)

View Source

A path is a collection of contours built from commands such as :move_to, :line_to, :quad_to, :cubic_to, and :close.

We typically:

You can also build paths with the DSL in Blendend.Draw:

use Blendend.Draw

path badge do
  add_round_rect(20, 20, 140, 80, 12, 12)
  add_circle(60, 60, 18)
  add_line(20, 20, 160, 100)
end

stroke_path badge

Segment commands vs. shape helpers

There are two families of path builders:

  • *_to segment commands (move_to/3, line_to/3, quad_to/5, cubic_to/7, arc_to/8, elliptic_arc_to/8, etc.) append to the current contour. They expect a current point (set by move_to/3 or a previous segment), do not auto-close, and keep the contour continuous. Reach for these when you need fine-grained control over how a path progresses or must preserve tangents between segments.
  • add_* shape helpers (add_line/6, add_arc/8, add_circle/5, add_rect/6, add_polygon/3, etc.) drop one or more self-contained figures into the path. They start their own contour(s) regardless of the current point, handle their own move_to/close sequence, and accept :direction/:matrix options for winding and transforms. Use these when you just need standard geometry stamped into a path without worrying about continuity with the previous segment.

Summary

Types

t()

Opaque path resource (sequence of lines/curves). Build via DSL or Path.*! helpers.

Functions

Adds an arc defined by (cx, cy, rx, ry, start, sweep).

Adds a closed rectangular box defined by corners (x0, y0) and (x1, y1).

Same as add_box/6, but returns the path .

Adds a chord (closed arc) defined by (cx, cy, rx, ry, start, sweep).

Adds a closed circular contour centered at (cx, cy) with radius r.

Same as add_circle/5, but returns the path .

Adds an ellipse centered at (cx, cy) with radii (rx, ry).

Adds a line segment between (x0, y0) and (x1, y1) as a figure.

Appends all contours from src into dst.

Appends src into dst after applying an affine transform mtx.

Same as add_path/2, but returns dst .

Same as add_path/3, but returns dst .

Adds a polygon defined by points ([{x, y}, ...]).

Same as add_polygon/3, but returns the path .

Adds a polyline defined by points ([{x, y}, ...]).

Adds a closed rectangle (x, y, w, h).

Same as add_rect/6, but returns the path .

Adds a rounded rectangle (x, y, w, h, rx, ry).

Runs Blend2D's stroker on src and appends the resulting outline geometry to dst.

Same as add_stroked_path/4, but limits stroking to a vertex range (tuple {start, stop} or Range, stop exclusive).

Adds a closed triangle (x0, y0), (x1, y1), (x2, y2).

Adds a single 90° arc segment between two points.

Adds a circular or elliptical arc segment to the path.

Clears all vertices from the path.

Same as clear/1, but returns the path .

Closes the current contour (adds a :close command).

Same as close/1, but returns the path .

Adds a rational quadratic Bézier segment to the path.

Same as conic_to/6, but returns the path .

Adds a cubic Bézier curve to (x3, y3) with control points (x1, y1) and (x2, y2).

Same as cubic_to/7, but returns the path .

Dumps internal path representation for debugging.

Same as debug_dump/1, but raises on error.

Adds an endpoint-based elliptical arc to the path.

Returns true if two paths are exactly equal.

Fits the path into the given rectangle {x, y, w, h}.

Same as fit_to/2, but on success, returns path.

Returns a new path where all curves have been approximated by :line_to segments.

Hit-tests (x, y) against the path (fill rule: :non_zero).

Hit-tests (x, y) using the given fill rule (:non_zero | :even_odd).

Adds a straight line segment from the current point to (x, y).

Same as line_to/3, but returns the path .

Starts a new contour at (x, y).

Same as move_to/3, but returns the path.

Creates a new, empty path.

Same as new/0, but returns the path directly.

Adds a quadratic Bézier curve to (x2, y2) with a single control point at (x1, y1).

Same as quad_to/5, but returns the path .

Samples points along a list of straight segments.

Returns a list of straight {{x0, y0}, {x1, y1}} segments for every contour.

set_vertex_at lets you mutate an existing path,

Same as set_vertex_at/5, but returns the path .

Normalizes a path in-place by removing redundant vertices and simplifying its data.

Same as shrink/1, but raises on error.

Continues a cubic Bézier smoothly from the previous segment.

Continues a quadratic Bézier smoothly from the previous segment.

Same as smooth_quad_to/3, but returns the path .

Transforms the whole path by matrix m.

Applies an affine transform matrix only to the vertices within range.

Same as transform/2, but returns the path .

Same as transform/3, but returns the path .

Translates all vertices in the path by (dx, dy) in-place.

Translates only the vertices within range by (dx, dy).

Same as translate/3, but returns the path .

Same as translate/4, but returns the path .

Returns the vertex at index idx.

Same as vertex_at/2, but returns {cmd, x, y} directly.

Returns the number of vertices stored in path.

Same as vertex_count/1, but returns the count directly.

Types

direction()

@type direction() :: :cw | :ccw | :none

hit_class()

@type hit_class() :: :in | :out | :part

point()

@type point() :: {float(), float()}

sampled_point()

@type sampled_point() :: {point(), {float(), float()}}

segment()

@type segment() :: {point(), point()}

t()

@opaque t()

Opaque path resource (sequence of lines/curves). Build via DSL or Path.*! helpers.

Functions

add_arc(path, cx, cy, rx, ry, start, sweep, opts \\ [])

@spec add_arc(
  t(),
  number(),
  number(),
  number(),
  number(),
  number(),
  number(),
  keyword()
) ::
  :ok | {:error, term()}

Adds an arc defined by (cx, cy, rx, ry, start, sweep).

Accepts the same optional opts as add_circle/5.

add_arc!(path, cx, cy, rx, ry, start, sweep, opts \\ [])

@spec add_arc!(
  t(),
  number(),
  number(),
  number(),
  number(),
  number(),
  number(),
  keyword()
) :: t()

Same as add_arc/8, but returns the path .

add_box(path, x0, y0, x1, y1, opts \\ [])

@spec add_box(t(), number(), number(), number(), number(), keyword()) ::
  :ok | {:error, term()}

Adds a closed rectangular box defined by corners (x0, y0) and (x1, y1).

Optional opts:

On success, returns :ok.

On failure, returns {:error, reason}.

add_box!(path, x0, y0, x1, y1, opts \\ [])

@spec add_box!(t(), number(), number(), number(), number(), keyword()) :: t()

Same as add_box/6, but returns the path .

On success, returns path.

On failure, raises Blendend.Error.

add_chord(path, cx, cy, rx, ry, start, sweep, opts \\ [])

@spec add_chord(
  t(),
  number(),
  number(),
  number(),
  number(),
  number(),
  number(),
  keyword()
) ::
  :ok | {:error, term()}

Adds a chord (closed arc) defined by (cx, cy, rx, ry, start, sweep).

Accepts the same optional opts as add_circle/5.

add_chord!(path, cx, cy, rx, ry, start, sweep, opts \\ [])

@spec add_chord!(
  t(),
  number(),
  number(),
  number(),
  number(),
  number(),
  number(),
  keyword()
) :: t()

Same as add_chord/8, but returns the path .

add_circle(path, cx, cy, r, opts \\ [])

@spec add_circle(t(), number(), number(), number(), keyword()) ::
  :ok | {:error, term()}

Adds a closed circular contour centered at (cx, cy) with radius r.

Optional opts:

On success, returns :ok.

On failure, returns {:error, reason}.

add_circle!(path, cx, cy, r, opts \\ [])

@spec add_circle!(t(), number(), number(), number(), keyword()) :: t()

Same as add_circle/5, but returns the path .

On success, returns path.

On failure, raises Blendend.Error.

add_ellipse(path, cx, cy, rx, ry, opts \\ [])

@spec add_ellipse(t(), number(), number(), number(), number(), keyword()) ::
  :ok | {:error, term()}

Adds an ellipse centered at (cx, cy) with radii (rx, ry).

Accepts the same optional opts as add_circle/5.

add_ellipse!(path, cx, cy, rx, ry, opts \\ [])

@spec add_ellipse!(t(), number(), number(), number(), number(), keyword()) :: t()

Same as add_ellipse/6, but returns the path .

add_line(path, x0, y0, x1, y1, opts \\ [])

@spec add_line(t(), number(), number(), number(), number(), keyword()) ::
  :ok | {:error, term()}

Adds a line segment between (x0, y0) and (x1, y1) as a figure.

Accepts the same optional opts as add_circle/5.

add_line!(path, x0, y0, x1, y1, opts \\ [])

@spec add_line!(t(), number(), number(), number(), number(), keyword()) :: t()

Same as add_line/6, but returns the path .

add_path(dst, src)

@spec add_path(t(), t()) :: :ok | {:error, term()}

Appends all contours from src into dst.

Mutates dst in-place and leaves src unchanged.

On success, returns :ok.

On failure, returns {:error, reason}.

add_path(dst, src, mtx)

@spec add_path(t(), t(), Blendend.Matrix2D.t()) :: :ok | {:error, term()}

Appends src into dst after applying an affine transform mtx.

Mutates dst in-place and leaves src unchanged.

On success, returns :ok.

On failure, returns {:error, reason}.

add_path!(dst, src)

@spec add_path!(t(), t()) :: t()

Same as add_path/2, but returns dst .

On success, returns dst.

On failure, raises Blendend.Error.

add_path!(dst, src, mtx)

@spec add_path!(t(), t(), Blendend.Matrix2D.t()) :: t()

Same as add_path/3, but returns dst .

On success, returns dst.

On failure, raises Blendend.Error.

add_polygon(path, points, opts \\ [])

@spec add_polygon(t(), [point()], keyword()) :: :ok | {:error, term()}

Adds a polygon defined by points ([{x, y}, ...]).

Accepts the same optional opts as add_circle/5.

add_polygon!(path, points, opts \\ [])

@spec add_polygon!(t(), [point()], keyword()) :: t()

Same as add_polygon/3, but returns the path .

add_polyline(path, points, opts \\ [])

@spec add_polyline(t(), [point()], keyword()) :: :ok | {:error, term()}

Adds a polyline defined by points ([{x, y}, ...]).

Accepts the same optional opts as add_circle/5.

add_polyline!(path, points, opts \\ [])

@spec add_polyline!(t(), [point()], keyword()) :: t()

Same as add_polyline/3, but returns the path .

add_rect(path, x, y, w, h, opts \\ [])

@spec add_rect(t(), number(), number(), number(), number(), keyword()) ::
  :ok | {:error, term()}

Adds a closed rectangle (x, y, w, h).

Accepts the same optional opts as add_box/6.

On success, returns :ok.

On failure, returns {:error, reason}.

add_rect!(path, x, y, w, h, opts \\ [])

@spec add_rect!(t(), number(), number(), number(), number(), keyword()) :: t()

Same as add_rect/6, but returns the path .

On success, returns path.

On failure, raises Blendend.Error.

add_round_rect(path, x, y, w, h, rx, ry, opts \\ [])

@spec add_round_rect(
  t(),
  number(),
  number(),
  number(),
  number(),
  number(),
  number(),
  keyword()
) ::
  :ok | {:error, term()}

Adds a rounded rectangle (x, y, w, h, rx, ry).

Accepts the same optional opts as add_circle/5.

add_round_rect!(path, x, y, w, h, rx, ry, opts \\ [])

@spec add_round_rect!(
  t(),
  number(),
  number(),
  number(),
  number(),
  number(),
  number(),
  keyword()
) :: t()

Same as add_round_rect/8, but returns the path .

add_stroked_path(dst, src, stroke_opts \\ [], approx_opts \\ [])

@spec add_stroked_path(t(), t(), keyword(), keyword()) :: :ok | {:error, term()}

Runs Blend2D's stroker on src and appends the resulting outline geometry to dst.

This does not draw anything; it converts a stroke into fillable path geometry.

stroke_opts (keyword list) mirrors Blendend.Canvas.Stroke.path/2:

  • :width – stroke width (float, default 1.0)
  • :miter_limit – miter limit (default 4.0)
  • :start_cap / :end_cap:butt | :round | :square | :round_rev | :triangle | :triangle_rev

  • :join:miter_clip | :miter_bevel | :miter_round | :bevel | :round

  • :transform_order:after | :before (default :after)

approx_opts (keyword list) maps to BLApproximationOptions:

  • :flatten_tolerance, :simplify_tolerance, :offset_parameter
  • :flatten_mode:default | :recursive

  • :offset_mode:default | :iterative

Examples

iex> alias Blendend.Path
iex> src = Path.new!() |> Path.move_to!(20, 20) |> Path.line_to!(80, 20)
iex> outline = Path.new!()
iex> :ok = Path.add_stroked_path(outline, src, width: 6.0, join: :round)
iex> Path.vertex_count!(outline) > Path.vertex_count!(src)
true

On success, returns :ok. On failure, returns {:error, reason}.

add_stroked_path(dst, src, range, stroke_opts, approx_opts)

@spec add_stroked_path(
  t(),
  t(),
  Range.t() | {non_neg_integer(), non_neg_integer()},
  keyword(),
  keyword()
) :: :ok | {:error, term()}

Same as add_stroked_path/4, but limits stroking to a vertex range (tuple {start, stop} or Range, stop exclusive).

add_stroked_path!(dst, src, stroke_opts \\ [], approx_opts \\ [])

@spec add_stroked_path!(t(), t(), keyword(), keyword()) :: t()

Same as add_stroked_path/4, but returns the path directly.

add_stroked_path!(dst, src, range, stroke_opts, approx_opts)

@spec add_stroked_path!(
  t(),
  t(),
  Range.t() | {non_neg_integer(), non_neg_integer()},
  keyword(),
  keyword()
) :: t()

Same as add_stroked_path/5, but returns the path directly.

add_triangle(path, x0, y0, x1, y1, x2, y2, opts \\ [])

@spec add_triangle(
  t(),
  number(),
  number(),
  number(),
  number(),
  number(),
  number(),
  keyword()
) :: :ok | {:error, term()}

Adds a closed triangle (x0, y0), (x1, y1), (x2, y2).

Accepts the same optional opts as add_circle/5.

add_triangle!(path, x0, y0, x1, y1, x2, y2, opts \\ [])

@spec add_triangle!(
  t(),
  number(),
  number(),
  number(),
  number(),
  number(),
  number(),
  keyword()
) :: t()

Same as add_triangle/8, but returns the path .

arc_quadrant_to(path, x1, y1, x2, y2)

@spec arc_quadrant_to(t(), number(), number(), number(), number()) ::
  :ok | {:error, term()}

Adds a single 90° arc segment between two points.

On success, returns :ok.

On failure, returns {:error, reason}.

arc_quadrant_to!(path, x1, y1, x2, y2)

@spec arc_quadrant_to!(t(), number(), number(), number(), number()) :: t()

Same as arc_quadrant_to/5, but returns the path .

On success, returns path.

On failure, raises Blendend.Error.

arc_to(path, cx, cy, rx, ry, start, sweep, force_move? \\ false)

@spec arc_to(
  t(),
  number(),
  number(),
  number(),
  number(),
  number(),
  number(),
  boolean()
) :: :ok | {:error, term()}

Adds a circular or elliptical arc segment to the path.

Wraps blend2d's arcTo. Parameters:

  • cx, cy – center of the ellipse
  • rx, ry – radii in x and y
  • start – start angle in radians
  • sweep – sweep angle in radians
  • force_move? – when true, starts a new sub-path at the arc's start point instead of connecting from the current point

On success, returns :ok.

On failure, returns {:error, reason}.

arc_to!(path, cx, cy, rx, ry, start, sweep, force_move? \\ false)

@spec arc_to!(
  t(),
  number(),
  number(),
  number(),
  number(),
  number(),
  number(),
  boolean()
) :: t()

Same as arc_to/8, but returns the path .

On success, returns path.

On failure, raises Blendend.Error.

clear(path)

@spec clear(t()) :: :ok | {:error, term()}

Clears all vertices from the path.

On success, returns :ok.

On failure, returns {:error, reason}.

clear!(path)

@spec clear!(t()) :: t()

Same as clear/1, but returns the path .

On success, returns path.

On failure, raises Blendend.Error.

close(path)

@spec close(t()) :: :ok | {:error, term()}

Closes the current contour (adds a :close command).

On success, returns :ok.

On failure, returns {:error, reason}.

close!(path)

@spec close!(t()) :: t()

Same as close/1, but returns the path .

On success, returns path.

On failure, raises Blendend.Error.

conic_to(path, x1, y1, x2, y2, w)

@spec conic_to(t(), number(), number(), number(), number(), number()) ::
  :ok | {:error, term()}

Adds a rational quadratic Bézier segment to the path.

Extends the current contour from the current point to (x2, y2) with a quadratic curve that has control point (x1, y1) and a weight w.

  • When w == 1.0 it behaves like a standard quadratic curve.
  • Other weights bend the curve closer to or further from the control point, which is useful for arcs and circular approximations.

The path must already have a current point.

On success, returns :ok.

On failure, returns {:error, reason}.

conic_to!(path, x1, y1, x2, y2, w)

@spec conic_to!(t(), number(), number(), number(), number(), number()) :: t()

Same as conic_to/6, but returns the path .

On success, returns path.

On failure, raises Blendend.Error.

cubic_to(path, x1, y1, x2, y2, x3, y3)

@spec cubic_to(t(), number(), number(), number(), number(), number(), number()) ::
  :ok | {:error, term()}

Adds a cubic Bézier curve to (x3, y3) with control points (x1, y1) and (x2, y2).

On success, returns :ok.

On failure, returns {:error, reason}.

cubic_to!(path, x1, y1, x2, y2, x3, y3)

@spec cubic_to!(t(), number(), number(), number(), number(), number(), number()) ::
  t()

Same as cubic_to/7, but returns the path .

On success, returns path.

On failure, raises Blendend.Error.

debug_dump(path)

@spec debug_dump(t()) :: :ok | {:error, term()}

Dumps internal path representation for debugging.

On success, returns :ok.

On failure, returns {:error, reason}.

debug_dump!(path)

@spec debug_dump!(t()) :: :ok

Same as debug_dump/1, but raises on error.

On success, returns :ok.

On failure, raises Blendend.Error.

Examples

iex> p = Blendend.Path.new!()
iex> p = Blendend.Path.move_to!(p, 247, 97)
iex> Path.debug_dump!(p)
:ok
# prints:
# [path_debug_dump] path size = 1
# [  0] cmd=0 x=247.000000 y=97.000000

elliptic_arc_to(path, rx, ry, rot, large?, sweep?, x1, y1)

@spec elliptic_arc_to(
  t(),
  number(),
  number(),
  number(),
  boolean(),
  boolean(),
  number(),
  number()
) :: :ok | {:error, term()}

Adds an endpoint-based elliptical arc to the path.

Wraps blend2d's ellipticArcTo (similar to SVG A):

  • rx, ry – ellipse radii
  • rot – x-axis rotation in radians
  • large? – large-arc flag
  • sweep? – sweep direction flag
  • x1, y1 – endpoint of the arc

The start point is the current point in the path.

On success, returns :ok.

On failure, returns {:error, reason}.

elliptic_arc_to!(path, rx, ry, rot, large?, sweep?, x1, y1)

@spec elliptic_arc_to!(
  t(),
  number(),
  number(),
  number(),
  boolean(),
  boolean(),
  number(),
  number()
) :: t()

Same as elliptic_arc_to/8, but returns the path .

On success, returns path.

On failure, raises Blendend.Error.

equal?(path_a, path_b)

@spec equal?(t(), t()) :: boolean()

Returns true if two paths are exactly equal.

This is a strict, bit-for-bit comparison of the underlying data. Tiny floating point differences will make it return false.

fit_to(path, arg)

@spec fit_to(t(), {number(), number(), number(), number()}) :: :ok | {:error, term()}

Fits the path into the given rectangle {x, y, w, h}.

Mutates the path in-place so its bounds fit inside the rectangle.

On success, returns :ok.

On failure, returns {:error, reason}.

fit_to!(path, rect)

@spec fit_to!(t(), {number(), number(), number(), number()}) :: t()

Same as fit_to/2, but on success, returns path.

On failure, raises Blendend.Error.

flatten(path, tolerance)

@spec flatten(t(), number()) :: {:ok, t()} | {:error, term()}

Returns a new path where all curves have been approximated by :line_to segments.

The resulting path only contains :move_to, :line_to, and :close commands. The tolerance argument controls the approximation accuracy (default 0.25 user units).

On success returns {:ok, new_path}.

flatten!(path, tolerance \\ 0.25)

@spec flatten!(t(), number()) :: t()

hit_test(path, x, y)

@spec hit_test(t(), number(), number()) :: hit_class()

Hit-tests (x, y) against the path (fill rule: :non_zero).

Returns :in | :out | :part on success.

Raises Blendend.Error if the NIF reports :invalid (bad args, NaNs, etc.) or if an error tuple is returned.

hit_test(path, x, y, rule)

@spec hit_test(t(), number(), number(), :non_zero | :even_odd) :: hit_class()

Hit-tests (x, y) using the given fill rule (:non_zero | :even_odd).

Returns :in | :out | :part on success.

Raises Blendend.Error if the NIF reports :invalid or an error.

line_to(path, x, y)

@spec line_to(t(), number(), number()) :: :ok | {:error, term()}

Adds a straight line segment from the current point to (x, y).

The path must already have a current point (for example from a previous move_to/3 or other drawing command).

On success, returns :ok.

On failure, returns {:error, reason}.

line_to!(path, x, y)

@spec line_to!(t(), number(), number()) :: t()

Same as line_to/3, but returns the path .

On success, returns the same path.

On failure, raises Blendend.Error.

move_to(path, x, y)

@spec move_to(t(), number(), number()) :: :ok | {:error, term()}

Starts a new contour at (x, y).

This is equivalent to a :move_to command in the underlying path.

On success, returns :ok.

On failure, returns {:error, reason}.

move_to!(path, x, y)

@spec move_to!(t(), number(), number()) :: t()

Same as move_to/3, but returns the path.

On failure, raises Blendend.Error.

new()

@spec new() :: {:ok, t()} | {:error, term()}

Creates a new, empty path.

On success, returns {:ok, path}.

On failure, returns {:error, reason}.

new!()

@spec new!() :: t()

Same as new/0, but returns the path directly.

On success, returns the path.

On failure, raises Blendend.Error.

quad_to(path, x1, y1, x2, y2)

@spec quad_to(t(), number(), number(), number(), number()) :: :ok | {:error, term()}

Adds a quadratic Bézier curve to (x2, y2) with a single control point at (x1, y1).

This is equivalent to a :quad_to command.

On success, returns :ok.

On failure, returns {:error, reason}.

quad_to!(path, x1, y1, x2, y2)

@spec quad_to!(t(), number(), number(), number(), number()) :: t()

Same as quad_to/5, but returns the path .

On success, returns path.

On failure, raises Blendend.Error.

sample(segments, spacing, opts \\ [])

@spec sample([segment()], number(), Keyword.t()) :: [sampled_point()]

Samples points along a list of straight segments.

Each returned item is {{x, y}, {nx, ny}} where {nx, ny} is the unit-length left-hand normal for the directed segment {p0 -> p1} ({-dy/len, dx/len}).

Options:

  • :include_ends? (default: true) – include segment endpoints in sampling

spacing must be positive. Zero-length segments are skipped.

segments(path)

@spec segments(t()) :: [segment()]

Returns a list of straight {{x0, y0}, {x1, y1}} segments for every contour.

Assumes the path only contains :move_to, :line_to, and :close commands. Call flatten!/1 first if your path has curves. When a :close is seen, the last point is connected back to the contour start.

Raises ArgumentError if a curve command (:quad_to, :cubic_to, etc.) is encountered or if the path is malformed (for example :line_to before any :move_to).

set_vertex_at(path, idx, cmd, x, y)

@spec set_vertex_at(t(), non_neg_integer(), atom(), float(), float()) ::
  :ok | {:error, term()}

set_vertex_at lets you mutate an existing path,

idx is zero-based; cmd controls how the vertex is interpreted.

On success, returns :ok.

On failure, returns {:error, reason}.

set_vertex_at!(path, idx, cmd, x, y)

@spec set_vertex_at!(t(), non_neg_integer(), atom(), float(), float()) :: t()

Same as set_vertex_at/5, but returns the path .

On success, returns path.

On failure, raises Blendend.Error.

shrink(path)

@spec shrink(t()) :: {:ok, t()} | {:error, term()}

Normalizes a path in-place by removing redundant vertices and simplifying its data.

Wraps BLPath.shrink/0. Useful after stroking or bulk edits to compact the path buffer.

shrink!(path)

@spec shrink!(t()) :: t()

Same as shrink/1, but raises on error.

smooth_cubic_to(path, x2, y2, x3, y3)

@spec smooth_cubic_to(t(), number(), number(), number(), number()) ::
  :ok | {:error, term()}

Continues a cubic Bézier smoothly from the previous segment.

Wraps blend2d smoothCubicTo (like SVG S):

  • If the previous segment was cubic, the first control point of this segment is the mirror of the previous segment's second control point across the current point.
  • This gives a visually smooth tangent across the join.

The segment ends at (x3, y3) and uses (x2, y2) as the second control point.

On success, returns :ok.

On failure, returns {:error, reason}.

smooth_cubic_to!(path, x2, y2, x3, y3)

@spec smooth_cubic_to!(t(), number(), number(), number(), number()) :: t()

Same as smooth_cubic_to/5, but returns the path .

On success, returns path.

On failure, raises Blendend.Error.

smooth_quad_to(path, x2, y2)

@spec smooth_quad_to(t(), number(), number()) :: :ok | {:error, term()}

Continues a quadratic Bézier smoothly from the previous segment.

Wraps blend2d smoothQuadTo (like SVG T):

  • If the previous segment was a quadratic curve, the missing control point is mirrored across the current point to keep the curve smooth.
  • If there is no previous quadratic, the current point is used as the control point.

The segment ends at (x2, y2).

On success, returns :ok.

On failure, returns {:error, reason}.

smooth_quad_to!(path, x2, y2)

@spec smooth_quad_to!(t(), number(), number()) :: t()

Same as smooth_quad_to/3, but returns the path .

On success, returns path.

On failure, raises Blendend.Error.

transform(path, matrix)

@spec transform(t(), Blendend.Matrix2D.t()) :: :ok | {:error, term()}

Transforms the whole path by matrix m.

Mutates the path in-place. Wraps BLPath::transform(matrix).

transform(path, range, matrix)

@spec transform(
  t(),
  Range.t() | {non_neg_integer(), non_neg_integer()},
  Blendend.Matrix2D.t()
) ::
  :ok | {:error, term()}

Applies an affine transform matrix only to the vertices within range.

range accepts a two-tuple {start, stop} (zero-based, stop exclusive) or an Elixir Range.

transform!(path, matrix)

@spec transform!(t(), Blendend.Matrix2D.t()) :: t()

Same as transform/2, but returns the path .

transform!(path, range, matrix)

@spec transform!(
  t(),
  Range.t() | {non_neg_integer(), non_neg_integer()},
  Blendend.Matrix2D.t()
) :: t()

Same as transform/3, but returns the path .

translate(path, dx, dy)

@spec translate(t(), number(), number()) :: :ok | {:error, term()}

Translates all vertices in the path by (dx, dy) in-place.

On success, returns :ok.

On failure, returns {:error, reason}.

translate(path, range, dx, dy)

@spec translate(
  t(),
  Range.t() | {non_neg_integer(), non_neg_integer()},
  number(),
  number()
) ::
  :ok | {:error, term()}

Translates only the vertices within range by (dx, dy).

range can be either a two-tuple {start, stop} (zero-based, stop is exclusive) or an Elixir Range struct.

On success, returns :ok.

On failure, returns {:error, reason}.

translate!(path, dx, dy)

@spec translate!(t(), number(), number()) :: t()

Same as translate/3, but returns the path .

On success, returns path.

On failure, raises Blendend.Error.

translate!(path, range, dx, dy)

@spec translate!(
  t(),
  Range.t() | {non_neg_integer(), non_neg_integer()},
  number(),
  number()
) :: t()

Same as translate/4, but returns the path .

On success, returns path.

On failure, raises Blendend.Error.

vertex_at(path, idx)

@spec vertex_at(t(), non_neg_integer()) ::
  {:ok, {atom(), float(), float()}} | {:error, term()}

Returns the vertex at index idx.

On success, returns {:ok, {cmd, x, y}} where:

  • cmd – atom like :move_to, :line_to, :quad_to, :cubic_to, :close
  • x, y – coordinates as floats

On failure, returns {:error, reason}.

vertex_at!(path, idx)

@spec vertex_at!(t(), non_neg_integer()) :: {atom(), float(), float()}

Same as vertex_at/2, but returns {cmd, x, y} directly.

On success, returns {cmd, x, y}.

On failure, raises Blendend.Error.

vertex_count(path)

@spec vertex_count(t()) :: {:ok, non_neg_integer()} | {:error, term()}

Returns the number of vertices stored in path.

On success, returns {:ok, count}.

On failure, returns {:error, reason}.

vertex_count!(path)

@spec vertex_count!(t()) :: non_neg_integer()

Same as vertex_count/1, but returns the count directly.

On success, returns count.

On failure, raises Blendend.Error.