Flutter Impeller
impeller::PathBuilder Class Reference

#include <path_builder.h>

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...
 
PathBuilderAddRoundRect (RoundRect rect)
 
PathBuilderAddPath (const Path &path)
 

Static Public Attributes

constexpr static const Scalar kArcApproximationMagic = 0.551915024494f
 

Detailed Description

Definition at line 15 of file path_builder.h.

Constructor & Destructor Documentation

◆ PathBuilder()

impeller::PathBuilder::PathBuilder ( )

Definition at line 13 of file path_builder.cc.

13  {
14  AddContourComponent({});
15 }

◆ ~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 338 of file path_builder.cc.

341  {
342  if (sweep.radians < 0) {
343  start.radians += sweep.radians;
344  sweep.radians *= -1;
345  }
346  sweep.radians = std::min(k2Pi, sweep.radians);
347  start.radians = std::fmod(start.radians, k2Pi);
348 
349  const Point center = oval_bounds.GetCenter();
350  const Point radius = center - oval_bounds.GetOrigin();
351 
352  Vector2 p1_unit(std::cos(start.radians), std::sin(start.radians));
353 
354  if (use_center) {
355  MoveTo(center);
356  LineTo(center + p1_unit * radius);
357  } else {
358  MoveTo(center + p1_unit * radius);
359  }
360 
361  while (sweep.radians > 0) {
362  Vector2 p2_unit;
363  Scalar quadrant_angle;
364  if (sweep.radians < kPiOver2) {
365  quadrant_angle = sweep.radians;
366  p2_unit = Vector2(std::cos(start.radians + quadrant_angle),
367  std::sin(start.radians + quadrant_angle));
368  } else {
369  quadrant_angle = kPiOver2;
370  p2_unit = Vector2(-p1_unit.y, p1_unit.x);
371  }
372 
373  Vector2 arc_cp_lengths =
374  (quadrant_angle / kPiOver2) * kArcApproximationMagic * radius;
375 
376  Point p1 = center + p1_unit * radius;
377  Point p2 = center + p2_unit * radius;
378  Point cp1 = p1 + Vector2(-p1_unit.y, p1_unit.x) * arc_cp_lengths;
379  Point cp2 = p2 + Vector2(p2_unit.y, -p2_unit.x) * arc_cp_lengths;
380 
381  AddCubicComponent(p1, cp1, cp2, p2);
382  current_ = p2;
383 
384  start.radians += quadrant_angle;
385  sweep.radians -= quadrant_angle;
386  p1_unit = p2_unit;
387  }
388 
389  if (use_center) {
390  Close();
391  }
392 
393  return *this;
394 }
PathBuilder & LineTo(Point point, bool relative=false)
Insert a line from the current position to point.
Definition: path_builder.cc:64
PathBuilder & MoveTo(Point point, bool relative=false)
Definition: path_builder.cc:45
PathBuilder & Close()
Definition: path_builder.cc:52
constexpr static const Scalar kArcApproximationMagic
Definition: path_builder.h:24
constexpr float k2Pi
Definition: constants.h:29
Point Vector2
Definition: point.h:331
float Scalar
Definition: scalar.h:18
TPoint< Scalar > Point
Definition: point.h:327
constexpr float kPiOver2
Definition: constants.h:32

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::TEST(), and impeller::testing::TEST_P().

◆ AddCircle()

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

Definition at line 147 of file path_builder.cc.

147  {
148  return AddOval(Rect::MakeXYWH(c.x - r, c.y - r, 2.0f * r, 2.0f * r));
149 }
PathBuilder & AddOval(const Rect &rect)
constexpr static TRect MakeXYWH(Type x, Type y, Type width, Type height)
Definition: rect.h:136

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

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

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

123  {
124  MoveTo(p1);
125  AddCubicComponent(p1, cp1, cp2, p2);
126  return *this;
127 }

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

444  {
445  MoveTo(p1);
446  AddLinearComponent(p1, p2);
447  return *this;
448 }

References MoveTo().

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

◆ AddOval()

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

Definition at line 396 of file path_builder.cc.

396  {
397  const Point c = container.GetCenter();
398  const Point r = c - container.GetOrigin();
399  const Point m = r * kArcApproximationMagic;
400 
401  MoveTo({c.x, c.y - r.y});
402 
403  //----------------------------------------------------------------------------
404  // Top right arc.
405  //
406  AddCubicComponent({c.x, c.y - r.y}, // p1
407  {c.x + m.x, c.y - r.y}, // cp1
408  {c.x + r.x, c.y - m.y}, // cp2
409  {c.x + r.x, c.y} // p2
410  );
411 
412  //----------------------------------------------------------------------------
413  // Bottom right arc.
414  //
415  AddCubicComponent({c.x + r.x, c.y}, // p1
416  {c.x + r.x, c.y + m.y}, // cp1
417  {c.x + m.x, c.y + r.y}, // cp2
418  {c.x, c.y + r.y} // p2
419  );
420 
421  //----------------------------------------------------------------------------
422  // Bottom left arc.
423  //
424  AddCubicComponent({c.x, c.y + r.y}, // p1
425  {c.x - m.x, c.y + r.y}, // cp1
426  {c.x - r.x, c.y + m.y}, // cp2
427  {c.x - r.x, c.y} // p2
428  );
429 
430  //----------------------------------------------------------------------------
431  // Top left arc.
432  //
433  AddCubicComponent({c.x - r.x, c.y}, // p1
434  {c.x - r.x, c.y - m.y}, // cp1
435  {c.x - m.x, c.y - r.y}, // cp2
436  {c.x, c.y - r.y} // p2
437  );
438 
439  Close();
440 
441  return *this;
442 }

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

450  {
451  auto& points = prototype_.points;
452  auto& components = prototype_.components;
453 
454  points.insert(points.end(), path.data_->points.begin(),
455  path.data_->points.end());
456  components.insert(components.end(), path.data_->components.begin(),
457  path.data_->components.end());
458 
459  size_t source_offset = points.size();
460  for (auto component : path.data_->components) {
461  if (component == Path::ComponentType::kContour) {
462  current_contour_location_ = source_offset;
463  contour_count_ += 1;
464  }
465  source_offset += Path::VerbToOffset(component);
466  }
467  return *this;
468 }
static constexpr size_t VerbToOffset(Path::ComponentType verb)
Definition: path.h:62

References impeller::Path::kContour, and impeller::Path::VerbToOffset().

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

114  {
115  MoveTo(p1);
116  AddQuadraticComponent(p1, cp, p2);
117  return *this;
118 }

References MoveTo().

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

◆ AddRect()

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

Definition at line 129 of file path_builder.cc.

129  {
130  auto origin = rect.GetOrigin();
131  auto size = rect.GetSize();
132 
133  auto tl = origin;
134  auto bl = origin + Point{0.0, size.height};
135  auto br = origin + size;
136  auto tr = origin + Point{size.width, 0.0};
137 
138  MoveTo(tl);
139  LineTo(tr);
140  LineTo(br);
141  LineTo(bl);
142  Close();
143 
144  return *this;
145 }

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

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

◆ AddRoundRect()

PathBuilder & impeller::PathBuilder::AddRoundRect ( RoundRect  rect)

Definition at line 151 of file path_builder.cc.

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

References AddRect(), Close(), impeller::RoundRect::GetBounds(), impeller::RoundRect::GetRadii(), and MoveTo().

Referenced by impeller::DlDispatcherBase::clipRoundRect(), impeller::DlDispatcherBase::drawDiffRoundRect(), impeller::Canvas::DrawRoundRect(), and impeller::testing::TEST().

◆ Close()

PathBuilder & impeller::PathBuilder::Close ( )

Definition at line 52 of file path_builder.cc.

52  {
53  // If the subpath start is the same as the current position, this
54  // is an empty contour and inserting a line segment will just
55  // confuse the tessellator.
56  if (subpath_start_ != current_) {
57  LineTo(subpath_start_);
58  }
59  SetContourClosed(true);
60  AddContourComponent(current_);
61  return *this;
62 }

References LineTo().

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

◆ CopyPath()

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

Definition at line 19 of file path_builder.cc.

19  {
20  prototype_.fill = fill;
21  prototype_.single_countour =
22  current_contour_location_ == 0u ||
23  (contour_count_ == 2 &&
24  prototype_.components.back() == Path::ComponentType::kContour);
25  return Path(prototype_);
26 }

References impeller::Path::kContour.

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

105  {
106  controlPoint1 = relative ? current_ + controlPoint1 : controlPoint1;
107  controlPoint2 = relative ? current_ + controlPoint2 : controlPoint2;
108  point = relative ? current_ + point : point;
109  AddCubicComponent(current_, controlPoint1, controlPoint2, point);
110  current_ = point;
111  return *this;
112 }

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

◆ HorizontalLineTo()

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

Definition at line 71 of file path_builder.cc.

71  {
72  Point endpoint =
73  relative ? Point{current_.x + x, current_.y} : Point{x, current_.y};
74  AddLinearComponent(current_, endpoint);
75  current_ = endpoint;
76  return *this;
77 }
int32_t x

References x, 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 64 of file path_builder.cc.

64  {
65  point = relative ? current_ + point : point;
66  AddLinearComponent(current_, point);
67  current_ = point;
68  return *this;
69 }

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

◆ MoveTo()

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

Definition at line 45 of file path_builder.cc.

45  {
46  current_ = relative ? current_ + point : point;
47  subpath_start_ = current_;
48  AddContourComponent(current_);
49  return *this;
50 }

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

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

89  {
90  point = relative ? current_ + point : point;
91  controlPoint = relative ? current_ + controlPoint : controlPoint;
92  AddQuadraticComponent(current_, controlPoint, point);
93  current_ = point;
94  return *this;
95 }

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

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

40  {
41  prototype_.points.reserve(point_size);
42  prototype_.components.reserve(verb_size);
43 }

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

510  {
511  prototype_.bounds = bounds;
512  return *this;
513 }

Referenced by impeller::DlDispatcherBase::drawDiffRoundRect(), impeller::Canvas::DrawRoundRect(), and impeller::testing::TEST().

◆ SetConvexity()

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

Definition at line 97 of file path_builder.cc.

97  {
98  prototype_.convexity = value;
99  return *this;
100 }
int32_t value

References value.

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

◆ Shift()

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

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

Definition at line 470 of file path_builder.cc.

470  {
471  auto& points = prototype_.points;
472  size_t storage_offset = 0u;
473  for (const auto& component : prototype_.components) {
474  switch (component) {
476  auto* linear =
477  reinterpret_cast<LinearPathComponent*>(&points[storage_offset]);
478  linear->p1 += offset;
479  linear->p2 += offset;
480  break;
481  }
483  auto* quad =
484  reinterpret_cast<QuadraticPathComponent*>(&points[storage_offset]);
485  quad->p1 += offset;
486  quad->p2 += offset;
487  quad->cp += offset;
488  } break;
490  auto* cubic =
491  reinterpret_cast<CubicPathComponent*>(&points[storage_offset]);
492  cubic->p1 += offset;
493  cubic->p2 += offset;
494  cubic->cp1 += offset;
495  cubic->cp2 += offset;
496  } break;
498  auto* contour =
499  reinterpret_cast<ContourComponent*>(&points[storage_offset]);
500  contour->destination += offset;
501  break;
502  }
503  storage_offset += Path::VerbToOffset(component);
504  }
505 
506  prototype_.bounds.reset();
507  return *this;
508 }
SeparatedVector2 offset

References impeller::ContourComponent::destination, impeller::Path::kContour, impeller::Path::kCubic, impeller::Path::kLinear, impeller::Path::kQuadratic, offset, impeller::LinearPathComponent::p1, impeller::QuadraticPathComponent::p1, impeller::CubicPathComponent::p1, and impeller::Path::VerbToOffset().

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

◆ TakePath()

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

Definition at line 28 of file path_builder.cc.

28  {
29  prototype_.fill = fill;
30  UpdateBounds();
31  prototype_.single_countour =
32  current_contour_location_ == 0u ||
33  (contour_count_ == 2 &&
34  prototype_.components.back() == Path::ComponentType::kContour);
35  current_contour_location_ = 0u;
36  contour_count_ = 1;
37  return Path(std::move(prototype_));
38 }

References impeller::Path::kContour.

Referenced by impeller::DlDispatcherBase::drawArc(), impeller::DlDispatcherBase::drawDashedLine(), impeller::DlDispatcherBase::drawDiffRoundRect(), impeller::Canvas::DrawRoundRect(), impeller::testing::TEST(), and impeller::testing::TEST_P().

◆ VerticalLineTo()

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

Definition at line 79 of file path_builder.cc.

79  {
80  Point endpoint =
81  relative ? Point{current_.x, current_.y + y} : Point{current_.x, y};
82  AddLinearComponent(current_, endpoint);
83  current_ = endpoint;
84  return *this;
85 }

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 24 of file path_builder.h.

Referenced by AddArc(), AddOval(), and flutter::testing::TEST_P().


The documentation for this class was generated from the following files: