Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
pulp::canvas::Path Class Reference

#include <path.hpp>

Classes

struct  Element
 One step of an iteration over the path. More...
class  Iterator
 Forward iterator over the verbs. More...
struct  FlatSubpath
 Flatten every curve to line segments, within tolerance user units of the true curve. More...

Public Types

enum class  Verb : uint8_t {
  move , line , quad , cubic ,
  close
}
 The closed verb set. Arcs and ellipses flatten to cubic at build time. More...

Public Member Functions

 Path ()=default
 Path (const Path &)=default
Path & operator= (const Path &)=default
 Path (Path &&) noexcept=default
Path & operator= (Path &&) noexcept=default
 ~Path ()=default
bool operator== (const Path &o) const
 Geometric equality: same verbs, same points, in the same order.
bool operator!= (const Path &o) const
Path & move_to (float x, float y)
Path & line_to (float x, float y)
Path & quad_to (float cx, float cy, float x, float y)
Path & cubic_to (float c1x, float c1y, float c2x, float c2y, float x, float y)
Path & arc_to (float x1, float y1, float x2, float y2, float radius)
 Tangent arc, matching Canvas2D ctx.arcTo(x1, y1, x2, y2, radius): the arc of radius tangent to both the line (current → P1) and the line (P1 → P2), preceded by a line from the current point to the first tangent point.
Path & close ()
void clear ()
 Drop every verb. Keeps any allocated capacity for reuse.
Path & add_rect (float x, float y, float w, float h)
Path & add_rect (const Rect2D &r)
Path & add_rounded_rect (float x, float y, float w, float h, float radius)
 Uniform corner radius, clamped to half the shorter side.
Path & add_rounded_rect (float x, float y, float w, float h, float top_left, float top_right, float bottom_right, float bottom_left)
 Per-corner radii, clockwise from the top-left.
Path & add_ellipse (float cx, float cy, float rx, float ry)
Path & add_circle (float cx, float cy, float radius)
Path & add_arc (float cx, float cy, float rx, float ry, float start_angle, float sweep_angle)
 Arc as its own subpath (an implicit move_to to the arc's start).
Path & add_pie (float cx, float cy, float rx, float ry, float start_angle, float sweep_angle)
 A pie slice / wedge: center → arc → back to center, closed.
Path & add_polygon (const Point2D *points, size_t count)
 Closed polygon through count points. Fewer than 2 points draws nothing.
Path & add_path (const Path &other, const AffineTransform &transform=AffineTransform::identity())
 Append other, optionally transformed.
void apply_transform (const AffineTransform &t)
 Transform every point in place.
Path transformed (const AffineTransform &t) const
 A transformed copy; leaves this path alone.
AffineTransform transform_to_fit (float x, float y, float w, float h, bool preserve_proportions) const
 The transform that would scale this path to fit (x, y, w, h).
void scale_to_fit (float x, float y, float w, float h, bool preserve_proportions)
 apply_transform(transform_to_fit(...)).
bool is_empty () const
size_t verb_count () const
 Number of verbs.
Rect2D bounds () const
 TIGHT bounds: the true visual bounding box, computed from each curve's extrema (the roots of its derivative), not from its control hull.
Rect2D control_bounds () const
 Cheap conservative bounds: the AABB of the control points.
bool contains (Point2D p, FillRule rule=FillRule::nonzero) const
 Is p inside the path under rule?
bool contains (float x, float y, FillRule rule=FillRule::nonzero) const
std::optional< Point2D > current_point () const
 The last point of the path, or nullopt if there is no current point.
Iterator begin () const
Iterator end () const
template<typename Sink>
void replay (Sink &sink) const
 Replay this path into any sink that exposes the Canvas path-builder verbs.
std::vector< FlatSubpath > flatten (float tolerance=0.25f) const
std::string to_svg_string () const
 Emit a standard SVG d string using absolute commands (M/L/Q/C/Z).

Static Public Member Functions

static constexpr int points_for (Verb v)
 How many points a verb consumes.
static Path from_svg_string (const std::string &d)
 Parse an SVG path d string.

Friends

class Iterator

Member Enumeration Documentation

◆ Verb

enum class pulp::canvas::Path::Verb : uint8_t
strong

The closed verb set. Arcs and ellipses flatten to cubic at build time.

Enumerator
move 

1 point: the new subpath's start

line 

1 point: the endpoint

quad 

2 points: control, endpoint

cubic 

3 points: control 1, control 2, endpoint

close 

0 points: close the current subpath

Constructor & Destructor Documentation

◆ Path() [1/3]

pulp::canvas::Path::Path ( )
default

◆ Path() [2/3]

pulp::canvas::Path::Path ( const Path & )
default

◆ Path() [3/3]

pulp::canvas::Path::Path ( Path && )
defaultnoexcept

◆ ~Path()

pulp::canvas::Path::~Path ( )
default

Member Function Documentation

◆ add_arc()

Path & pulp::canvas::Path::add_arc ( float cx,
float cy,
float rx,
float ry,
float start_angle,
float sweep_angle )

Arc as its own subpath (an implicit move_to to the arc's start).

Angles in radians, measured clockwise from the +x axis in Pulp's y-down coordinate space. sweep may be negative (counter-clockwise).

◆ add_circle()

Path & pulp::canvas::Path::add_circle ( float cx,
float cy,
float radius )
inline

◆ add_ellipse()

Path & pulp::canvas::Path::add_ellipse ( float cx,
float cy,
float rx,
float ry )

◆ add_path()

Path & pulp::canvas::Path::add_path ( const Path & other,
const AffineTransform & transform = AffineTransform::identity() )

Append other, optionally transformed.

Subpaths stay separate — this never joins other's first point to this path's current point.

◆ add_pie()

Path & pulp::canvas::Path::add_pie ( float cx,
float cy,
float rx,
float ry,
float start_angle,
float sweep_angle )

A pie slice / wedge: center → arc → back to center, closed.

◆ add_polygon()

Path & pulp::canvas::Path::add_polygon ( const Point2D * points,
size_t count )

Closed polygon through count points. Fewer than 2 points draws nothing.

◆ add_rect() [1/2]

Path & pulp::canvas::Path::add_rect ( const Rect2D & r)
inline

◆ add_rect() [2/2]

Path & pulp::canvas::Path::add_rect ( float x,
float y,
float w,
float h )

◆ add_rounded_rect() [1/2]

Path & pulp::canvas::Path::add_rounded_rect ( float x,
float y,
float w,
float h,
float radius )

Uniform corner radius, clamped to half the shorter side.

◆ add_rounded_rect() [2/2]

Path & pulp::canvas::Path::add_rounded_rect ( float x,
float y,
float w,
float h,
float top_left,
float top_right,
float bottom_right,
float bottom_left )

Per-corner radii, clockwise from the top-left.

Each is clamped so that adjacent radii on one side never sum to more than that side's length — the CSS border-radius overlap rule.

◆ apply_transform()

void pulp::canvas::Path::apply_transform ( const AffineTransform & t)

Transform every point in place.

◆ arc_to()

Path & pulp::canvas::Path::arc_to ( float x1,
float y1,
float x2,
float y2,
float radius )

Tangent arc, matching Canvas2D ctx.arcTo(x1, y1, x2, y2, radius): the arc of radius tangent to both the line (current → P1) and the line (P1 → P2), preceded by a line from the current point to the first tangent point.

Degenerate input (no current point, zero radius, collinear points) falls back to a straight line_to(x1, y1), which is what the Canvas2D spec requires.

◆ begin()

Iterator pulp::canvas::Path::begin ( ) const
inline

◆ bounds()

Rect2D pulp::canvas::Path::bounds ( ) const

TIGHT bounds: the true visual bounding box, computed from each curve's extrema (the roots of its derivative), not from its control hull.

This differs from control_bounds() for any curve whose control points fall outside the curve — which is most of them. Tight bounds are what scale_to_fit and hit-testing need: fitting by hull bounds would leave the shape mysteriously inset from the box it was asked to fill. Cached; invalidated on mutation.

◆ clear()

void pulp::canvas::Path::clear ( )

Drop every verb. Keeps any allocated capacity for reuse.

◆ close()

Path & pulp::canvas::Path::close ( )

◆ contains() [1/2]

bool pulp::canvas::Path::contains ( float x,
float y,
FillRule rule = FillRule::nonzero ) const
inline

◆ contains() [2/2]

bool pulp::canvas::Path::contains ( Point2D p,
FillRule rule = FillRule::nonzero ) const

Is p inside the path under rule?

Open subpaths are treated as closed, matching how they fill.

◆ control_bounds()

Rect2D pulp::canvas::Path::control_bounds ( ) const

Cheap conservative bounds: the AABB of the control points.

Never smaller than bounds(), sometimes larger, and computed without solving anything. This is the right choice for a repaint rect (where over-estimating costs a few pixels of redraw and under-estimating is a rendering artifact) and the wrong choice for anything that must be exact.

◆ cubic_to()

Path & pulp::canvas::Path::cubic_to ( float c1x,
float c1y,
float c2x,
float c2y,
float x,
float y )

◆ current_point()

std::optional< Point2D > pulp::canvas::Path::current_point ( ) const

The last point of the path, or nullopt if there is no current point.

◆ end()

Iterator pulp::canvas::Path::end ( ) const
inline

◆ flatten()

std::vector< FlatSubpath > pulp::canvas::Path::flatten ( float tolerance = 0.25f) const

◆ from_svg_string()

Path pulp::canvas::Path::from_svg_string ( const std::string & d)
static

Parse an SVG path d string.

Supports the full grammar: M/m L/l H/h V/v C/c S/s Q/q T/t A/a Z/z, with implicit repeated coordinate sets and elliptical arcs (converted to cubics). Malformed input yields whatever prefix parsed cleanly — never throws.

◆ is_empty()

bool pulp::canvas::Path::is_empty ( ) const
inline

◆ line_to()

Path & pulp::canvas::Path::line_to ( float x,
float y )

◆ move_to()

Path & pulp::canvas::Path::move_to ( float x,
float y )

◆ operator!=()

bool pulp::canvas::Path::operator!= ( const Path & o) const
inline

◆ operator=() [1/2]

Path & pulp::canvas::Path::operator= ( const Path & )
default

◆ operator=() [2/2]

Path & pulp::canvas::Path::operator= ( Path && )
defaultnoexcept

◆ operator==()

bool pulp::canvas::Path::operator== ( const Path & o) const

Geometric equality: same verbs, same points, in the same order.

Two paths that enclose the same area by different routes are NOT equal.

◆ points_for()

constexpr int pulp::canvas::Path::points_for ( Verb v)
inlinestaticconstexpr

How many points a verb consumes.

◆ quad_to()

Path & pulp::canvas::Path::quad_to ( float cx,
float cy,
float x,
float y )

◆ replay()

template<typename Sink>
void pulp::canvas::Path::replay ( Sink & sink) const
inline

Replay this path into any sink that exposes the Canvas path-builder verbs.

Used by every backend and by ScenePath; also the simplest way for a caller to walk a path without touching the iterator.

◆ scale_to_fit()

void pulp::canvas::Path::scale_to_fit ( float x,
float y,
float w,
float h,
bool preserve_proportions )

apply_transform(transform_to_fit(...)).

◆ to_svg_string()

std::string pulp::canvas::Path::to_svg_string ( ) const

Emit a standard SVG d string using absolute commands (M/L/Q/C/Z).

Round-trips through from_svg_string.

◆ transform_to_fit()

AffineTransform pulp::canvas::Path::transform_to_fit ( float x,
float y,
float w,
float h,
bool preserve_proportions ) const

The transform that would scale this path to fit (x, y, w, h).

With preserve_proportions, the path is scaled uniformly by min(w / bounds.width, h / bounds.height) and then centerd on both axes within the target rect — so the slack on the axis that did not bind is split evenly, not dumped at one edge. (Derived empirically; see test_canvas_path.cpp, which pins the centring with a case whose scaled height is half the target's.)

Returns identity — a deliberate no-op — when the path's bounds are degenerate on either axis (a horizontal or vertical line, a single point, an empty path) or when the target rect is zero-sized. Scaling a zero-width path to a non-zero width is a division by zero; the guard is why scale_to_fit on a vertical line yields an unchanged path rather than one whose coordinates are all NaN.

◆ transformed()

Path pulp::canvas::Path::transformed ( const AffineTransform & t) const

A transformed copy; leaves this path alone.

◆ verb_count()

size_t pulp::canvas::Path::verb_count ( ) const
inline

Number of verbs.

◆ Iterator

friend class Iterator
friend

The documentation for this class was generated from the following file:
  • /home/runner/work/pulp/pulp/core/canvas/include/pulp/canvas/path.hpp