Flutter Impeller
path_tessellator.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_TESSELLATOR_PATH_TESSELLATOR_H_
6 #define FLUTTER_IMPELLER_TESSELLATOR_PATH_TESSELLATOR_H_
7 
8 #include <memory>
9 #include <tuple>
10 
14 
15 namespace impeller {
16 
18  public:
19  /// @brief An interface for generating a multi contour polyline as a triangle
20  /// strip.
21  class VertexWriter {
22  public:
23  virtual void Write(Point point) = 0;
24  virtual void EndContour() = 0;
25  };
26 
27  /// An interface for receiving pruned path segments.
29  public:
30  /// Every set of path segments will be surrounded by a Begin/EndContour
31  /// pair with the same origin point.
32  virtual void BeginContour(Point origin, bool will_be_closed) = 0;
33 
34  /// Guaranteed to be non-degenerate except in the single case of stroking
35  /// where we have a MoveTo followed by any number of degenerate (single
36  /// point, going nowhere) path segments.
37  /// p1 will always be the last recorded point.
38  virtual void RecordLine(Point p1, Point p2) = 0;
39 
40  /// Guaranteed to be non-degenerate (not a line).
41  /// p1 will always be the last recorded point.
42  virtual void RecordQuad(Point p1, Point cp, Point p2) = 0;
43 
44  /// Guaranteed to be non-degenerate (not a quad or line)
45  /// p1 will always be the last recorded point.
46  virtual void RecordConic(Point p1, Point cp, Point p2, Scalar weight) = 0;
47 
48  /// Guaranteed to be trivially non-degenerate (not all 4 points the same).
49  /// p1 will always be the last recorded point.
50  virtual void RecordCubic(Point p1, Point cp1, Point cp2, Point p2) = 0;
51 
52  /// Every set of path segments will be surrounded by a Begin/EndContour
53  /// pair with the same origin point.
54  /// The boolean indicates if the path was closed as the result of an
55  /// explicit PathReceiver::Close invocation which tells a stroking
56  /// sub-class whether to use end caps or a "join to first segment".
57  /// Contours which are closed by a MoveTo will supply "false".
58  virtual void EndContour(Point origin, bool with_close) = 0;
59  };
60 
61  struct Quad {
62  const Point p1;
63  const Point cp;
64  const Point p2;
65 
66  Point Last() const { return p2; }
67 
68  Point Solve(Scalar t) const {
69  Scalar u = 1.0f - t;
70  return p1 * u * u + 2 * cp * u * t + p2 * t * t;
71  }
72 
74  return ComputeQuadradicSubdivisions(scale, p1, cp, p2);
75  }
76 
77  std::optional<Vector2> GetStartDirection() const {
78  if (p1 != cp) {
79  return (p1 - cp).Normalize();
80  }
81  if (p1 != p2) {
82  return (p1 - p2).Normalize();
83  }
84  return std::nullopt;
85  }
86 
87  std::optional<Vector2> GetEndDirection() const {
88  if (p2 != cp) {
89  return (p2 - cp).Normalize();
90  }
91  if (p2 != p1) {
92  return (p2 - p1).Normalize();
93  }
94  return std::nullopt;
95  }
96  };
97 
98  struct Conic {
99  const Point p1;
100  const Point cp;
101  const Point p2;
102  const Scalar weight;
103 
104  Point Last() const { return p2; }
105 
106  Point Solve(Scalar t) const {
107  Scalar u = 1.0f - t;
108  Scalar coeff_1 = u * u;
109  Scalar coeff_c = 2 * u * t * weight;
110  Scalar coeff_2 = t * t;
111 
112  return (p1 * coeff_1 + cp * coeff_c + p2 * coeff_2) /
113  (coeff_1 + coeff_c + coeff_2);
114  }
115 
117  return ComputeConicSubdivisions(scale, p1, cp, p2, weight);
118  }
119 
120  std::optional<Vector2> GetStartDirection() const {
121  if (p1 != cp) {
122  return (p1 - cp).Normalize();
123  }
124  if (p1 != p2) {
125  return (p1 - p2).Normalize();
126  }
127  return std::nullopt;
128  }
129 
130  std::optional<Vector2> GetEndDirection() const {
131  if (p2 != cp) {
132  return (p2 - cp).Normalize();
133  }
134  if (p2 != p1) {
135  return (p2 - p1).Normalize();
136  }
137  return std::nullopt;
138  }
139  };
140 
141  struct Cubic {
142  const Point p1;
143  const Point cp1;
144  const Point cp2;
145  const Point p2;
146 
147  Point Last() const { return p2; }
148 
149  Point Solve(Scalar t) const {
150  Scalar u = 1.0f - t;
151  return p1 * u * u * u + //
152  3 * cp1 * u * u * t + //
153  3 * cp2 * u * t * t + //
154  p2 * t * t * t;
155  }
156 
158  return ComputeCubicSubdivisions(scale, p1, cp1, cp2, p2);
159  }
160 
161  std::optional<Vector2> GetStartDirection() const {
162  if (p1 != cp1) {
163  return (p1 - cp1).Normalize();
164  }
165  if (p1 != cp2) {
166  return (p1 - cp2).Normalize();
167  }
168  if (p1 != p2) {
169  return (p1 - p2).Normalize();
170  }
171  return std::nullopt;
172  }
173 
174  std::optional<Vector2> GetEndDirection() const {
175  if (p2 != cp2) {
176  return (p2 - cp2).Normalize();
177  }
178  if (p2 != cp1) {
179  return (p2 - cp1).Normalize();
180  }
181  if (p2 != p1) {
182  return (p2 - p1).Normalize();
183  }
184  return std::nullopt;
185  }
186  };
187 
188  static void PathToFilledSegments(const PathSource& source,
189  SegmentReceiver& receiver);
190 
191  static void PathToStrokedSegments(const PathSource& source,
192  SegmentReceiver& receiver);
193 
194  static std::pair<size_t, size_t> CountFillStorage(const PathSource& source,
195  Scalar scale);
196 
197  static void PathToFilledVertices(const PathSource& source,
198  VertexWriter& writer,
199  Scalar scale);
200 };
201 
202 } // namespace impeller
203 
204 #endif // FLUTTER_IMPELLER_TESSELLATOR_PATH_TESSELLATOR_H_
An interface for receiving pruned path segments.
virtual void RecordLine(Point p1, Point p2)=0
virtual void RecordCubic(Point p1, Point cp1, Point cp2, Point p2)=0
virtual void RecordConic(Point p1, Point cp, Point p2, Scalar weight)=0
virtual void RecordQuad(Point p1, Point cp, Point p2)=0
virtual void EndContour(Point origin, bool with_close)=0
virtual void BeginContour(Point origin, bool will_be_closed)=0
An interface for generating a multi contour polyline as a triangle strip.
virtual void Write(Point point)=0
static void PathToFilledSegments(const PathSource &source, SegmentReceiver &receiver)
static void PathToStrokedSegments(const PathSource &source, SegmentReceiver &receiver)
static void PathToFilledVertices(const PathSource &source, VertexWriter &writer, Scalar scale)
static std::pair< size_t, size_t > CountFillStorage(const PathSource &source, Scalar scale)
float Scalar
Definition: scalar.h:19
Scalar ComputeConicSubdivisions(Scalar scale_factor, Point p0, Point p1, Point p2, Scalar w)
Scalar ComputeQuadradicSubdivisions(Scalar scale_factor, Point p0, Point p1, Point p2)
Scalar ComputeCubicSubdivisions(Scalar scale_factor, Point p0, Point p1, Point p2, Point p3)
std::optional< Vector2 > GetStartDirection() const
std::optional< Vector2 > GetEndDirection() const
Scalar SubdivisionCount(Scalar scale) const
std::optional< Vector2 > GetStartDirection() const
Scalar SubdivisionCount(Scalar scale) const
std::optional< Vector2 > GetEndDirection() const
Scalar SubdivisionCount(Scalar scale) const
std::optional< Vector2 > GetStartDirection() const
std::optional< Vector2 > GetEndDirection() const