#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 |
|
strong |
|
default |
|
default |
|
defaultnoexcept |
|
default |
| 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).
|
inline |
| Path & pulp::canvas::Path::add_ellipse | ( | float | cx, |
| float | cy, | ||
| float | rx, | ||
| float | ry ) |
| 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.
| 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.
Closed polygon through count points. Fewer than 2 points draws nothing.
| Path & pulp::canvas::Path::add_rect | ( | float | x, |
| float | y, | ||
| float | w, | ||
| float | h ) |
| 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.
| 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.
| void pulp::canvas::Path::apply_transform | ( | const AffineTransform & | t | ) |
Transform every point in place.
| 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.
|
inline |
| 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.
| void pulp::canvas::Path::clear | ( | ) |
Drop every verb. Keeps any allocated capacity for reuse.
| Path & pulp::canvas::Path::close | ( | ) |
|
inline |
| 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.
| 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.
| Path & pulp::canvas::Path::cubic_to | ( | float | c1x, |
| float | c1y, | ||
| float | c2x, | ||
| float | c2y, | ||
| float | x, | ||
| float | y ) |
| std::optional< Point2D > pulp::canvas::Path::current_point | ( | ) | const |
The last point of the path, or nullopt if there is no current point.
|
inline |
| std::vector< FlatSubpath > pulp::canvas::Path::flatten | ( | float | tolerance = 0.25f | ) | const |
|
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.
|
inline |
| Path & pulp::canvas::Path::line_to | ( | float | x, |
| float | y ) |
| Path & pulp::canvas::Path::move_to | ( | float | x, |
| float | y ) |
|
inline |
| 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.
|
inlinestaticconstexpr |
How many points a verb consumes.
| Path & pulp::canvas::Path::quad_to | ( | float | cx, |
| float | cy, | ||
| float | x, | ||
| float | y ) |
|
inline |
| void pulp::canvas::Path::scale_to_fit | ( | float | x, |
| float | y, | ||
| float | w, | ||
| float | h, | ||
| bool | preserve_proportions ) |
apply_transform(transform_to_fit(...)).
| 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.
| 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.
| Path pulp::canvas::Path::transformed | ( | const AffineTransform & | t | ) | const |
A transformed copy; leaves this path alone.
|
inline |
Number of verbs.
|
friend |