Flutter Impeller
path.h
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef FLUTTER_IMPELLER_GEOMETRY_PATH_H_
6 #define FLUTTER_IMPELLER_GEOMETRY_PATH_H_
7 
8 #include <functional>
9 #include <optional>
10 #include <tuple>
11 #include <vector>
12 
14 
15 namespace impeller {
16 
17 enum class Cap {
18  kButt,
19  kRound,
20  kSquare,
21 };
22 
23 enum class Join {
24  kMiter,
25  kRound,
26  kBevel,
27 };
28 
29 enum class FillType {
30  kNonZero, // The default winding order.
31  kOdd,
32 };
33 
34 enum class Convexity {
35  kUnknown,
36  kConvex,
37 };
38 
39 //------------------------------------------------------------------------------
40 /// @brief Paths are lightweight objects that describe a collection of
41 /// linear, quadratic, or cubic segments. These segments may be
42 /// broken up by move commands, which are effectively linear
43 /// commands that pick up the pen rather than continuing to draw.
44 ///
45 /// All shapes supported by Impeller are paths either directly or
46 /// via approximation (in the case of circles).
47 ///
48 /// Paths are externally immutable once created, Creating paths must
49 /// be done using a path builder.
50 ///
51 class Path {
52  public:
53  enum class ComponentType {
54  kLinear,
55  kQuadratic,
56  kCubic,
57  kContour,
58  };
59 
60  struct PolylineContour {
61  struct Component {
63  /// Denotes whether this component is a curve.
64  ///
65  /// This is set to true when this component is generated from
66  /// QuadraticComponent or CubicPathComponent.
67  bool is_curve;
68  };
69  /// Index that denotes the first point of this contour.
70  size_t start_index;
71 
72  /// Denotes whether the last point of this contour is connected to the first
73  /// point of this contour or not.
74  bool is_closed;
75 
76  /// The direction of the contour's start cap.
78  /// The direction of the contour's end cap.
80 
81  /// Distinct components in this contour.
82  ///
83  /// If this contour is generated from multiple path components, each
84  /// path component forms a component in this vector.
85  std::vector<Component> components;
86  };
87 
88  /// One or more contours represented as a series of points and indices in
89  /// the point vector representing the start of a new contour.
90  ///
91  /// Polylines are ephemeral and meant to be used by the tessellator. They do
92  /// not allocate their own point vectors to allow for optimizations around
93  /// allocation and reuse of arenas.
94  struct Polyline {
95  /// The signature of a method called when it is safe to reclaim the point
96  /// buffer provided to the constructor of this object.
97  using PointBufferPtr = std::unique_ptr<std::vector<Point>>;
98  using ReclaimPointBufferCallback = std::function<void(PointBufferPtr)>;
99 
100  /// The buffer will be cleared and returned at the destruction of this
101  /// polyline.
102  Polyline(PointBufferPtr point_buffer, ReclaimPointBufferCallback reclaim);
103 
104  Polyline(Polyline&& other);
105  ~Polyline();
106 
107  /// Points in the polyline, which may represent multiple contours specified
108  /// by indices in |contours|.
110 
111  Point& GetPoint(size_t index) const { return (*points)[index]; }
112 
113  /// Contours are disconnected pieces of a polyline, such as when a MoveTo
114  /// was issued on a PathBuilder.
115  std::vector<PolylineContour> contours;
116 
117  /// Convenience method to compute the start (inclusive) and end (exclusive)
118  /// point of the given contour index.
119  ///
120  /// The contour_index parameter is clamped to contours.size().
121  std::tuple<size_t, size_t> GetContourPointBounds(
122  size_t contour_index) const;
123 
124  private:
125  ReclaimPointBufferCallback reclaim_points_;
126  };
127 
128  Path();
129 
130  ~Path();
131 
132  size_t GetComponentCount(std::optional<ComponentType> type = {}) const;
133 
134  FillType GetFillType() const;
135 
136  bool IsConvex() const;
137 
138  bool IsEmpty() const;
139 
140  template <class T>
141  using Applier = std::function<void(size_t index, const T& component)>;
142  void EnumerateComponents(
143  const Applier<LinearPathComponent>& linear_applier,
144  const Applier<QuadraticPathComponent>& quad_applier,
145  const Applier<CubicPathComponent>& cubic_applier,
146  const Applier<ContourComponent>& contour_applier) const;
147 
148  bool GetLinearComponentAtIndex(size_t index,
149  LinearPathComponent& linear) const;
150 
151  bool GetQuadraticComponentAtIndex(size_t index,
152  QuadraticPathComponent& quadratic) const;
153 
154  bool GetCubicComponentAtIndex(size_t index, CubicPathComponent& cubic) const;
155 
156  bool GetContourComponentAtIndex(size_t index,
157  ContourComponent& contour) const;
158 
159  /// Callers must provide the scale factor for how this path will be
160  /// transformed.
161  ///
162  /// It is suitable to use the max basis length of the matrix used to transform
163  /// the path. If the provided scale is 0, curves will revert to straight
164  /// lines.
166  Scalar scale,
167  Polyline::PointBufferPtr point_buffer =
168  std::make_unique<std::vector<Point>>(),
169  Polyline::ReclaimPointBufferCallback reclaim = nullptr) const;
170 
171  std::optional<Rect> GetBoundingBox() const;
172 
173  std::optional<Rect> GetTransformedBoundingBox(const Matrix& transform) const;
174 
175  private:
176  friend class PathBuilder;
177 
178  struct ComponentIndexPair {
180  size_t index = 0;
181 
182  ComponentIndexPair() {}
183 
184  ComponentIndexPair(ComponentType a_type, size_t a_index)
185  : type(a_type), index(a_index) {}
186  };
187 
188  // All of the data for the path is stored in this structure which is
189  // held by a shared_ptr. Since they all share the structure, the
190  // copy constructor for Path is very cheap and we don't need to deal
191  // with shared pointers for Path fields and method arguments.
192  //
193  // PathBuilder also uses this structure to accumulate the path data
194  // but the Path constructor used in |TakePath()| will clone the
195  // structure to prevent sharing and future modifications within the
196  // builder from affecting the existing taken paths.
197  struct Data {
198  Data() = default;
199 
200  Data(Data&& other) = default;
201 
202  Data(const Data& other) = default;
203 
204  ~Data() = default;
205 
207  Convexity convexity = Convexity::kUnknown;
208  std::vector<ComponentIndexPair> components;
209  std::vector<Point> points;
210  std::vector<ContourComponent> contours;
211 
212  std::optional<Rect> bounds;
213  };
214 
215  explicit Path(Data data);
216 
217  std::shared_ptr<const Data> data_;
218 };
219 
220 static_assert(sizeof(Path) == sizeof(std::shared_ptr<struct Anonymous>));
221 
222 } // namespace impeller
223 
224 #endif // FLUTTER_IMPELLER_GEOMETRY_PATH_H_
impeller::Cap::kRound
@ kRound
impeller::Cap::kSquare
@ kSquare
impeller::LinearPathComponent
Definition: path_component.h:29
impeller::Path::GetQuadraticComponentAtIndex
bool GetQuadraticComponentAtIndex(size_t index, QuadraticPathComponent &quadratic) const
Definition: path.cc:124
impeller::Scalar
float Scalar
Definition: scalar.h:18
impeller::Path::PolylineContour
Definition: path.h:60
impeller::FillType::kOdd
@ kOdd
impeller::Path::ComponentType::kLinear
@ kLinear
impeller::Path::PolylineContour::start_index
size_t start_index
Index that denotes the first point of this contour.
Definition: path.h:70
impeller::Path::PolylineContour::components
std::vector< Component > components
Definition: path.h:85
impeller::Path::ComponentType::kCubic
@ kCubic
impeller::PathBuilder
Definition: path_builder.h:14
impeller::Path::GetBoundingBox
std::optional< Rect > GetBoundingBox() const
Definition: path.cc:339
impeller::Convexity
Convexity
Definition: path.h:34
impeller::Path::ComponentType::kQuadratic
@ kQuadratic
impeller::Path::IsEmpty
bool IsEmpty() const
Definition: path.cc:59
impeller::Cap::kButt
@ kButt
impeller::Path::Polyline::Polyline
Polyline(PointBufferPtr point_buffer, ReclaimPointBufferCallback reclaim)
Definition: path.cc:179
impeller::Join::kMiter
@ kMiter
impeller::Path::~Path
~Path()
impeller::Path::Polyline
Definition: path.h:94
impeller::Convexity::kUnknown
@ kUnknown
impeller::Path::ComponentType
ComponentType
Definition: path.h:53
impeller::Path::GetCubicComponentAtIndex
bool GetCubicComponentAtIndex(size_t index, CubicPathComponent &cubic) const
Definition: path.cc:144
impeller::Path::Polyline::ReclaimPointBufferCallback
std::function< void(PointBufferPtr)> ReclaimPointBufferCallback
Definition: path.h:98
impeller::Path::EnumerateComponents
void EnumerateComponents(const Applier< LinearPathComponent > &linear_applier, const Applier< QuadraticPathComponent > &quad_applier, const Applier< CubicPathComponent > &cubic_applier, const Applier< ContourComponent > &contour_applier) const
Definition: path.cc:63
impeller::Path::PolylineContour::start_direction
Vector2 start_direction
The direction of the contour's start cap.
Definition: path.h:77
impeller::Path
Paths are lightweight objects that describe a collection of linear, quadratic, or cubic segments....
Definition: path.h:51
impeller::Path::Polyline::GetPoint
Point & GetPoint(size_t index) const
Definition: path.h:111
impeller::Path::GetTransformedBoundingBox
std::optional< Rect > GetTransformedBoundingBox(const Matrix &transform) const
Definition: path.cc:343
impeller::Path::Polyline::GetContourPointBounds
std::tuple< size_t, size_t > GetContourPointBounds(size_t contour_index) const
Definition: path.cc:22
impeller::Path::PolylineContour::Component
Definition: path.h:61
impeller::FillType
FillType
Definition: path.h:29
impeller::Join::kRound
@ kRound
impeller::Path::PolylineContour::end_direction
Vector2 end_direction
The direction of the contour's end cap.
Definition: path.h:79
impeller::FillType::kNonZero
@ kNonZero
impeller::Path::Path
Path()
Definition: path.cc:16
impeller::Path::GetContourComponentAtIndex
bool GetContourComponentAtIndex(size_t index, ContourComponent &contour) const
Definition: path.cc:163
impeller::CubicPathComponent
Definition: path_component.h:99
impeller::Path::Polyline::points
PointBufferPtr points
Definition: path.h:109
impeller::Join::kBevel
@ kBevel
impeller::Path::PolylineContour::Component::is_curve
bool is_curve
Definition: path.h:67
impeller::Join
Join
Definition: path.h:23
impeller::Path::Applier
std::function< void(size_t index, const T &component)> Applier
Definition: path.h:141
impeller::TPoint< Scalar >
impeller::Path::GetComponentCount
size_t GetComponentCount(std::optional< ComponentType > type={}) const
Definition: path.cc:34
impeller::Path::Polyline::contours
std::vector< PolylineContour > contours
Definition: path.h:115
scale
const Scalar scale
Definition: stroke_path_geometry.cc:297
impeller::Path::Polyline::PointBufferPtr
std::unique_ptr< std::vector< Point > > PointBufferPtr
Definition: path.h:97
impeller::Path::Polyline::~Polyline
~Polyline()
Definition: path.cc:191
impeller::Path::IsConvex
bool IsConvex() const
Definition: path.cc:55
path_component.h
impeller::ContourComponent
Definition: path_component.h:152
impeller::Convexity::kConvex
@ kConvex
impeller::Path::PolylineContour::Component::component_start_index
size_t component_start_index
Definition: path.h:62
impeller
Definition: aiks_blur_unittests.cc:20
impeller::QuadraticPathComponent
Definition: path_component.h:53
impeller::Path::CreatePolyline
Polyline CreatePolyline(Scalar scale, Polyline::PointBufferPtr point_buffer=std::make_unique< std::vector< Point >>(), Polyline::ReclaimPointBufferCallback reclaim=nullptr) const
Definition: path.cc:198
impeller::Path::GetLinearComponentAtIndex
bool GetLinearComponentAtIndex(size_t index, LinearPathComponent &linear) const
Definition: path.cc:106
impeller::Path::ComponentType::kContour
@ kContour
impeller::Matrix
A 4x4 matrix using column-major storage.
Definition: matrix.h:37
impeller::Path::PolylineContour::is_closed
bool is_closed
Definition: path.h:74
impeller::Cap
Cap
Definition: path.h:17
impeller::Path::GetFillType
FillType GetFillType() const
Definition: path.cc:51