16#include "tiny_skia/Edge.h"
46 enum class Kind : std::uint8_t { MoveTo, LineTo, QuadTo, CubicTo, Close };
59 Path(std::vector<PathVerb> verbs, std::vector<Point> points)
60 : verbs_(std::move(verbs)), points_(std::move(points)) {
66 std::vector<PathVerb> verbs = {PathVerb::Move, PathVerb::Line, PathVerb::Line, PathVerb::Line,
68 std::vector<Point> points = {
Point{rect.left(), rect.top()},
Point{rect.right(), rect.top()},
69 Point{rect.right(), rect.bottom()},
70 Point{rect.left(), rect.bottom()}};
71 return Path(std::move(verbs), std::move(points));
75 [[nodiscard]]
static std::optional<Path>
fromCircle(
float cx,
float cy,
float r);
77 [[nodiscard]] std::size_t size()
const {
return verbs_.size(); }
78 [[nodiscard]]
bool empty()
const {
return verbs_.empty(); }
80 [[nodiscard]] std::span<const PathVerb> verbs()
const {
return verbs_; }
81 [[nodiscard]] std::span<const Point> points()
const {
return points_; }
84 void addVerb(PathVerb verb) { verbs_.push_back(verb); }
87 void addPoint(Point point) {
88 if (bounds_.has_value()) {
89 const auto current = bounds_.value();
91 Rect::fromLTRB(std::min(current.left(), point.x), std::min(current.top(), point.y),
92 std::max(current.right(), point.x), std::max(current.bottom(), point.y));
96 points_.push_back(point);
102 [[nodiscard]]
bool isConvex()
const {
103 if (points_.size() < 3)
return false;
107 bool hasClosed =
false;
108 for (
auto v : verbs_) {
109 if (v == PathVerb::Move) moveCount++;
110 if (v == PathVerb::Close) hasClosed =
true;
112 if (moveCount != 1 || !hasClosed)
return false;
114 const auto n = points_.size();
118 for (std::size_t i = 0; i < n; i++) {
119 const auto& p0 = points_[i];
120 const auto& p1 = points_[(i + 1) % n];
121 const auto& p2 = points_[(i + 2) % n];
123 float dx1 = p1.x - p0.x;
124 float dy1 = p1.y - p0.y;
125 float dx2 = p2.x - p1.x;
126 float dy2 = p2.y - p1.y;
128 float cross = dx1 * dy2 - dy1 * dx2;
130 if (sign < 0)
return false;
132 }
else if (cross < 0.0f) {
133 if (sign > 0)
return false;
137 if (sign == 0)
return false;
142 for (std::size_t i = 0; i < n; i++) {
143 const auto& a = points_[i];
144 const auto& b = points_[(i + 1) % n];
145 for (std::size_t j = i + 2; j < n; j++) {
146 if (i == 0 && j == n - 1)
continue;
147 const auto& c = points_[j];
148 const auto& d = points_[(j + 1) % n];
150 float d1 = (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
151 float d2 = (b.x - a.x) * (d.y - a.y) - (b.y - a.y) * (d.x - a.x);
152 float d3 = (d.x - c.x) * (a.y - c.y) - (d.y - c.y) * (a.x - c.x);
153 float d4 = (d.x - c.x) * (b.y - c.y) - (d.y - c.y) * (b.x - c.x);
154 if (((d1 > 0 && d2 < 0) || (d1 < 0 && d2 > 0)) &&
155 ((d3 > 0 && d4 < 0) || (d3 < 0 && d4 > 0))) {
165 return bounds_.value_or(
Rect::fromLTRB(0.0f, 0.0f, 0.0f, 0.0f).value());
172 for (
const auto& p : pts) {
173 if (!std::isfinite(p.x) || !std::isfinite(p.y)) {
177 return Path(verbs_, std::move(pts));
193 void recomputeBounds() {
194 if (points_.empty()) {
199 auto left = points_[0].x;
200 auto top = points_[0].y;
201 auto right = points_[0].x;
202 auto bottom = points_[0].y;
204 for (
const auto& point : points_) {
205 left = std::min(left, point.x);
206 right = std::max(right, point.x);
207 top = std::min(top, point.y);
208 bottom = std::max(bottom, point.y);
214 std::vector<PathVerb> verbs_;
215 std::vector<Point> points_;
216 std::optional<Rect> bounds_;
227class PathSegmentsIter {
229 explicit PathSegmentsIter(
const Path& path) : path_(&path) {}
231 void setAutoClose(
bool flag) { isAutoClose_ = flag; }
233 std::optional<PathSegment> next();
235 [[nodiscard]] Point lastPoint()
const {
return lastPoint_; }
236 [[nodiscard]] Point lastMoveTo()
const {
return lastMoveTo_; }
238 [[nodiscard]]
PathVerb currVerb()
const {
return path_->verbs()[verbIndex_ - 1]; }
240 [[nodiscard]] std::optional<PathVerb> nextVerb()
const {
241 if (verbIndex_ < path_->verbs().size()) {
242 return path_->verbs()[verbIndex_];
247 [[nodiscard]]
bool hasValidTangent()
const;
250 PathSegment autoClose();
253 std::size_t verbIndex_ = 0;
254 std::size_t pointsIndex_ = 0;
255 bool isAutoClose_ =
false;
256 Point lastMoveTo_ = Point::zero();
257 Point lastPoint_ = Point::zero();
Geometric primitives: Rect, IntRect, ScreenIntRect, IntSize.
PathVerb
Path segment verb (moveTo, lineTo, quadTo, cubicTo, close).
Definition Path.h:23
FillRule
Fill rule for path filling.
Definition Path.h:220
@ Winding
Non-zero winding rule.
@ EvenOdd
Even-odd (parity) rule.
LineCap
Line cap style for stroke endpoints.
Definition Path.h:32
@ Butt
Flat cap, no extension.
@ Square
Extends by half the stroke width.
Incrementally builds a Path from move/line/quad/cubic/close operations.
Definition PathBuilder.h:20
Immutable vector path — a sequence of lines, quadratics, and cubics.
Definition Path.h:56
Rect bounds() const
Axis-aligned bounding box (control-point bounds).
Definition Path.h:164
std::optional< Path > transform(const Transform &ts) const
Returns a transformed copy. Nullopt if the transform produces non-finite values.
Definition Path.h:169
std::optional< Path > dash(const StrokeDash &dash, float resScale) const
Applies a dash pattern, returning a new dashed path.
std::optional< Rect > computeTightBounds() const
Computes tight bounds by finding curve extrema (more precise than bounds()).
std::optional< Path > stroke(const Stroke &stroke, float resScale) const
Generates a filled path representing the stroke outline.
static Path fromRect(const Rect &rect)
Creates a rectangular path.
Definition Path.h:65
static std::optional< Path > fromCircle(float cx, float cy, float r)
Creates a circular path. Returns nullopt for non-positive radius.
PathBuilder clear()
Clears the path and returns a PathBuilder reusing the allocations.
Floating-point rectangle (left, top, right, bottom). All components must be finite,...
Definition Geom.h:119
static std::optional< Rect > fromLTRB(float left, float top, float right, float bottom)
Creates from edges. Returns nullopt for non-finite, empty, or inverted rects.
2D point / vector with float components.
Definition Point.h:14
Dash pattern for stroked paths.
Definition Stroke.h:24
Stroke properties for Painter::strokePath.
Definition Stroke.h:36