12 AddContourComponent({});
18 prototype_.fill = fill;
19 return Path(prototype_);
23 prototype_.fill = fill;
25 return Path(std::move(prototype_));
29 prototype_.points.reserve(point_size);
30 prototype_.components.reserve(verb_size);
34 current_ = relative ? current_ + point : point;
35 subpath_start_ = current_;
36 AddContourComponent(current_);
44 if (subpath_start_ != current_) {
47 SetContourClosed(
true);
48 AddContourComponent(current_);
53 point = relative ? current_ + point : point;
54 AddLinearComponent(current_, point);
62 AddLinearComponent(current_, endpoint);
70 AddLinearComponent(current_, endpoint);
78 point = relative ? current_ + point : point;
79 controlPoint = relative ? current_ + controlPoint : controlPoint;
80 AddQuadraticComponent(current_, controlPoint, point);
86 prototype_.convexity =
value;
94 controlPoint1 = relative ? current_ + controlPoint1 : controlPoint1;
95 controlPoint2 = relative ? current_ + controlPoint2 : controlPoint2;
96 point = relative ? current_ + point : point;
97 AddCubicComponent(current_, controlPoint1, controlPoint2, point);
104 AddQuadraticComponent(p1, cp, p2);
113 AddCubicComponent(p1, cp1, cp2, p2);
118 auto origin = rect.GetOrigin();
119 auto size = rect.GetSize();
122 auto bl = origin +
Point{0.0, size.height};
123 auto br = origin + size;
124 auto tr = origin +
Point{size.width, 0.0};
140 return radius <= 0.0 ?
AddRect(rect)
155 auto rect_origin = rect.GetOrigin();
156 auto rect_size = rect.GetSize();
166 {rect_origin.x + radii.
top_left.
x, rect_origin.y},
167 {rect_origin.x + rect_size.width - radii.
top_right.
x, rect_origin.y});
172 AddRoundedRectTopRight(rect, radii);
178 {rect_origin.x + rect_size.width, rect_origin.y + radii.
top_right.
y},
179 {rect_origin.x + rect_size.width,
185 AddRoundedRectBottomRight(rect, radii);
192 rect_origin.y + rect_size.height},
193 {rect_origin.x + radii.
bottom_left.
x, rect_origin.y + rect_size.height});
198 AddRoundedRectBottomLeft(rect, radii);
204 {rect_origin.x, rect_origin.y + rect_size.height - radii.
bottom_left.
y},
205 {rect_origin.x, rect_origin.y + radii.
top_left.
y});
210 AddRoundedRectTopLeft(rect, radii);
218 RoundingRadii radii) {
220 const auto corner = rect.GetOrigin();
221 AddCubicComponent({corner.x, corner.y + radii.top_left.y},
222 {corner.x, corner.y + radii.top_left.y - magic_top_left.y},
223 {corner.x + radii.top_left.x - magic_top_left.x, corner.y},
224 {corner.x + radii.top_left.x, corner.y});
228PathBuilder& PathBuilder::AddRoundedRectTopRight(
Rect rect,
229 RoundingRadii radii) {
231 const auto corner =
rect.GetOrigin() +
Point{
rect.GetWidth(), 0};
233 {corner.x - radii.top_right.x, corner.y},
234 {corner.x - radii.top_right.x + magic_top_right.x, corner.y},
235 {corner.x, corner.y + radii.top_right.y - magic_top_right.y},
236 {corner.x, corner.y + radii.top_right.y});
240PathBuilder& PathBuilder::AddRoundedRectBottomRight(
Rect rect,
241 RoundingRadii radii) {
243 const auto corner =
rect.GetOrigin() +
rect.GetSize();
245 {corner.x, corner.y - radii.bottom_right.y},
246 {corner.x, corner.y - radii.bottom_right.y + magic_bottom_right.y},
247 {corner.x - radii.bottom_right.x + magic_bottom_right.x, corner.y},
248 {corner.x - radii.bottom_right.x, corner.y});
252PathBuilder& PathBuilder::AddRoundedRectBottomLeft(
Rect rect,
253 RoundingRadii radii) {
255 const auto corner =
rect.GetOrigin() +
Point{0,
rect.GetHeight()};
257 {corner.x + radii.bottom_left.x, corner.y},
258 {corner.x + radii.bottom_left.x - magic_bottom_left.x, corner.y},
259 {corner.x, corner.y - radii.bottom_left.y + magic_bottom_left.y},
260 {corner.x, corner.y - radii.bottom_left.y});
264void PathBuilder::AddContourComponent(
const Point& destination,
266 auto& components = prototype_.components;
267 auto& contours = prototype_.contours;
268 if (components.size() > 0 &&
271 contours.back() = ContourComponent(destination, is_closed);
273 contours.emplace_back(ContourComponent(destination, is_closed));
276 prototype_.bounds.reset();
279void PathBuilder::AddLinearComponent(
const Point& p1,
const Point& p2) {
280 auto&
points = prototype_.points;
281 auto index =
points.size();
285 prototype_.bounds.reset();
288void PathBuilder::AddQuadraticComponent(
const Point& p1,
291 auto&
points = prototype_.points;
292 auto index =
points.size();
297 prototype_.bounds.reset();
300void PathBuilder::AddCubicComponent(
const Point& p1,
304 auto&
points = prototype_.points;
305 auto index =
points.size();
311 prototype_.bounds.reset();
314void PathBuilder::SetContourClosed(
bool is_closed) {
315 prototype_.contours.back().is_closed = is_closed;
345 quadrant_angle = sweep.
radians;
346 p2_unit =
Vector2(std::cos(
start.radians + quadrant_angle),
347 std::sin(
start.radians + quadrant_angle));
350 p2_unit =
Vector2(-p1_unit.
y, p1_unit.
x);
361 AddCubicComponent(p1, cp1, cp2, p2);
364 start.radians += quadrant_angle;
365 sweep.
radians -= quadrant_angle;
386 AddCubicComponent({c.
x, c.
y - r.
y},
387 {c.
x + m.x, c.
y - r.
y},
388 {c.
x + r.
x, c.
y - m.y},
395 AddCubicComponent({c.
x + r.
x, c.
y},
396 {c.
x + r.
x, c.
y + m.y},
397 {c.
x + m.x, c.
y + r.
y},
404 AddCubicComponent({c.
x, c.
y + r.
y},
405 {c.
x - m.x, c.
y + r.
y},
406 {c.
x - r.
x, c.
y + m.y},
413 AddCubicComponent({c.
x - r.
x, c.
y},
414 {c.
x - r.
x, c.
y - m.y},
415 {c.
x - m.x, c.
y - r.
y},
426 AddLinearComponent(p1, p2);
432 AddLinearComponent(l.p1, l.p2);
435 AddQuadraticComponent(q.p1, q.cp, q.p2);
438 AddCubicComponent(c.p1, c.cp1, c.cp2, c.p2);
441 AddContourComponent(m.destination);
443 path.EnumerateComponents(
linear, quadratic, cubic, move);
448 for (
auto& point : prototype_.points) {
451 for (
auto&
contour : prototype_.contours) {
454 prototype_.bounds.reset();
459 prototype_.bounds = bounds;
463void PathBuilder::UpdateBounds() {
464 if (!prototype_.bounds.has_value()) {
465 auto min_max = GetMinMaxCoveragePoints();
466 if (!min_max.has_value()) {
467 prototype_.bounds.reset();
470 auto min = min_max->first;
471 auto max = min_max->second;
478std::optional<std::pair<Point, Point>> PathBuilder::GetMinMaxCoveragePoints()
480 auto&
points = prototype_.points;
486 std::optional<Point>
min,
max;
489 if (
min.has_value()) {
495 if (
max.has_value()) {
502 for (
const auto& component : prototype_.components) {
503 switch (component.type) {
505 auto*
linear =
reinterpret_cast<const LinearPathComponent*
>(
506 &
points[component.index]);
512 for (
const auto& extrema :
513 reinterpret_cast<const QuadraticPathComponent*>(
520 for (
const auto& extrema : reinterpret_cast<const CubicPathComponent*>(
531 if (!
min.has_value() || !
max.has_value()) {
535 return std::make_pair(
min.value(),
max.value());
static const int points[]
static unsigned clamp(SkFixed fx, int max)
static size_t difference(size_t minuend, size_t subtrahend)
static SkScalar center(float pos0, float pos1)
PathBuilder & AddRect(Rect rect)
Path TakePath(FillType fill=FillType::kNonZero)
PathBuilder & AddArc(const Rect &oval_bounds, Radians start, Radians sweep, bool use_center=false)
PathBuilder & LineTo(Point point, bool relative=false)
Insert a line from the current position to point.
PathBuilder & MoveTo(Point point, bool relative=false)
PathBuilder & SetBounds(Rect bounds)
Set the bounding box that will be used by Path.GetBoundingBox in place of performing the computation.
void Reserve(size_t point_size, size_t verb_size)
Reserve [point_size] points and [verb_size] verbs in the underlying path buffer.
PathBuilder & AddOval(const Rect &rect)
static constexpr const Scalar kArcApproximationMagic
PathBuilder & AddCircle(const Point ¢er, Scalar radius)
PathBuilder & AddPath(const Path &path)
Path CopyPath(FillType fill=FillType::kNonZero)
PathBuilder & VerticalLineTo(Scalar y, bool relative=false)
PathBuilder & Shift(Point offset)
Transform the existing path segments and contours by the given offset.
PathBuilder & AddLine(const Point &p1, const Point &p2)
Move to point p1, then insert a line from p1 to p2.
PathBuilder & AddRoundedRect(Rect rect, RoundingRadii radii)
PathBuilder & AddQuadraticCurve(Point p1, Point cp, Point p2)
Move to point p1, then insert a quadradic curve from p1 to p2 with the control point cp.
PathBuilder & CubicCurveTo(Point controlPoint1, Point controlPoint2, Point point, bool relative=false)
Insert a cubic curve from the curren position to point using the control points controlPoint1 and con...
PathBuilder & AddCubicCurve(Point p1, Point cp1, Point cp2, Point p2)
Move to point p1, then insert a cubic curve from p1 to p2 with control points cp1 and cp2.
PathBuilder & HorizontalLineTo(Scalar x, bool relative=false)
PathBuilder & SetConvexity(Convexity value)
PathBuilder & QuadraticCurveTo(Point controlPoint, Point point, bool relative=false)
Insert a quadradic curve from the current position to point using the control point controlPoint.
Paths are lightweight objects that describe a collection of linear, quadratic, or cubic segments....
static float max(float r, float g, float b)
static float min(float r, float g, float b)
sk_sp< SkBlender > blender SkRect rect
static constexpr TRect MakeXYWH(Type x, Type y, Type width, Type height)
constexpr Point GetCenter() const
Get the center point as a |Point|.
constexpr TPoint< Type > GetOrigin() const
Returns the upper left corner of the rectangle as specified by the left/top or x/y values when it was...
static sk_sp< SkShader > linear(sk_sp< SkShader > shader)