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 <memory>
10 #include <optional>
11 #include <ostream>
12 #include <tuple>
13 #include <vector>
14 
16 #include "impeller/geometry/rect.h"
17 
18 namespace impeller {
19 
20 enum class Cap {
21  kButt,
22  kRound,
23  kSquare,
24 };
25 
26 enum class Join {
27  kMiter,
28  kRound,
29  kBevel,
30 };
31 
32 enum class FillType {
33  kNonZero, // The default winding order.
34  kOdd,
35 };
36 
37 enum class Convexity {
38  kUnknown,
39  kConvex,
40 };
41 
42 //------------------------------------------------------------------------------
43 /// @brief Paths are lightweight objects that describe a collection of
44 /// linear, quadratic, or cubic segments. These segments may be
45 /// broken up by move commands, which are effectively linear
46 /// commands that pick up the pen rather than continuing to draw.
47 ///
48 /// All shapes supported by Impeller are paths either directly or
49 /// via approximation (in the case of circles).
50 ///
51 /// Paths are externally immutable once created, Creating paths must
52 /// be done using a path builder.
53 ///
54 class Path {
55  public:
56  enum class ComponentType {
57  kLinear,
58  kQuadratic,
59  kConic,
60  kCubic,
61  kContour,
62  };
63 
65  public:
66  ComponentType type() const;
67 
68  // Return pointer to path component or null if the type is wrong or
69  // the iterator is past the end of the path.
70  const LinearPathComponent* linear() const;
71  const QuadraticPathComponent* quadratic() const;
72  const ConicPathComponent* conic() const;
73  const CubicPathComponent* cubic() const;
74  const ContourComponent* contour() const;
75 
77  bool operator==(const ComponentIterator& other) const {
78  return component_index_ == other.component_index_;
79  }
80  bool operator!=(const ComponentIterator& other) const {
81  return component_index_ != other.component_index_;
82  }
83 
84  private:
85  ComponentIterator(const Path& path, size_t index, size_t offset)
86  : path_(path), component_index_(index), storage_offset_(offset) {}
87 
88  const Path& path_;
89  size_t component_index_ = 0u;
90  size_t storage_offset_ = 0u;
91 
92  friend class Path;
93  };
94 
95  static constexpr size_t VerbToOffset(Path::ComponentType verb) {
96  switch (verb) {
98  return 2u;
100  return 3u;
102  return 4u;
104  return 4u;
106  return 2u;
107  break;
108  }
109  FML_UNREACHABLE();
110  }
111 
113  struct Component {
115  /// Denotes whether this component is a curve.
116  ///
117  /// This is set to true when this component is generated from
118  /// QuadraticComponent or CubicPathComponent.
119  bool is_curve;
120  };
121  /// Index that denotes the first point of this contour.
122  size_t start_index;
123 
124  /// Denotes whether the last point of this contour is connected to the first
125  /// point of this contour or not.
126  bool is_closed;
127 
128  /// The direction of the contour's start cap.
130  /// The direction of the contour's end cap.
132 
133  /// Distinct components in this contour.
134  ///
135  /// If this contour is generated from multiple path components, each
136  /// path component forms a component in this vector.
137  std::vector<Component> components;
138  };
139 
140  /// One or more contours represented as a series of points and indices in
141  /// the point vector representing the start of a new contour.
142  ///
143  /// Polylines are ephemeral and meant to be used by the tessellator. They do
144  /// not allocate their own point vectors to allow for optimizations around
145  /// allocation and reuse of arenas.
146  struct Polyline {
147  /// The signature of a method called when it is safe to reclaim the point
148  /// buffer provided to the constructor of this object.
149  using PointBufferPtr = std::unique_ptr<std::vector<Point>>;
150  using ReclaimPointBufferCallback = std::function<void(PointBufferPtr)>;
151 
152  /// The buffer will be cleared and returned at the destruction of this
153  /// polyline.
154  Polyline(PointBufferPtr point_buffer, ReclaimPointBufferCallback reclaim);
155 
156  Polyline(Polyline&& other);
157  ~Polyline();
158 
159  /// Points in the polyline, which may represent multiple contours specified
160  /// by indices in |contours|.
162 
163  Point& GetPoint(size_t index) const { return (*points)[index]; }
164 
165  /// Contours are disconnected pieces of a polyline, such as when a MoveTo
166  /// was issued on a PathBuilder.
167  std::vector<PolylineContour> contours;
168 
169  /// Convenience method to compute the start (inclusive) and end (exclusive)
170  /// point of the given contour index.
171  ///
172  /// The contour_index parameter is clamped to contours.size().
173  std::tuple<size_t, size_t> GetContourPointBounds(
174  size_t contour_index) const;
175 
176  private:
177  ReclaimPointBufferCallback reclaim_points_;
178  };
179 
180  Path();
181 
182  ~Path();
183 
184  size_t GetComponentCount(std::optional<ComponentType> type = {}) const;
185 
186  size_t GetPointCount() const;
187 
188  FillType GetFillType() const;
189 
190  bool IsConvex() const;
191 
192  bool IsEmpty() const;
193 
194  /// @brief Whether the line contains a single contour.
195  bool IsSingleContour() const;
196 
197  ComponentIterator begin() const;
198  ComponentIterator end() const;
199 
200  /// Callers must provide the scale factor for how this path will be
201  /// transformed.
202  ///
203  /// It is suitable to use the max basis length of the matrix used to transform
204  /// the path. If the provided scale is 0, curves will revert to straight
205  /// lines.
206  Polyline CreatePolyline(
207  Scalar scale,
208  Polyline::PointBufferPtr point_buffer =
209  std::make_unique<std::vector<Point>>(),
210  Polyline::ReclaimPointBufferCallback reclaim = nullptr) const;
211 
212  void EndContour(
213  size_t storage_offset,
214  Polyline& polyline,
215  size_t component_index,
216  std::vector<PolylineContour::Component>& poly_components) const;
217 
218  std::optional<Rect> GetBoundingBox() const;
219 
220  std::optional<Rect> GetTransformedBoundingBox(const Matrix& transform) const;
221 
222  /// Generate a polyline into the temporary storage held by the [writer].
223  ///
224  /// It is suitable to use the max basis length of the matrix used to transform
225  /// the path. If the provided scale is 0, curves will revert to straight
226  /// lines.
227  void WritePolyline(Scalar scale, VertexWriter& writer) const;
228 
229  /// Determine required storage for points and number of contours.
230  std::pair<size_t, size_t> CountStorage(Scalar scale) const;
231 
232  private:
233  friend class PathBuilder;
234 
235  // All of the data for the path is stored in this structure which is
236  // held by a shared_ptr. Since they all share the structure, the
237  // copy constructor for Path is very cheap and we don't need to deal
238  // with shared pointers for Path fields and method arguments.
239  //
240  // PathBuilder also uses this structure to accumulate the path data
241  // but the Path constructor used in |TakePath()| will clone the
242  // structure to prevent sharing and future modifications within the
243  // builder from affecting the existing taken paths.
244  struct Data {
245  Data() = default;
246 
247  Data(Data&& other) = default;
248 
249  Data(const Data& other) = default;
250 
251  ~Data() = default;
252 
254  Convexity convexity = Convexity::kUnknown;
255  bool single_contour = true;
256  std::optional<Rect> bounds;
257  std::vector<Point> points;
258  std::vector<ComponentType> components;
259  };
260 
261  explicit Path(Data data);
262 
263  std::shared_ptr<const Data> data_;
264 };
265 
266 static_assert(sizeof(Path) == sizeof(std::shared_ptr<struct Anonymous>));
267 
268 } // namespace impeller
269 
270 #endif // FLUTTER_IMPELLER_GEOMETRY_PATH_H_
GLenum type
const ContourComponent * contour() const
Definition: path.cc:63
ComponentIterator & operator++()
Definition: path.cc:71
const QuadraticPathComponent * quadratic() const
Definition: path.cc:39
ComponentType type() const
Definition: path.cc:22
const LinearPathComponent * linear() const
Definition: path.cc:31
const ConicPathComponent * conic() const
Definition: path.cc:47
bool operator!=(const ComponentIterator &other) const
Definition: path.h:80
bool operator==(const ComponentIterator &other) const
Definition: path.h:77
const CubicPathComponent * cubic() const
Definition: path.cc:55
Paths are lightweight objects that describe a collection of linear, quadratic, or cubic segments....
Definition: path.h:54
FillType GetFillType() const
Definition: path.cc:110
size_t GetComponentCount(std::optional< ComponentType > type={}) const
Definition: path.cc:92
ComponentIterator begin() const
Definition: path.cc:253
Polyline CreatePolyline(Scalar scale, Polyline::PointBufferPtr point_buffer=std::make_unique< std::vector< Point >>(), Polyline::ReclaimPointBufferCallback reclaim=nullptr) const
Definition: path.cc:355
bool IsSingleContour() const
Whether the line contains a single contour.
Definition: path.cc:124
std::optional< Rect > GetTransformedBoundingBox(const Matrix &transform) const
Definition: path.cc:470
static constexpr size_t VerbToOffset(Path::ComponentType verb)
Definition: path.h:95
bool IsConvex() const
Definition: path.cc:114
ComponentIterator end() const
Definition: path.cc:257
size_t GetPointCount() const
Definition: path.cc:106
void WritePolyline(Scalar scale, VertexWriter &writer) const
Definition: path.cc:174
bool IsEmpty() const
Definition: path.cc:118
void EndContour(size_t storage_offset, Polyline &polyline, size_t component_index, std::vector< PolylineContour::Component > &poly_components) const
Definition: path.cc:281
std::optional< Rect > GetBoundingBox() const
Definition: path.cc:466
std::pair< size_t, size_t > CountStorage(Scalar scale) const
Determine required storage for points and number of contours.
Definition: path.cc:129
An interface for generating a multi contour polyline as a triangle strip.
Join
Definition: path.h:26
float Scalar
Definition: scalar.h:18
FillType
Definition: path.h:32
Convexity
Definition: path.h:37
Cap
Definition: path.h:20
const Scalar scale
const Path::Polyline & polyline
SeparatedVector2 offset
A 4x4 matrix using column-major storage.
Definition: matrix.h:37
Vector2 start_direction
The direction of the contour's start cap.
Definition: path.h:129
size_t start_index
Index that denotes the first point of this contour.
Definition: path.h:122
std::vector< Component > components
Definition: path.h:137
Vector2 end_direction
The direction of the contour's end cap.
Definition: path.h:131
Polyline(PointBufferPtr point_buffer, ReclaimPointBufferCallback reclaim)
Definition: path.cc:262
std::vector< PolylineContour > contours
Definition: path.h:167
Point & GetPoint(size_t index) const
Definition: path.h:163
std::function< void(PointBufferPtr)> ReclaimPointBufferCallback
Definition: path.h:150
std::unique_ptr< std::vector< Point > > PointBufferPtr
Definition: path.h:149
PointBufferPtr points
Definition: path.h:161
std::tuple< size_t, size_t > GetContourPointBounds(size_t contour_index) const
Definition: path.cc:80
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:67