Flutter Engine
 
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().addRect(left, top, right, bottom));
48}
49
51 DlScalar y,
54 return DlPath(SkPath().addRect(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 SkPath 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);
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 SkPath path = data_->sk_path;
192 path = path.offset(offset.x, offset.y);
193 return DlPath(path);
194}
195
197 SkPathFillType sk_type = ToSkFillType(type);
198 if (data_->sk_path.getFillType() == sk_type) {
199 return *this;
200 }
201 SkPath path = data_->sk_path;
202 path.setFillType(sk_type);
203 return DlPath(path);
204}
205
206bool DlPath::IsEmpty() const {
207 return GetSkPath().isEmpty();
208}
209
210bool DlPath::IsRect(DlRect* rect, bool* is_closed) const {
211 return GetSkPath().isRect(ToSkRect(rect), is_closed);
212}
213
214bool DlPath::IsOval(DlRect* bounds) const {
215 return GetSkPath().isOval(ToSkRect(bounds));
216}
217
218bool DlPath::IsLine(DlPoint* start, DlPoint* end) const {
219 SkPoint sk_points[2];
220 if (GetSkPath().isLine(sk_points)) {
221 *start = ToDlPoint(sk_points[0]);
222 *end = ToDlPoint(sk_points[1]);
223 return true;
224 }
225 return false;
226}
227
229 SkRRect sk_rrect;
230 bool ret = GetSkPath().isRRect(rrect ? &sk_rrect : nullptr);
231 if (rrect) {
232 *rrect = ToDlRoundRect(sk_rrect);
233 }
234 return ret;
235}
236
237bool DlPath::Contains(const DlPoint point) const {
238 return GetSkPath().contains(point.x, point.y);
239}
240
242 return ToDlFillType(GetSkPath().getFillType());
243}
244
246 return ToDlRect(GetSkPath().getBounds());
247}
248
249bool DlPath::operator==(const DlPath& other) const {
250 return GetSkPath() == other.GetSkPath();
251}
252
253bool DlPath::IsVolatile() const {
254 return GetSkPath().isVolatile();
255}
256
257bool DlPath::IsConvex() const {
258 return data_->sk_path.isConvex();
259}
260
261DlPath DlPath::operator+(const DlPath& other) const {
262 SkPath path = GetSkPath();
263 path.addPath(other.GetSkPath());
264 return DlPath(path);
265}
266
267void DlPath::ReduceConic(DlPathReceiver& receiver,
268 const DlPoint& p1,
269 const DlPoint& cp,
270 const DlPoint& p2,
271 DlScalar weight) {
272 // We might eventually have conic conversion math that deals with
273 // degenerate conics gracefully (or have all receivers just handle
274 // them directly). But, until then, we will just convert them to a
275 // pair of quads and accept the results as "close enough".
276 if (p1 != cp) {
277 if (cp != p2) {
278 FML_DCHECK(std::isfinite(weight) && weight > 0);
279
280 // Observe that scale will always be smaller than 1 because weight > 0.
281 const DlScalar scale = 1.0f / (1.0f + weight);
282
283 // The subdivided control points below are the sums of the following
284 // three terms. Because the terms are multiplied by something <1, and
285 // the resulting control points lie within the control points of the
286 // original then the terms and the sums below will not overflow.
287 // Note that weight * scale approaches 1 as weight becomes very large.
288 DlPoint tp1 = p1 * scale;
289 DlPoint tcp = cp * (weight * scale);
290 DlPoint tp2 = p2 * scale;
291
292 // Calculate the subdivided control points
293 DlPoint sub_cp1 = tp1 + tcp;
294 DlPoint sub_cp2 = tcp + tp2;
295
296 // The middle point shared by the 2 sub-divisions, the interpolation of
297 // the original curve at its halfway point.
298 DlPoint sub_mid = (tp1 + tcp + tcp + tp2) * 0.5f;
299
300 FML_DCHECK(sub_cp1.IsFinite() && //
301 sub_mid.IsFinite() && //
302 sub_cp2.IsFinite());
303
304 receiver.QuadTo(sub_cp1, sub_mid);
305 receiver.QuadTo(sub_cp2, p2);
306
307 // Update w.
308 // Currently this method only subdivides a single time directly to 2
309 // quadratics, but if we eventually want to keep the weights for further
310 // subdivision, this was the code that did it in Skia:
311 // sub_w1 = sub_w2 = SkScalarSqrt(SK_ScalarHalf + w * SK_ScalarHalf)
312 } else {
313 receiver.LineTo(cp);
314 }
315 } else if (cp != p2) {
316 receiver.LineTo(p2);
317 }
318}
319
320} // 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:237
bool IsEmpty() const
Definition dl_path.cc:206
bool IsRect(DlRect *rect=nullptr, bool *is_closed=nullptr) const
Definition dl_path.cc:210
static constexpr uint32_t kMaxVolatileUses
Definition dl_path.h:21
bool operator==(const DlPath &other) const
Definition dl_path.cc:249
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:261
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:228
static DlPath MakeOvalLTRB(DlScalar left, DlScalar top, DlScalar right, DlScalar bottom)
Definition dl_path.cc:61
DlRect GetBounds() const override
Definition dl_path.cc:245
const SkPath & GetSkPath() const
Definition dl_path.cc:116
DlPathFillType GetFillType() const override
Definition dl_path.cc:241
DlPath WithFillType(DlPathFillType type) const
Definition dl_path.cc:196
bool IsLine(DlPoint *start=nullptr, DlPoint *end=nullptr) const
Definition dl_path.cc:218
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:253
void Dispatch(DlPathReceiver &receiver) const override
Definition dl_path.cc:120
bool IsConvex() const override
Definition dl_path.cc:257
bool IsOval(DlRect *bounds=nullptr) const
Definition dl_path.cc:214
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