Flutter Impeller
impeller::PathBuilder Class Reference

#include <path_builder.h>

Classes

struct  RoundingRadii
 

Public Member Functions

 PathBuilder ()
 
 ~PathBuilder ()
 
Path CopyPath (FillType fill=FillType::kNonZero)
 
Path TakePath (FillType fill=FillType::kNonZero)
 
void Reserve (size_t point_size, size_t verb_size)
 Reserve [point_size] points and [verb_size] verbs in the underlying path buffer. More...
 
PathBuilderSetConvexity (Convexity value)
 
PathBuilderMoveTo (Point point, bool relative=false)
 
PathBuilderClose ()
 
PathBuilderLineTo (Point point, bool relative=false)
 Insert a line from the current position to point. More...
 
PathBuilderHorizontalLineTo (Scalar x, bool relative=false)
 
PathBuilderVerticalLineTo (Scalar y, bool relative=false)
 
PathBuilderQuadraticCurveTo (Point controlPoint, Point point, bool relative=false)
 Insert a quadradic curve from the current position to point using the control point controlPoint. More...
 
PathBuilderCubicCurveTo (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 controlPoint2. More...
 
PathBuilderAddRect (Rect rect)
 
PathBuilderAddCircle (const Point &center, Scalar radius)
 
PathBuilderAddArc (const Rect &oval_bounds, Radians start, Radians sweep, bool use_center=false)
 
PathBuilderAddOval (const Rect &rect)
 
PathBuilderAddLine (const Point &p1, const Point &p2)
 Move to point p1, then insert a line from p1 to p2. More...
 
PathBuilderAddQuadraticCurve (Point p1, Point cp, Point p2)
 Move to point p1, then insert a quadradic curve from p1 to p2 with the control point cp. More...
 
PathBuilderAddCubicCurve (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. More...
 
PathBuilderShift (Point offset)
 Transform the existing path segments and contours by the given offset. More...
 
PathBuilderSetBounds (Rect bounds)
 Set the bounding box that will be used by Path.GetBoundingBox in place of performing the computation. More...
 
PathBuilderAddRoundedRect (Rect rect, RoundingRadii radii)
 
PathBuilderAddRoundedRect (Rect rect, Size radii)
 
PathBuilderAddRoundedRect (Rect rect, Scalar radius)
 
PathBuilderAddPath (const Path &path)
 

Static Public Attributes

constexpr static const Scalar kArcApproximationMagic = 0.551915024494f
 

Detailed Description

Definition at line 14 of file path_builder.h.

Constructor & Destructor Documentation

◆ PathBuilder()

impeller::PathBuilder::PathBuilder ( )

Definition at line 11 of file path_builder.cc.

11  {
12  AddContourComponent({});
13 }

◆ ~PathBuilder()

impeller::PathBuilder::~PathBuilder ( )
default

Member Function Documentation

◆ AddArc()

PathBuilder & impeller::PathBuilder::AddArc ( const Rect oval_bounds,
Radians  start,
Radians  sweep,
bool  use_center = false 
)

Definition at line 318 of file path_builder.cc.

321  {
322  if (sweep.radians < 0) {
323  start.radians += sweep.radians;
324  sweep.radians *= -1;
325  }
326  sweep.radians = std::min(k2Pi, sweep.radians);
327  start.radians = std::fmod(start.radians, k2Pi);
328 
329  const Point center = oval_bounds.GetCenter();
330  const Point radius = center - oval_bounds.GetOrigin();
331 
332  Vector2 p1_unit(std::cos(start.radians), std::sin(start.radians));
333 
334  if (use_center) {
335  MoveTo(center);
336  LineTo(center + p1_unit * radius);
337  } else {
338  MoveTo(center + p1_unit * radius);
339  }
340 
341  while (sweep.radians > 0) {
342  Vector2 p2_unit;
343  Scalar quadrant_angle;
344  if (sweep.radians < kPiOver2) {
345  quadrant_angle = sweep.radians;
346  p2_unit = Vector2(std::cos(start.radians + quadrant_angle),
347  std::sin(start.radians + quadrant_angle));
348  } else {
349  quadrant_angle = kPiOver2;
350  p2_unit = Vector2(-p1_unit.y, p1_unit.x);
351  }
352 
353  Vector2 arc_cp_lengths =
354  (quadrant_angle / kPiOver2) * kArcApproximationMagic * radius;
355 
356  Point p1 = center + p1_unit * radius;
357  Point p2 = center + p2_unit * radius;
358  Point cp1 = p1 + Vector2(-p1_unit.y, p1_unit.x) * arc_cp_lengths;
359  Point cp2 = p2 + Vector2(p2_unit.y, -p2_unit.x) * arc_cp_lengths;
360 
361  AddCubicComponent(p1, cp1, cp2, p2);
362  current_ = p2;
363 
364  start.radians += quadrant_angle;
365  sweep.radians -= quadrant_angle;
366  p1_unit = p2_unit;
367  }
368 
369  if (use_center) {
370  Close();
371  }
372 
373  return *this;
374 }

References Close(), impeller::TRect< T >::GetCenter(), impeller::TRect< T >::GetOrigin(), impeller::k2Pi, kArcApproximationMagic, impeller::kPiOver2, LineTo(), MoveTo(), impeller::Radians::radians, impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

Referenced by impeller::DlDispatcherBase::drawArc(), impeller::testing::MaskBlurVariantTest(), impeller::testing::TEST(), and impeller::testing::TEST_P().

◆ AddCircle()

PathBuilder & impeller::PathBuilder::AddCircle ( const Point center,
Scalar  radius 
)

Definition at line 135 of file path_builder.cc.

135  {
136  return AddOval(Rect::MakeXYWH(c.x - r, c.y - r, 2.0f * r, 2.0f * r));
137 }

References AddOval(), impeller::TRect< Scalar >::MakeXYWH(), impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

Referenced by impeller::testing::TEST(), and impeller::testing::TEST_P().

◆ AddCubicCurve()

PathBuilder & impeller::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.

Definition at line 108 of file path_builder.cc.

111  {
112  MoveTo(p1);
113  AddCubicComponent(p1, cp1, cp2, p2);
114  return *this;
115 }

References MoveTo().

Referenced by impeller::testing::TEST(), and impeller::testing::TEST_P().

◆ AddLine()

PathBuilder & impeller::PathBuilder::AddLine ( const Point p1,
const Point p2 
)

Move to point p1, then insert a line from p1 to p2.

Definition at line 424 of file path_builder.cc.

424  {
425  MoveTo(p1);
426  AddLinearComponent(p1, p2);
427  return *this;
428 }

References MoveTo().

Referenced by impeller::testing::TEST(), and impeller::testing::TEST_P().

◆ AddOval()

PathBuilder & impeller::PathBuilder::AddOval ( const Rect rect)

Definition at line 376 of file path_builder.cc.

376  {
377  const Point c = container.GetCenter();
378  const Point r = c - container.GetOrigin();
379  const Point m = r * kArcApproximationMagic;
380 
381  MoveTo({c.x, c.y - r.y});
382 
383  //----------------------------------------------------------------------------
384  // Top right arc.
385  //
386  AddCubicComponent({c.x, c.y - r.y}, // p1
387  {c.x + m.x, c.y - r.y}, // cp1
388  {c.x + r.x, c.y - m.y}, // cp2
389  {c.x + r.x, c.y} // p2
390  );
391 
392  //----------------------------------------------------------------------------
393  // Bottom right arc.
394  //
395  AddCubicComponent({c.x + r.x, c.y}, // p1
396  {c.x + r.x, c.y + m.y}, // cp1
397  {c.x + m.x, c.y + r.y}, // cp2
398  {c.x, c.y + r.y} // p2
399  );
400 
401  //----------------------------------------------------------------------------
402  // Bottom left arc.
403  //
404  AddCubicComponent({c.x, c.y + r.y}, // p1
405  {c.x - m.x, c.y + r.y}, // cp1
406  {c.x - r.x, c.y + m.y}, // cp2
407  {c.x - r.x, c.y} // p2
408  );
409 
410  //----------------------------------------------------------------------------
411  // Top left arc.
412  //
413  AddCubicComponent({c.x - r.x, c.y}, // p1
414  {c.x - r.x, c.y - m.y}, // cp1
415  {c.x - m.x, c.y - r.y}, // cp2
416  {c.x, c.y - r.y} // p2
417  );
418 
419  Close();
420 
421  return *this;
422 }

References Close(), impeller::TRect< T >::GetCenter(), impeller::TRect< T >::GetOrigin(), kArcApproximationMagic, MoveTo(), impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

Referenced by AddCircle(), impeller::Canvas::DrawOval(), and impeller::testing::TEST().

◆ AddPath()

PathBuilder & impeller::PathBuilder::AddPath ( const Path path)

Definition at line 430 of file path_builder.cc.

430  {
431  auto linear = [&](size_t index, const LinearPathComponent& l) {
432  AddLinearComponent(l.p1, l.p2);
433  };
434  auto quadratic = [&](size_t index, const QuadraticPathComponent& q) {
435  AddQuadraticComponent(q.p1, q.cp, q.p2);
436  };
437  auto cubic = [&](size_t index, const CubicPathComponent& c) {
438  AddCubicComponent(c.p1, c.cp1, c.cp2, c.p2);
439  };
440  auto move = [&](size_t index, const ContourComponent& m) {
441  AddContourComponent(m.destination);
442  };
443  path.EnumerateComponents(linear, quadratic, cubic, move);
444  return *this;
445 }

References impeller::Path::EnumerateComponents().

Referenced by impeller::DlDispatcherBase::drawDRRect().

◆ AddQuadraticCurve()

PathBuilder & impeller::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.

Definition at line 102 of file path_builder.cc.

102  {
103  MoveTo(p1);
104  AddQuadraticComponent(p1, cp, p2);
105  return *this;
106 }

References MoveTo().

Referenced by impeller::testing::TEST().

◆ AddRect()

PathBuilder & impeller::PathBuilder::AddRect ( Rect  rect)

Definition at line 117 of file path_builder.cc.

117  {
118  auto origin = rect.GetOrigin();
119  auto size = rect.GetSize();
120 
121  auto tl = origin;
122  auto bl = origin + Point{0.0, size.height};
123  auto br = origin + size;
124  auto tr = origin + Point{size.width, 0.0};
125 
126  MoveTo(tl);
127  LineTo(tr);
128  LineTo(br);
129  LineTo(bl);
130  Close();
131 
132  return *this;
133 }

References Close(), impeller::TRect< T >::GetOrigin(), impeller::TRect< T >::GetSize(), LineTo(), and MoveTo().

Referenced by AddRoundedRect(), impeller::testing::CreatePassWithRectPath(), impeller::Canvas::DrawRect(), impeller::testing::TEST(), and impeller::testing::TEST_P().

◆ AddRoundedRect() [1/3]

PathBuilder & impeller::PathBuilder::AddRoundedRect ( Rect  rect,
RoundingRadii  radii 
)

Definition at line 150 of file path_builder.cc.

150  {
151  if (radii.AreAllZero()) {
152  return AddRect(rect);
153  }
154 
155  auto rect_origin = rect.GetOrigin();
156  auto rect_size = rect.GetSize();
157 
158  current_ = rect_origin + Point{radii.top_left.x, 0.0};
159 
160  MoveTo({rect_origin.x + radii.top_left.x, rect_origin.y});
161 
162  //----------------------------------------------------------------------------
163  // Top line.
164  //
165  AddLinearComponent(
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});
168 
169  //----------------------------------------------------------------------------
170  // Top right arc.
171  //
172  AddRoundedRectTopRight(rect, radii);
173 
174  //----------------------------------------------------------------------------
175  // Right line.
176  //
177  AddLinearComponent(
178  {rect_origin.x + rect_size.width, rect_origin.y + radii.top_right.y},
179  {rect_origin.x + rect_size.width,
180  rect_origin.y + rect_size.height - radii.bottom_right.y});
181 
182  //----------------------------------------------------------------------------
183  // Bottom right arc.
184  //
185  AddRoundedRectBottomRight(rect, radii);
186 
187  //----------------------------------------------------------------------------
188  // Bottom line.
189  //
190  AddLinearComponent(
191  {rect_origin.x + rect_size.width - radii.bottom_right.x,
192  rect_origin.y + rect_size.height},
193  {rect_origin.x + radii.bottom_left.x, rect_origin.y + rect_size.height});
194 
195  //----------------------------------------------------------------------------
196  // Bottom left arc.
197  //
198  AddRoundedRectBottomLeft(rect, radii);
199 
200  //----------------------------------------------------------------------------
201  // Left line.
202  //
203  AddLinearComponent(
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});
206 
207  //----------------------------------------------------------------------------
208  // Top left arc.
209  //
210  AddRoundedRectTopLeft(rect, radii);
211 
212  Close();
213 
214  return *this;
215 }

References AddRect(), impeller::PathBuilder::RoundingRadii::AreAllZero(), impeller::PathBuilder::RoundingRadii::bottom_left, impeller::PathBuilder::RoundingRadii::bottom_right, Close(), impeller::TRect< T >::GetOrigin(), impeller::TRect< T >::GetSize(), MoveTo(), impeller::PathBuilder::RoundingRadii::top_left, impeller::PathBuilder::RoundingRadii::top_right, impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

Referenced by AddRoundedRect(), impeller::Canvas::DrawRRect(), impeller::testing::TEST(), impeller::testing::TEST_P(), and impeller::skia_conversions::ToPath().

◆ AddRoundedRect() [2/3]

PathBuilder & impeller::PathBuilder::AddRoundedRect ( Rect  rect,
Scalar  radius 
)

Definition at line 139 of file path_builder.cc.

139  {
140  return radius <= 0.0 ? AddRect(rect)
141  : AddRoundedRect(rect, RoundingRadii(radius));
142 }

References AddRect(), and AddRoundedRect().

◆ AddRoundedRect() [3/3]

PathBuilder & impeller::PathBuilder::AddRoundedRect ( Rect  rect,
Size  radii 
)

Definition at line 144 of file path_builder.cc.

144  {
145  return radii.width <= 0 || radii.height <= 0
146  ? AddRect(rect)
147  : AddRoundedRect(rect, RoundingRadii(radii));
148 }

References AddRect(), AddRoundedRect(), impeller::TSize< T >::height, and impeller::TSize< T >::width.

◆ Close()

PathBuilder & impeller::PathBuilder::Close ( )

Definition at line 40 of file path_builder.cc.

40  {
41  // If the subpath start is the same as the current position, this
42  // is an empty contour and inserting a line segment will just
43  // confuse the tessellator.
44  if (subpath_start_ != current_) {
45  LineTo(subpath_start_);
46  }
47  SetContourClosed(true);
48  AddContourComponent(current_);
49  return *this;
50 }

References LineTo().

Referenced by AddArc(), AddOval(), AddRect(), AddRoundedRect(), impeller::Close(), impeller::testing::TEST(), impeller::testing::TEST_P(), and impeller::skia_conversions::ToPath().

◆ CopyPath()

Path impeller::PathBuilder::CopyPath ( FillType  fill = FillType::kNonZero)

Definition at line 17 of file path_builder.cc.

17  {
18  prototype_.fill = fill;
19  return Path(prototype_);
20 }

Referenced by impeller::Tessellate(), and impeller::testing::TEST().

◆ CubicCurveTo()

PathBuilder & impeller::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 controlPoint2.

If relative is true the point, controlPoint1, and controlPoint2 are relative to current location.

Definition at line 90 of file path_builder.cc.

93  {
94  controlPoint1 = relative ? current_ + controlPoint1 : controlPoint1;
95  controlPoint2 = relative ? current_ + controlPoint2 : controlPoint2;
96  point = relative ? current_ + point : point;
97  AddCubicComponent(current_, controlPoint1, controlPoint2, point);
98  current_ = point;
99  return *this;
100 }

Referenced by impeller::CubicTo(), impeller::testing::TEST(), and impeller::skia_conversions::ToPath().

◆ HorizontalLineTo()

PathBuilder & impeller::PathBuilder::HorizontalLineTo ( Scalar  x,
bool  relative = false 
)

Definition at line 59 of file path_builder.cc.

59  {
60  Point endpoint =
61  relative ? Point{current_.x + x, current_.y} : Point{x, current_.y};
62  AddLinearComponent(current_, endpoint);
63  current_ = endpoint;
64  return *this;
65 }

References impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

Referenced by impeller::testing::TEST().

◆ LineTo()

PathBuilder & impeller::PathBuilder::LineTo ( Point  point,
bool  relative = false 
)

Insert a line from the current position to point.

If relative is true, then point is relative to the current location.

Definition at line 52 of file path_builder.cc.

52  {
53  point = relative ? current_ + point : point;
54  AddLinearComponent(current_, point);
55  current_ = point;
56  return *this;
57 }

Referenced by AddArc(), AddRect(), Close(), impeller::DlDispatcherBase::drawDashedLine(), impeller::LineTo(), impeller::testing::TEST(), impeller::testing::TEST_P(), and impeller::skia_conversions::ToPath().

◆ MoveTo()

PathBuilder & impeller::PathBuilder::MoveTo ( Point  point,
bool  relative = false 
)

Definition at line 33 of file path_builder.cc.

33  {
34  current_ = relative ? current_ + point : point;
35  subpath_start_ = current_;
36  AddContourComponent(current_);
37  return *this;
38 }

Referenced by AddArc(), AddCubicCurve(), AddLine(), AddOval(), AddQuadraticCurve(), AddRect(), AddRoundedRect(), impeller::DlDispatcherBase::drawDashedLine(), impeller::testing::MaskBlurVariantTest(), impeller::MoveTo(), impeller::testing::TEST(), impeller::testing::TEST_P(), and impeller::skia_conversions::ToPath().

◆ QuadraticCurveTo()

PathBuilder & impeller::PathBuilder::QuadraticCurveTo ( Point  controlPoint,
Point  point,
bool  relative = false 
)

Insert a quadradic curve from the current position to point using the control point controlPoint.

If relative is true the point and controlPoint are relative to current location.

Definition at line 75 of file path_builder.cc.

77  {
78  point = relative ? current_ + point : point;
79  controlPoint = relative ? current_ + controlPoint : controlPoint;
80  AddQuadraticComponent(current_, controlPoint, point);
81  current_ = point;
82  return *this;
83 }

Referenced by impeller::testing::TEST(), impeller::testing::TEST_P(), and impeller::skia_conversions::ToPath().

◆ Reserve()

void impeller::PathBuilder::Reserve ( size_t  point_size,
size_t  verb_size 
)

Reserve [point_size] points and [verb_size] verbs in the underlying path buffer.

Definition at line 28 of file path_builder.cc.

28  {
29  prototype_.points.reserve(point_size);
30  prototype_.components.reserve(verb_size);
31 }

Referenced by impeller::skia_conversions::ToPath().

◆ SetBounds()

PathBuilder & impeller::PathBuilder::SetBounds ( Rect  bounds)

Set the bounding box that will be used by Path.GetBoundingBox in place of performing the computation.

   When Impeller recieves Skia Path objects, many of these already
   have computed bounds. This method is used to avoid needlessly
   recomputing these bounds. 

Definition at line 458 of file path_builder.cc.

458  {
459  prototype_.bounds = bounds;
460  return *this;
461 }

Referenced by impeller::Canvas::DrawRRect(), impeller::testing::TEST(), and impeller::skia_conversions::ToPath().

◆ SetConvexity()

PathBuilder & impeller::PathBuilder::SetConvexity ( Convexity  value)

Definition at line 85 of file path_builder.cc.

85  {
86  prototype_.convexity = value;
87  return *this;
88 }

Referenced by impeller::Canvas::DrawRRect(), impeller::testing::TEST(), impeller::testing::TEST_P(), and impeller::skia_conversions::ToPath().

◆ Shift()

PathBuilder & impeller::PathBuilder::Shift ( Point  offset)

Transform the existing path segments and contours by the given offset.

Definition at line 447 of file path_builder.cc.

447  {
448  for (auto& point : prototype_.points) {
449  point += offset;
450  }
451  for (auto& contour : prototype_.contours) {
452  contour.destination += offset;
453  }
454  prototype_.bounds.reset();
455  return *this;
456 }

References offset.

Referenced by impeller::testing::TEST(), and impeller::skia_conversions::ToPath().

◆ TakePath()

Path impeller::PathBuilder::TakePath ( FillType  fill = FillType::kNonZero)

◆ VerticalLineTo()

PathBuilder & impeller::PathBuilder::VerticalLineTo ( Scalar  y,
bool  relative = false 
)

Definition at line 67 of file path_builder.cc.

67  {
68  Point endpoint =
69  relative ? Point{current_.x, current_.y + y} : Point{current_.x, y};
70  AddLinearComponent(current_, endpoint);
71  current_ = endpoint;
72  return *this;
73 }

References impeller::TPoint< T >::x, and impeller::TPoint< T >::y.

Referenced by impeller::testing::TEST().

Member Data Documentation

◆ kArcApproximationMagic

constexpr static const Scalar impeller::PathBuilder::kArcApproximationMagic = 0.551915024494f
staticconstexpr

Used for approximating quarter circle arcs with cubic curves. This is the control point distance which results in the smallest possible unit circle integration for a right angle arc. It can be used to approximate arcs less than 90 degrees to great effect by simply reducing it proportionally to the angle. However, accuracy rapidly diminishes if magnified for obtuse angle arcs, and so multiple cubic curves should be used when approximating arcs greater than 90 degrees.

Definition at line 23 of file path_builder.h.

Referenced by AddArc(), and AddOval().


The documentation for this class was generated from the following files:
impeller::TPoint::y
Type y
Definition: point.h:31
impeller::Scalar
float Scalar
Definition: scalar.h:18
impeller::TRect< Scalar >::MakeXYWH
constexpr static TRect MakeXYWH(Type x, Type y, Type width, Type height)
Definition: rect.h:136
impeller::Vector2
Point Vector2
Definition: point.h:326
impeller::PathBuilder::AddRoundedRect
PathBuilder & AddRoundedRect(Rect rect, RoundingRadii radii)
Definition: path_builder.cc:150
impeller::PathBuilder::kArcApproximationMagic
constexpr static const Scalar kArcApproximationMagic
Definition: path_builder.h:23
offset
SeparatedVector2 offset
Definition: stroke_path_geometry.cc:311
impeller::PathBuilder::AddRect
PathBuilder & AddRect(Rect rect)
Definition: path_builder.cc:117
impeller::kPiOver2
constexpr float kPiOver2
Definition: constants.h:32
impeller::Point
TPoint< Scalar > Point
Definition: point.h:322
impeller::k2Pi
constexpr float k2Pi
Definition: constants.h:29
impeller::PathBuilder::LineTo
PathBuilder & LineTo(Point point, bool relative=false)
Insert a line from the current position to point.
Definition: path_builder.cc:52
impeller::TPoint::x
Type x
Definition: point.h:30
impeller::PathBuilder::Close
PathBuilder & Close()
Definition: path_builder.cc:40
impeller::PathBuilder::MoveTo
PathBuilder & MoveTo(Point point, bool relative=false)
Definition: path_builder.cc:33
impeller::PathBuilder::AddOval
PathBuilder & AddOval(const Rect &rect)
Definition: path_builder.cc:376