| Flutter Impeller |

Classes | Public Types | Public Member Functions | Friends | List of all members
impeller::Path Class Reference

Paths are lightweight objects that describe a collection of linear, quadratic, or cubic segments. These segments may be broken up by move commands, which are effectively linear commands that pick up the pen rather than continuing to draw. More...

`#include <path.h>`

## Classes
struct | Polyline
struct | PolylineContour

## Public Types
enum | ComponentType { ComponentType::kLinear, ComponentType::kQuadratic, ComponentType::kCubic, ComponentType::kContour }
template<class T >
using | Applier = std::function< void(size_t index, const T &component)>

## Public Member Functions
| Path ()
| ~Path ()
| Path (Path &&other)=default
Path | Clone () const
| Deeply clone this path and all data associated with it. More...
size_t | GetComponentCount (std::optional< ComponentType > type={}) const
FillType | GetFillType () const
bool | IsConvex () const
void | EnumerateComponents (const Applier< LinearPathComponent > &linear_applier, const Applier< QuadraticPathComponent > &quad_applier, const Applier< CubicPathComponent > &cubic_applier, const Applier< ContourComponent > &contour_applier) const
bool | GetLinearComponentAtIndex (size_t index, LinearPathComponent &linear) const
bool | GetQuadraticComponentAtIndex (size_t index, QuadraticPathComponent &quadratic) const
bool | GetCubicComponentAtIndex (size_t index, CubicPathComponent &cubic) const
bool | GetContourComponentAtIndex (size_t index, ContourComponent &contour) const
Polyline | CreatePolyline (Scalar scale, Polyline::PointBufferPtr point_buffer=std::make_unique< std::vector< Point >>(), Polyline::ReclaimPointBufferCallback reclaim=nullptr) const
std::optional< Rect > | GetBoundingBox () const
std::optional< Rect > | GetTransformedBoundingBox (const Matrix &transform) const
std::optional< std::pair< Point, Point > > | GetMinMaxCoveragePoints () const

## Friends
class | PathBuilder

## Detailed Description

Paths are lightweight objects that describe a collection of linear, quadratic, or cubic segments. These segments may be broken up by move commands, which are effectively linear commands that pick up the pen rather than continuing to draw.

All shapes supported by Impeller are paths either directly or via approximation (in the case of circles).

Paths are externally immutable once created, Creating paths must be done using a path builder.

Definition at line 55 of file path.h.

## Member Typedef Documentation

## ◆ Applier

template<class T >

using impeller::Path::Applier = std::function<void(size_t index, const T& component)>

Definition at line 148 of file path.h.

## Member Enumeration Documentation

## ◆ ComponentType

enum impeller::Path::ComponentType
| strong

Enumerator
kLinear |
kQuadratic |
kCubic |
kContour |

Definition at line 57 of file path.h.

57 {
58 kLinear,
59 kQuadratic,
60 kCubic,
61 kContour,
62 };

## Constructor & Destructor Documentation

## ◆ Path() [1/2]

impeller::Path::Path | ( |  | ) |

Definition at line 16 of file path.cc.

16 {
17 AddContourComponent({});
18 };

## ◆ ~Path()

impeller::Path::~Path | ( |  | ) |
| default

## ◆ Path() [2/2]

impeller::Path::Path | ( | Path && | other | ) |
| default

## Member Function Documentation

## ◆ Clone()

Path impeller::Path::Clone | ( |  | ) | const

Deeply clone this path and all data associated with it.

Definition at line 76 of file path.cc.

76 {
77 Path new_path = *this;
78 return new_path;
79 }

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

## ◆ CreatePolyline()

Path::Polyline impeller::Path::CreatePolyline | ( | Scalar | scale,
|  | Polyline::PointBufferPtr | point_buffer = `std::make_unique<std::vector<Point>>()`,
|  | Polyline::ReclaimPointBufferCallback | reclaim = `nullptr`
| ) |  | const

Callers must provide the scale factor for how this path will be transformed.

It is suitable to use the max basis length of the matrix used to transform the path. If the provided scale is 0, curves will revert to straight lines.

Definition at line 253 of file path.cc.

256 {
257 Polyline polyline(std::move(point_buffer), std::move(reclaim));
258
259 auto get_path_component = [this](size_t component_i) -> PathComponentVariant {
260 if (component_i >= components_.size()) {
261 return std::monostate{};
262 }
263 const auto& component = components_[component_i];
264 switch (component.type) {
265 case ComponentType::kLinear:
266 return reinterpret_cast<const LinearPathComponent*>(
267 &points_[component.index]);
268 case ComponentType::kQuadratic:
269 return reinterpret_cast<const QuadraticPathComponent*>(
270 &points_[component.index]);
271 case ComponentType::kCubic:
272 return reinterpret_cast<const CubicPathComponent*>(
273 &points_[component.index]);
274 case ComponentType::kContour:
275 return std::monostate{};
276 }
277 };
278
279 auto compute_contour_start_direction =
280 [&get_path_component](size_t current_path_component_index) {
281 size_t next_component_index = current_path_component_index + 1;
282 while (!std::holds_alternative<std::monostate>(
283 get_path_component(next_component_index))) {
284 auto next_component = get_path_component(next_component_index);
285 auto maybe_vector =
286 std::visit(PathComponentStartDirectionVisitor(), next_component);
287 if (maybe_vector.has_value()) {
288 return maybe_vector.value();
289 } else {
290 next_component_index++;
291 }
292 }
293 return Vector2(0, -1);
294 };
295
296 std::vector<PolylineContour::Component> components;
297 std::optional<size_t> previous_path_component_index;
298 auto end_contour = [&polyline, &previous_path_component_index,
299 &get_path_component, &components]() {
300 // Whenever a contour has ended, extract the exact end direction from
301 // the last component.
302 if (polyline.contours.empty()) {
303 return;
304 }
305
306 if (!previous_path_component_index.has_value()) {
307 return;
308 }
309
310 auto& contour = polyline.contours.back();
311 contour.end_direction = Vector2(0, 1);
312 contour.components = components;
313 components.clear();
314
315 size_t previous_index = previous_path_component_index.value();
316 while (!std::holds_alternative<std::monostate>(
317 get_path_component(previous_index))) {
318 auto previous_component = get_path_component(previous_index);
319 auto maybe_vector =
320 std::visit(PathComponentEndDirectionVisitor(), previous_component);
321 if (maybe_vector.has_value()) {
322 contour.end_direction = maybe_vector.value();
323 break;
324 } else {
325 if (previous_index == 0) {
326 break;
327 }
328 previous_index--;
329 }
330 }
331 };
332
333 for (size_t component_i = 0; component_i < components_.size();
334 component_i++) {
335 const auto& component = components_[component_i];
336 switch (component.type) {
337 case ComponentType::kLinear:
338 components.push_back({
339 .component_start_index = polyline.points->size() - 1,
340 .is_curve = false,
341 });
342 reinterpret_cast<const LinearPathComponent*>(&points_[component.index])
343 ->AppendPolylinePoints(*polyline.points);
344 previous_path_component_index = component_i;
345 break;
346 case ComponentType::kQuadratic:
347 components.push_back({
348 .component_start_index = polyline.points->size() - 1,
349 .is_curve = true,
350 });
351 reinterpret_cast<const QuadraticPathComponent*>(
352 &points_[component.index])
353 ->AppendPolylinePoints(scale, *polyline.points);
354 previous_path_component_index = component_i;
355 break;
356 case ComponentType::kCubic:
357 components.push_back({
358 .component_start_index = polyline.points->size() - 1,
359 .is_curve = true,
360 });
361 reinterpret_cast<const CubicPathComponent*>(&points_[component.index])
362 ->AppendPolylinePoints(scale, *polyline.points);
363 previous_path_component_index = component_i;
364 break;
365 case ComponentType::kContour:
366 if (component_i == components_.size() - 1) {
367 // If the last component is a contour, that means it's an empty
368 // contour, so skip it.
369 continue;
370 }
371 end_contour();
372
373 Vector2 start_direction = compute_contour_start_direction(component_i);
374 const auto& contour = contours_[component.index];
375 polyline.contours.push_back({.start_index = polyline.points->size(),
376 .is_closed = contour.is_closed,
377 .start_direction = start_direction,
378 .components = components});
379
380 polyline.points->push_back(contour.destination);
381 break;
382 }
383 }
384 end_contour();
385 return polyline;
386 }

References impeller::Path::Polyline::contours, kContour, kCubic, kLinear, kQuadratic, and impeller::Path::Polyline::points.

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

## ◆ EnumerateComponents()

void impeller::Path::EnumerateComponents | ( | const Applier< LinearPathComponent > & | linear_applier,
|  | const Applier< QuadraticPathComponent > & | quad_applier,
|  | const Applier< CubicPathComponent > & | cubic_applier,
|  | const Applier< ContourComponent > & | contour_applier
| ) |  | const

Definition at line 129 of file path.cc.

133 {
134 size_t currentIndex = 0;
135 for (const auto& component : components_) {
136 switch (component.type) {
137 case ComponentType::kLinear:
138 if (linear_applier) {
139 linear_applier(currentIndex,
140 LinearPathComponent(points_[component.index],
141 points_[component.index + 1]));
142 }
143 break;
144 case ComponentType::kQuadratic:
145 if (quad_applier) {
146 quad_applier(currentIndex,
147 QuadraticPathComponent(points_[component.index],
148 points_[component.index + 1],
149 points_[component.index + 2]));
150 }
151 break;
152 case ComponentType::kCubic:
153 if (cubic_applier) {
154 cubic_applier(currentIndex,
155 CubicPathComponent(points_[component.index],
156 points_[component.index + 1],
157 points_[component.index + 2],
158 points_[component.index + 3]));
159 }
160 break;
161 case ComponentType::kContour:
162 if (contour_applier) {
163 contour_applier(currentIndex, contours_[component.index]);
164 }
165 break;
166 }
167 currentIndex++;
168 }
169 }

References kContour, kCubic, kLinear, and kQuadratic.

Referenced by impeller::PathBuilder::AddPath(), and impeller::ComputeTessellator::Tessellate().

## ◆ GetBoundingBox()

std::optional< Rect > impeller::Path::GetBoundingBox | ( |  | ) | const

Definition at line 388 of file path.cc.

388 {
389 return computed_bounds_;
390 }

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

## ◆ GetComponentCount()

size_t impeller::Path::GetComponentCount | ( | std::optional< ComponentType > | type = `{}` | ) | const

Definition at line 34 of file path.cc.

34 {
35 if (!type.has_value()) {
36 return components_.size();
37 }
38 auto type_value = type.value();
39 if (type_value == ComponentType::kContour) {
40 return contours_.size();
41 }
42 size_t count = 0u;
43 for (const auto& component : components_) {
44 if (component.type == type_value) {
45 count++;
46 }
47 }
48 return count;
49 }

References kContour.

Referenced by impeller::ComputeTessellator::Tessellate().

## ◆ GetContourComponentAtIndex()

bool impeller::Path::GetContourComponentAtIndex | ( | size_t | index,
|  | ContourComponent & | contour
| ) |  | const

Definition at line 220 of file path.cc.

221 {
222 if (index >= components_.size()) {
223 return false;
224 }
225
226 if (components_[index].type != ComponentType::kContour) {
227 return false;
228 }
229
230 move = contours_[components_[index].index];
231 return true;
232 }

References kContour.

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

## ◆ GetCubicComponentAtIndex()

bool impeller::Path::GetCubicComponentAtIndex | ( | size_t | index,
|  | CubicPathComponent & | cubic
| ) |  | const

Definition at line 203 of file path.cc.

204 {
205 if (index >= components_.size()) {
206 return false;
207 }
208
209 if (components_[index].type != ComponentType::kCubic) {
210 return false;
211 }
212
213 auto point_index = components_[index].index;
214 cubic =
215 CubicPathComponent(points_[point_index], points_[point_index + 1],
216 points_[point_index + 2], points_[point_index + 3]);
217 return true;
218 }

References kCubic.

## ◆ GetFillType()

FillType impeller::Path::GetFillType | ( |  | ) | const

Definition at line 55 of file path.cc.

55 {
56 return fill_;
57 }

Referenced by impeller::Tessellator::Tessellate().

## ◆ GetLinearComponentAtIndex()

bool impeller::Path::GetLinearComponentAtIndex | ( | size_t | index,
|  | LinearPathComponent & | linear
| ) |  | const

Definition at line 171 of file path.cc.

172 {
173 if (index >= components_.size()) {
174 return false;
175 }
176
177 if (components_[index].type != ComponentType::kLinear) {
178 return false;
179 }
180
181 auto point_index = components_[index].index;
182 linear = LinearPathComponent(points_[point_index], points_[point_index + 1]);
183 return true;
184 }

References kLinear.

## ◆ GetMinMaxCoveragePoints()

std::optional< std::pair< Point, Point > > impeller::Path::GetMinMaxCoveragePoints | ( |  | ) | const

Definition at line 413 of file path.cc.

413 {
414 if (points_.empty()) {
415 return std::nullopt;
416 }
417
418 std::optional<Point> min, max;
419
420 auto clamp = [&min, &max](const Point& point) {
421 if (min.has_value()) {
422 min = min->Min(point);
423 } else {
424 min = point;
425 }
426
427 if (max.has_value()) {
428 max = max->Max(point);
429 } else {
430 max = point;
431 }
432 };
433
434 for (const auto& component : components_) {
435 switch (component.type) {
436 case ComponentType::kLinear: {
437 auto* linear = reinterpret_cast<const LinearPathComponent*>(
438 &points_[component.index]);
439 clamp(linear->p1);
440 clamp(linear->p2);
441 break;
442 }
443 case ComponentType::kQuadratic:
444 for (const auto& extrema :
445 reinterpret_cast<const QuadraticPathComponent*>(
446 &points_[component.index])
447 ->Extrema()) {
448 clamp(extrema);
449 }
450 break;
451 case ComponentType::kCubic:
452 for (const auto& extrema : reinterpret_cast<const CubicPathComponent*>(
453 &points_[component.index])
454 ->Extrema()) {
455 clamp(extrema);
456 }
457 break;
458 case ComponentType::kContour:
459 break;
460 }
461 }
462
463 if (!min.has_value() || !max.has_value()) {
464 return std::nullopt;
465 }
466
467 return std::make_pair(min.value(), max.value());
468 }

References impeller::QuadraticPathComponent::Extrema(), impeller::CubicPathComponent::Extrema(), kContour, kCubic, kLinear, and kQuadratic.

## ◆ GetQuadraticComponentAtIndex()

bool impeller::Path::GetQuadraticComponentAtIndex | ( | size_t | index,
|  | QuadraticPathComponent & | quadratic
| ) |  | const

Definition at line 186 of file path.cc.

188 {
189 if (index >= components_.size()) {
190 return false;
191 }
192
193 if (components_[index].type != ComponentType::kQuadratic) {
194 return false;
195 }
196
197 auto point_index = components_[index].index;
198 quadratic = QuadraticPathComponent(
199 points_[point_index], points_[point_index + 1], points_[point_index + 2]);
200 return true;
201 }

References kQuadratic.

## ◆ GetTransformedBoundingBox()

std::optional< Rect > impeller::Path::GetTransformedBoundingBox | ( | const Matrix & | transform | ) | const

Definition at line 404 of file path.cc.

405 {
406 auto bounds = GetBoundingBox();
407 if (!bounds.has_value()) {
408 return std::nullopt;
409 }
410 return bounds->TransformBounds(transform);
411 }

References GetBoundingBox().

## ◆ IsConvex()

bool impeller::Path::IsConvex | ( |  | ) | const

Definition at line 59 of file path.cc.

59 {
60 return convexity_ == Convexity::kConvex;
61 }

References impeller::kConvex.

## Friends And Related Function Documentation

## ◆ PathBuilder

friend class PathBuilder
| friend

Definition at line 185 of file path.h.

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

- impeller/geometry/path.h
- impeller/geometry/path.cc

impeller::Path::ComponentType::kLinear
@ kLinear
impeller::Path::ComponentType::kCubic
@ kCubic
impeller::Vector2
Point Vector2
Definition: point.h:312
impeller::Path::GetBoundingBox
std::optional< Rect > GetBoundingBox() const
Definition: path.cc:388
impeller::Path::ComponentType::kQuadratic
@ kQuadratic
impeller::Point
TPoint< Scalar > Point
Definition: point.h:308
impeller::MinMagFilter::kLinear
@ kLinear
impeller::Path::Path
Path()
Definition: path.cc:16
impeller::PathComponentVariant
std::variant< std::monostate, const LinearPathComponent *, const QuadraticPathComponent *, const CubicPathComponent * > PathComponentVariant
Definition: path_component.h:163
impeller::Convexity::kConvex
@ kConvex
impeller::Path::ComponentType::kContour
@ kContour