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 313 of file path_builder.cc.

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

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::DlDispatcher::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 130 of file path_builder.cc.

130  {
131  return AddOval(Rect::MakeXYWH(c.x - r, c.y - r, 2.0f * r, 2.0f * r));
132 }

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 103 of file path_builder.cc.

106  {
107  MoveTo(p1);
108  AddCubicComponent(p1, cp1, cp2, p2);
109  return *this;
110 }

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 419 of file path_builder.cc.

419  {
420  MoveTo(p1);
421  AddLinearComponent(p1, p2);
422  return *this;
423 }

References MoveTo().

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

◆ AddOval()

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

Definition at line 371 of file path_builder.cc.

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

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 425 of file path_builder.cc.

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

References impeller::Path::EnumerateComponents().

Referenced by impeller::DlDispatcher::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 97 of file path_builder.cc.

97  {
98  MoveTo(p1);
99  AddQuadraticComponent(p1, cp, p2);
100  return *this;
101 }

References MoveTo().

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

◆ AddRect()

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

Definition at line 112 of file path_builder.cc.

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

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 145 of file path_builder.cc.

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

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 134 of file path_builder.cc.

134  {
135  return radius <= 0.0 ? AddRect(rect)
136  : AddRoundedRect(rect, RoundingRadii(radius));
137 }

References AddRect(), and AddRoundedRect().

◆ AddRoundedRect() [3/3]

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

Definition at line 139 of file path_builder.cc.

139  {
140  return radii.width <= 0 || radii.height <= 0
141  ? AddRect(rect)
142  : AddRoundedRect(rect, RoundingRadii(radii));
143 }

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  LineTo(subpath_start_);
42  SetContourClosed(true);
43  AddContourComponent(current_);
44  return *this;
45 }

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 85 of file path_builder.cc.

88  {
89  controlPoint1 = relative ? current_ + controlPoint1 : controlPoint1;
90  controlPoint2 = relative ? current_ + controlPoint2 : controlPoint2;
91  point = relative ? current_ + point : point;
92  AddCubicComponent(current_, controlPoint1, controlPoint2, point);
93  current_ = point;
94  return *this;
95 }

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 54 of file path_builder.cc.

54  {
55  Point endpoint =
56  relative ? Point{current_.x + x, current_.y} : Point{x, current_.y};
57  AddLinearComponent(current_, endpoint);
58  current_ = endpoint;
59  return *this;
60 }

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 47 of file path_builder.cc.

47  {
48  point = relative ? current_ + point : point;
49  AddLinearComponent(current_, point);
50  current_ = point;
51  return *this;
52 }

Referenced by AddArc(), AddRect(), Close(), 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::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 70 of file path_builder.cc.

72  {
73  point = relative ? current_ + point : point;
74  controlPoint = relative ? current_ + controlPoint : controlPoint;
75  AddQuadraticComponent(current_, controlPoint, point);
76  current_ = point;
77  return *this;
78 }

Referenced by impeller::testing::TEST(), 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 453 of file path_builder.cc.

453  {
454  prototype_.bounds = bounds;
455  return *this;
456 }

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

◆ SetConvexity()

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

Definition at line 80 of file path_builder.cc.

80  {
81  prototype_.convexity = value;
82  return *this;
83 }

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 442 of file path_builder.cc.

442  {
443  for (auto& point : prototype_.points) {
444  point += offset;
445  }
446  for (auto& contour : prototype_.contours) {
447  contour.destination += offset;
448  }
449  prototype_.bounds.reset();
450  return *this;
451 }

References offset.

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

◆ TakePath()

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

Definition at line 22 of file path_builder.cc.

22  {
23  prototype_.fill = fill;
24  UpdateBounds();
25  return Path(std::move(prototype_));
26 }

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

◆ VerticalLineTo()

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

Definition at line 62 of file path_builder.cc.

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

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:320
impeller::PathBuilder::AddRoundedRect
PathBuilder & AddRoundedRect(Rect rect, RoundingRadii radii)
Definition: path_builder.cc:145
impeller::PathBuilder::kArcApproximationMagic
constexpr static const Scalar kArcApproximationMagic
Definition: path_builder.h:23
impeller::PathBuilder::AddRect
PathBuilder & AddRect(Rect rect)
Definition: path_builder.cc:112
impeller::kPiOver2
constexpr float kPiOver2
Definition: constants.h:32
impeller::Point
TPoint< Scalar > Point
Definition: point.h:316
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:47
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:371
offset
Point offset
Definition: stroke_path_geometry.cc:300