Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
dl_path.cc
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
6
10
11namespace {
12inline constexpr flutter::DlPathFillType ToDlFillType(SkPathFillType sk_type) {
13 switch (sk_type) {
14 case SkPathFillType::kEvenOdd:
16 case SkPathFillType::kWinding:
18 case SkPathFillType::kInverseEvenOdd:
19 case SkPathFillType::kInverseWinding:
21 }
22}
23
24inline constexpr SkPathFillType ToSkFillType(flutter::DlPathFillType dl_type) {
25 switch (dl_type) {
27 return SkPathFillType::kEvenOdd;
29 return SkPathFillType::kWinding;
30 }
31}
32} // namespace
33
34namespace flutter {
35
38
40 return DlPath(SkPath::Rect(ToSkRect(rect)));
41}
42
44 DlScalar top,
45 DlScalar right,
46 DlScalar bottom) {
47 return DlPath(SkPath::Rect(SkRect::MakeLTRB(left, top, right, bottom)));
48}
49
51 DlScalar y,
54 return DlPath(SkPath::Rect(SkRect::MakeXYWH(x, y, width, height)));
55}
56
58 return DlPath(SkPath::Oval(ToSkRect(bounds)));
59}
60
62 DlScalar top,
63 DlScalar right,
64 DlScalar bottom) {
65 return DlPath(SkPath::Oval(SkRect::MakeLTRB(left, top, right, bottom)));
66}
67
69 return DlPath(SkPath::Circle(center.x, center.y, radius));
70}
71
73 return DlPath(SkPath::RRect(ToSkRRect(rrect)));
74}
75
77 DlScalar x_radius,
78 DlScalar y_radius,
79 bool counter_clock_wise) {
80 return DlPath(SkPath::RRect(
81 ToSkRect(rect), x_radius, y_radius,
82 counter_clock_wise ? SkPathDirection::kCCW : SkPathDirection::kCW));
83}
84
88
90 return DlPath(SkPath::Line(ToSkPoint(a), ToSkPoint(b)));
91}
92
94 int count,
95 bool close,
96 DlPathFillType fill_type) {
97 return DlPath(SkPath::Polygon({ToSkPoints(pts), count}, close,
98 ToSkFillType(fill_type)));
99}
100
102 DlDegrees start,
103 DlDegrees sweep,
104 bool use_center) {
105 SkPathBuilder path;
106 if (use_center) {
107 path.moveTo(ToSkPoint(bounds.GetCenter()));
108 }
109 path.arcTo(ToSkRect(bounds), start.degrees, sweep.degrees, !use_center);
110 if (use_center) {
111 path.close();
112 }
113 return DlPath(path.detach());
114}
115
116const SkPath& DlPath::GetSkPath() const {
117 return data_->sk_path;
118}
119
120void DlPath::Dispatch(DlPathReceiver& receiver) const {
121 const SkPath& path = data_->sk_path;
122 if (path.isEmpty()) {
123 return;
124 }
125
126 auto iterator = SkPath::Iter(path, false);
127
128 struct PathData {
129 union {
130 SkPoint points[4];
131 };
132 };
133
135
136 auto verb = SkPath::Verb::kDone_Verb;
137 do {
138 verb = iterator.next(data.points);
139 switch (verb) {
140 case SkPath::kMove_Verb:
141 receiver.MoveTo(ToDlPoint(data.points[0]), iterator.isClosedContour());
142 break;
143 case SkPath::kLine_Verb:
144 receiver.LineTo(ToDlPoint(data.points[1]));
145 break;
146 case SkPath::kQuad_Verb:
147 receiver.QuadTo(ToDlPoint(data.points[1]), ToDlPoint(data.points[2]));
148 break;
149 case SkPath::kConic_Verb:
150 if (!receiver.ConicTo(ToDlPoint(data.points[1]),
151 ToDlPoint(data.points[2]),
152 iterator.conicWeight())) {
153 ReduceConic(receiver, //
154 ToDlPoint(data.points[0]), //
155 ToDlPoint(data.points[1]), //
156 ToDlPoint(data.points[2]), //
157 iterator.conicWeight());
158 }
159 break;
160 case SkPath::kCubic_Verb:
161 receiver.CubicTo(ToDlPoint(data.points[1]), //
162 ToDlPoint(data.points[2]), //
163 ToDlPoint(data.points[3]));
164 break;
165 case SkPath::kClose_Verb:
166 receiver.Close();
167 break;
168 case SkPath::kDone_Verb:
169 break;
170 }
171 } while (verb != SkPath::Verb::kDone_Verb);
172}
173
175 uint32_t count = data_->render_count;
176 if (count <= kMaxVolatileUses) {
177 if (count == kMaxVolatileUses) {
178 data_->sk_path.setIsVolatile(false);
179 }
180 data_->render_count = ++count;
181 }
182}
183
184[[nodiscard]] DlPath DlPath::WithOffset(const DlPoint offset) const {
185 if (offset.IsZero()) {
186 return *this;
187 }
188 if (!offset.IsFinite()) {
189 return DlPath();
190 }
191 return DlPath(data_->sk_path.makeOffset(offset.x, offset.y));
192}
193
195 SkPathFillType sk_type = ToSkFillType(type);
196 if (data_->sk_path.getFillType() == sk_type) {
197 return *this;
198 }
199 SkPath path = data_->sk_path;
200 path.setFillType(sk_type);
201 return DlPath(path);
202}
203
204bool DlPath::IsEmpty() const {
205 return GetSkPath().isEmpty();
206}
207
208bool DlPath::IsRect(DlRect* rect, bool* is_closed) const {
209 return GetSkPath().isRect(ToSkRect(rect), is_closed);
210}
211
212bool DlPath::IsOval(DlRect* bounds) const {
213 return GetSkPath().isOval(ToSkRect(bounds));
214}
215
216bool DlPath::IsLine(DlPoint* start, DlPoint* end) const {
217 SkPoint sk_points[2];
218 if (GetSkPath().isLine(sk_points)) {
219 *start = ToDlPoint(sk_points[0]);
220 *end = ToDlPoint(sk_points[1]);
221 return true;
222 }
223 return false;
224}
225
227 SkRRect sk_rrect;
228 bool ret = GetSkPath().isRRect(rrect ? &sk_rrect : nullptr);
229 if (rrect) {
230 *rrect = ToDlRoundRect(sk_rrect);
231 }
232 return ret;
233}
234
235bool DlPath::Contains(const DlPoint point) const {
236 return GetSkPath().contains(point.x, point.y);
237}
238
240 return ToDlFillType(GetSkPath().getFillType());
241}
242
244 return ToDlRect(GetSkPath().getBounds());
245}
246
247bool DlPath::operator==(const DlPath& other) const {
248 return GetSkPath() == other.GetSkPath();
249}
250
251bool DlPath::IsVolatile() const {
252 return GetSkPath().isVolatile();
253}
254
255bool DlPath::IsConvex() const {
256 return data_->sk_path.isConvex();
257}
258
259DlPath DlPath::operator+(const DlPath& other) const {
260 SkPathBuilder path = SkPathBuilder(GetSkPath());
261 path.addPath(other.GetSkPath());
262 return DlPath(path.detach());
263}
264
265void DlPath::ReduceConic(DlPathReceiver& receiver,
266 const DlPoint& p1,
267 const DlPoint& cp,
268 const DlPoint& p2,
269 DlScalar weight) {
270 // We might eventually have conic conversion math that deals with
271 // degenerate conics gracefully (or have all receivers just handle
272 // them directly). But, until then, we will just convert them to a
273 // pair of quads and accept the results as "close enough".
274 if (p1 != cp) {
275 if (cp != p2) {
276 FML_DCHECK(std::isfinite(weight) && weight > 0);
277
278 // Observe that scale will always be smaller than 1 because weight > 0.
279 const DlScalar scale = 1.0f / (1.0f + weight);
280
281 // The subdivided control points below are the sums of the following
282 // three terms. Because the terms are multiplied by something <1, and
283 // the resulting control points lie within the control points of the
284 // original then the terms and the sums below will not overflow.
285 // Note that weight * scale approaches 1 as weight becomes very large.
286 DlPoint tp1 = p1 * scale;
287 DlPoint tcp = cp * (weight * scale);
288 DlPoint tp2 = p2 * scale;
289
290 // Calculate the subdivided control points
291 DlPoint sub_cp1 = tp1 + tcp;
292 DlPoint sub_cp2 = tcp + tp2;
293
294 // The middle point shared by the 2 sub-divisions, the interpolation of
295 // the original curve at its halfway point.
296 DlPoint sub_mid = (tp1 + tcp + tcp + tp2) * 0.5f;
297
298 FML_DCHECK(sub_cp1.IsFinite() && //
299 sub_mid.IsFinite() && //
300 sub_cp2.IsFinite());
301
302 receiver.QuadTo(sub_cp1, sub_mid);
303 receiver.QuadTo(sub_cp2, p2);
304
305 // Update w.
306 // Currently this method only subdivides a single time directly to 2
307 // quadratics, but if we eventually want to keep the weights for further
308 // subdivision, this was the code that did it in Skia:
309 // sub_w1 = sub_w2 = SkScalarSqrt(SK_ScalarHalf + w * SK_ScalarHalf)
310 } else {
311 receiver.LineTo(cp);
312 }
313 } else if (cp != p2) {
314 receiver.LineTo(p2);
315 }
316}
317
318} // namespace flutter
GLenum type
DlPathBuilder & AddRoundSuperellipse(const DlRoundSuperellipse &rse)
Append a closed rounded super-ellipse contour to the path.
const DlPath TakePath()
Returns the path constructed by this path builder and resets its internal state to the default state ...
bool Contains(const DlPoint point) const
Definition dl_path.cc:235
bool IsEmpty() const
Definition dl_path.cc:204
bool IsRect(DlRect *rect=nullptr, bool *is_closed=nullptr) const
Definition dl_path.cc:208
static constexpr uint32_t kMaxVolatileUses
Definition dl_path.h:21
bool operator==(const DlPath &other) const
Definition dl_path.cc:247
static DlPath MakeRectLTRB(DlScalar left, DlScalar top, DlScalar right, DlScalar bottom)
Definition dl_path.cc:43
static DlPath MakeLine(const DlPoint a, const DlPoint b)
Definition dl_path.cc:89
DlPath WithOffset(const DlPoint offset) const
Definition dl_path.cc:184
DlPath operator+(const DlPath &other) const
Definition dl_path.cc:259
static DlPath MakeRoundRect(const DlRoundRect &rrect)
Definition dl_path.cc:72
static DlPath MakeCircle(const DlPoint center, DlScalar radius)
Definition dl_path.cc:68
static DlPath MakeArc(const DlRect &bounds, DlDegrees start, DlDegrees sweep, bool use_center)
Definition dl_path.cc:101
static DlPath MakeRectXYWH(DlScalar x, DlScalar y, DlScalar width, DlScalar height)
Definition dl_path.cc:50
static DlPath MakeRect(const DlRect &rect)
Definition dl_path.cc:39
static DlPath MakeRoundSuperellipse(const DlRoundSuperellipse &rse)
Definition dl_path.cc:85
static DlPath MakeRoundRectXY(const DlRect &rect, DlScalar x_radius, DlScalar y_radius, bool counter_clock_wise=false)
Definition dl_path.cc:76
bool IsRoundRect(DlRoundRect *rrect=nullptr) const
Definition dl_path.cc:226
static DlPath MakeOvalLTRB(DlScalar left, DlScalar top, DlScalar right, DlScalar bottom)
Definition dl_path.cc:61
DlRect GetBounds() const override
Definition dl_path.cc:243
const SkPath & GetSkPath() const
Definition dl_path.cc:116
DlPathFillType GetFillType() const override
Definition dl_path.cc:239
DlPath WithFillType(DlPathFillType type) const
Definition dl_path.cc:194
bool IsLine(DlPoint *start=nullptr, DlPoint *end=nullptr) const
Definition dl_path.cc:216
void WillRenderSkPath() const
Definition dl_path.cc:174
static DlPath MakeOval(const DlRect &bounds)
Definition dl_path.cc:57
bool IsVolatile() const
Definition dl_path.cc:251
void Dispatch(DlPathReceiver &receiver) const override
Definition dl_path.cc:120
bool IsConvex() const override
Definition dl_path.cc:255
bool IsOval(DlRect *bounds=nullptr) const
Definition dl_path.cc:212
static DlPath MakePoly(const DlPoint pts[], int count, bool close, DlPathFillType fill_type=DlPathFillType::kNonZero)
Definition dl_path.cc:93
Collection of functions to receive path segments from the underlying path representation via the DlPa...
Definition path_source.h:42
virtual void CubicTo(const Point &cp1, const Point &cp2, const Point &p2)=0
virtual void LineTo(const Point &p2)=0
virtual void QuadTo(const Point &cp, const Point &p2)=0
virtual void Close()=0
virtual void MoveTo(const Point &p2, bool will_be_closed)=0
virtual bool ConicTo(const Point &cp, const Point &p2, Scalar weight)
Definition path_source.h:48
int32_t x
#define FML_UNREACHABLE()
Definition logging.h:128
#define FML_DCHECK(condition)
Definition logging.h:122
double y
impeller::Scalar DlScalar
const SkPoint & ToSkPoint(const DlPoint &point)
const DlPoint & ToDlPoint(const SkPoint &point)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition switch_defs.h:52
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot data
Definition switch_defs.h:36
const SkPoint * ToSkPoints(const DlPoint *points)
const DlRoundRect ToDlRoundRect(const SkRRect &rrect)
const SkRRect ToSkRRect(const DlRoundRect &round_rect)
const DlRect & ToDlRect(const SkRect &rect)
const SkRect & ToSkRect(const DlRect &rect)
int32_t height
int32_t width
Scalar degrees
Definition scalar.h:67
constexpr bool IsZero() const
Definition point.h:240
IsFinite() const
Definition point.h:243
constexpr Point GetCenter() const
Get the center point as a |Point|.
Definition rect.h:382
const size_t start
const size_t end
std::vector< Point > points