Flutter Engine
The Flutter Engine
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
5#include "flutter/lib/ui/painting/path.h"
6
7#include <cmath>
8
9#include "flutter/lib/ui/floating_point.h"
10#include "flutter/lib/ui/painting/matrix.h"
11#include "flutter/lib/ui/ui_dart_state.h"
16
17using tonic::ToDart;
18
19namespace flutter {
20
21typedef CanvasPath Path;
22
24
25CanvasPath::CanvasPath()
26 : path_tracker_(UIDartState::Current()->GetVolatilePathTracker()),
27 tracked_path_(std::make_shared<VolatilePathTracker::TrackedPath>()) {
28 FML_DCHECK(path_tracker_);
29 resetVolatility();
30}
31
32CanvasPath::~CanvasPath() = default;
33
34void CanvasPath::resetVolatility() {
35 if (!tracked_path_->tracking_volatility) {
36 mutable_path().setIsVolatile(true);
37 tracked_path_->frame_count = 0;
38 tracked_path_->tracking_volatility = true;
39 path_tracker_->Track(tracked_path_);
40 }
41}
42
43int CanvasPath::getFillType() {
44 return static_cast<int>(path().getFillType());
45}
46
47void CanvasPath::setFillType(int fill_type) {
48 mutable_path().setFillType(static_cast<SkPathFillType>(fill_type));
49 resetVolatility();
50}
51
52void CanvasPath::moveTo(double x, double y) {
53 mutable_path().moveTo(SafeNarrow(x), SafeNarrow(y));
54 resetVolatility();
55}
56
57void CanvasPath::relativeMoveTo(double x, double y) {
58 mutable_path().rMoveTo(SafeNarrow(x), SafeNarrow(y));
59 resetVolatility();
60}
61
62void CanvasPath::lineTo(double x, double y) {
63 mutable_path().lineTo(SafeNarrow(x), SafeNarrow(y));
64 resetVolatility();
65}
66
67void CanvasPath::relativeLineTo(double x, double y) {
68 mutable_path().rLineTo(SafeNarrow(x), SafeNarrow(y));
69 resetVolatility();
70}
71
72void CanvasPath::quadraticBezierTo(double x1, double y1, double x2, double y2) {
73 mutable_path().quadTo(SafeNarrow(x1), SafeNarrow(y1), SafeNarrow(x2),
74 SafeNarrow(y2));
75 resetVolatility();
76}
77
78void CanvasPath::relativeQuadraticBezierTo(double x1,
79 double y1,
80 double x2,
81 double y2) {
82 mutable_path().rQuadTo(SafeNarrow(x1), SafeNarrow(y1), SafeNarrow(x2),
83 SafeNarrow(y2));
84 resetVolatility();
85}
86
87void CanvasPath::cubicTo(double x1,
88 double y1,
89 double x2,
90 double y2,
91 double x3,
92 double y3) {
93 mutable_path().cubicTo(SafeNarrow(x1), SafeNarrow(y1), SafeNarrow(x2),
94 SafeNarrow(y2), SafeNarrow(x3), SafeNarrow(y3));
95 resetVolatility();
96}
97
98void CanvasPath::relativeCubicTo(double x1,
99 double y1,
100 double x2,
101 double y2,
102 double x3,
103 double y3) {
104 mutable_path().rCubicTo(SafeNarrow(x1), SafeNarrow(y1), SafeNarrow(x2),
105 SafeNarrow(y2), SafeNarrow(x3), SafeNarrow(y3));
106 resetVolatility();
107}
108
109void CanvasPath::conicTo(double x1, double y1, double x2, double y2, double w) {
110 mutable_path().conicTo(SafeNarrow(x1), SafeNarrow(y1), SafeNarrow(x2),
111 SafeNarrow(y2), SafeNarrow(w));
112 resetVolatility();
113}
114
115void CanvasPath::relativeConicTo(double x1,
116 double y1,
117 double x2,
118 double y2,
119 double w) {
120 mutable_path().rConicTo(SafeNarrow(x1), SafeNarrow(y1), SafeNarrow(x2),
121 SafeNarrow(y2), SafeNarrow(w));
122 resetVolatility();
123}
124
125void CanvasPath::arcTo(double left,
126 double top,
127 double right,
128 double bottom,
129 double startAngle,
130 double sweepAngle,
131 bool forceMoveTo) {
132 mutable_path().arcTo(
134 SafeNarrow(bottom)),
135 SafeNarrow(startAngle) * 180.0f / static_cast<float>(M_PI),
136 SafeNarrow(sweepAngle) * 180.0f / static_cast<float>(M_PI), forceMoveTo);
137 resetVolatility();
138}
139
140void CanvasPath::arcToPoint(double arcEndX,
141 double arcEndY,
142 double radiusX,
143 double radiusY,
144 double xAxisRotation,
145 bool isLargeArc,
146 bool isClockwiseDirection) {
147 const auto arcSize = isLargeArc ? SkPath::ArcSize::kLarge_ArcSize
148 : SkPath::ArcSize::kSmall_ArcSize;
149 const auto direction =
150 isClockwiseDirection ? SkPathDirection::kCW : SkPathDirection::kCCW;
151
152 mutable_path().arcTo(SafeNarrow(radiusX), SafeNarrow(radiusY),
153 SafeNarrow(xAxisRotation), arcSize, direction,
154 SafeNarrow(arcEndX), SafeNarrow(arcEndY));
155 resetVolatility();
156}
157
158void CanvasPath::relativeArcToPoint(double arcEndDeltaX,
159 double arcEndDeltaY,
160 double radiusX,
161 double radiusY,
162 double xAxisRotation,
163 bool isLargeArc,
164 bool isClockwiseDirection) {
165 const auto arcSize = isLargeArc ? SkPath::ArcSize::kLarge_ArcSize
166 : SkPath::ArcSize::kSmall_ArcSize;
167 const auto direction =
168 isClockwiseDirection ? SkPathDirection::kCW : SkPathDirection::kCCW;
169 mutable_path().rArcTo(SafeNarrow(radiusX), SafeNarrow(radiusY),
170 SafeNarrow(xAxisRotation), arcSize, direction,
171 SafeNarrow(arcEndDeltaX), SafeNarrow(arcEndDeltaY));
172 resetVolatility();
173}
174
175void CanvasPath::addRect(double left, double top, double right, double bottom) {
176 mutable_path().addRect(SkRect::MakeLTRB(SafeNarrow(left), SafeNarrow(top),
178 SafeNarrow(bottom)));
179 resetVolatility();
180}
181
182void CanvasPath::addOval(double left, double top, double right, double bottom) {
183 mutable_path().addOval(SkRect::MakeLTRB(SafeNarrow(left), SafeNarrow(top),
185 SafeNarrow(bottom)));
186 resetVolatility();
187}
188
189void CanvasPath::addArc(double left,
190 double top,
191 double right,
192 double bottom,
193 double startAngle,
194 double sweepAngle) {
195 mutable_path().addArc(
197 SafeNarrow(bottom)),
198 SafeNarrow(startAngle) * 180.0f / static_cast<float>(M_PI),
199 SafeNarrow(sweepAngle) * 180.0f / static_cast<float>(M_PI));
200 resetVolatility();
201}
202
203void CanvasPath::addPolygon(const tonic::Float32List& points, bool close) {
204 mutable_path().addPoly(reinterpret_cast<const SkPoint*>(points.data()),
205 points.num_elements() / 2, close);
206 resetVolatility();
207}
208
209void CanvasPath::addRRect(const RRect& rrect) {
210 mutable_path().addRRect(rrect.sk_rrect);
211 resetVolatility();
212}
213
214void CanvasPath::addPath(CanvasPath* path, double dx, double dy) {
215 if (!path) {
216 Dart_ThrowException(ToDart("Path.addPath called with non-genuine Path."));
217 return;
218 }
219 mutable_path().addPath(path->path(), SafeNarrow(dx), SafeNarrow(dy),
221 resetVolatility();
222}
223
224void CanvasPath::addPathWithMatrix(CanvasPath* path,
225 double dx,
226 double dy,
227 Dart_Handle matrix4_handle) {
228 tonic::Float64List matrix4(matrix4_handle);
229
230 if (!path) {
231 matrix4.Release();
233 ToDart("Path.addPathWithMatrix called with non-genuine Path."));
234 return;
235 }
236
237 SkMatrix matrix = ToSkMatrix(matrix4);
238 matrix4.Release();
239 matrix.setTranslateX(matrix.getTranslateX() + SafeNarrow(dx));
240 matrix.setTranslateY(matrix.getTranslateY() + SafeNarrow(dy));
241 mutable_path().addPath(path->path(), matrix, SkPath::kAppend_AddPathMode);
242 resetVolatility();
243}
244
245void CanvasPath::extendWithPath(CanvasPath* path, double dx, double dy) {
246 if (!path) {
248 ToDart("Path.extendWithPath called with non-genuine Path."));
249 return;
250 }
251 mutable_path().addPath(path->path(), SafeNarrow(dx), SafeNarrow(dy),
253 resetVolatility();
254}
255
256void CanvasPath::extendWithPathAndMatrix(CanvasPath* path,
257 double dx,
258 double dy,
259 Dart_Handle matrix4_handle) {
260 tonic::Float64List matrix4(matrix4_handle);
261
262 if (!path) {
263 matrix4.Release();
265 ToDart("Path.addPathWithMatrix called with non-genuine Path."));
266 return;
267 }
268
269 SkMatrix matrix = ToSkMatrix(matrix4);
270 matrix4.Release();
271 matrix.setTranslateX(matrix.getTranslateX() + SafeNarrow(dx));
272 matrix.setTranslateY(matrix.getTranslateY() + SafeNarrow(dy));
273 mutable_path().addPath(path->path(), matrix, SkPath::kExtend_AddPathMode);
274 resetVolatility();
275}
276
277void CanvasPath::close() {
278 mutable_path().close();
279 resetVolatility();
280}
281
283 mutable_path().reset();
284 resetVolatility();
285}
286
287bool CanvasPath::contains(double x, double y) {
288 return path().contains(SafeNarrow(x), SafeNarrow(y));
289}
290
291void CanvasPath::shift(Dart_Handle path_handle, double dx, double dy) {
292 fml::RefPtr<CanvasPath> path = Create(path_handle);
293 auto& other_mutable_path = path->mutable_path();
294 mutable_path().offset(SafeNarrow(dx), SafeNarrow(dy), &other_mutable_path);
295 resetVolatility();
296}
297
299 Dart_Handle matrix4_handle) {
300 tonic::Float64List matrix4(matrix4_handle);
301 auto sk_matrix = ToSkMatrix(matrix4);
302 matrix4.Release();
303 fml::RefPtr<CanvasPath> path = Create(path_handle);
304 auto& other_mutable_path = path->mutable_path();
305 mutable_path().transform(sk_matrix, &other_mutable_path);
306}
307
308tonic::Float32List CanvasPath::getBounds() {
309 tonic::Float32List rect(Dart_NewTypedData(Dart_TypedData_kFloat32, 4));
310 const SkRect& bounds = path().getBounds();
311 rect[0] = bounds.left();
312 rect[1] = bounds.top();
313 rect[2] = bounds.right();
314 rect[3] = bounds.bottom();
315 return rect;
316}
317
318bool CanvasPath::op(CanvasPath* path1, CanvasPath* path2, int operation) {
319 bool result = Op(path1->path(), path2->path(),
320 static_cast<SkPathOp>(operation), &tracked_path_->path);
321 resetVolatility();
322 return result;
323}
324
325void CanvasPath::clone(Dart_Handle path_handle) {
326 fml::RefPtr<CanvasPath> path = Create(path_handle);
327 // per Skia docs, this will create a fast copy
328 // data is shared until the source path or dest path are mutated
329 path->mutable_path() = this->path();
330}
331
332} // namespace flutter
m reset()
#define M_PI
static const int points[]
static SkPath path1()
static SkPath path2()
static sk_sp< Effect > Create()
Definition: RefCntTest.cpp:117
static void operation(T operation, uint32_t &a, uint32_t b, uint32_t c, uint32_t d, uint32_t x, uint8_t s, uint32_t t)
Definition: SkMD5.cpp:144
SkPathOp
Definition: SkPathOps.h:22
SkPathFillType
Definition: SkPathTypes.h:11
static bool left(const SkPoint &p0, const SkPoint &p1)
static bool right(const SkPoint &p0, const SkPoint &p1)
@ kExtend_AddPathMode
Definition: SkPath.h:1293
@ kAppend_AddPathMode
Definition: SkPath.h:1286
struct _Dart_Handle * Dart_Handle
Definition: dart_api.h:258
DART_EXPORT Dart_Handle Dart_ThrowException(Dart_Handle exception)
@ Dart_TypedData_kFloat32
Definition: dart_api.h:2623
DART_EXPORT Dart_Handle Dart_NewTypedData(Dart_TypedData_Type type, intptr_t length)
SkMatrix sk_matrix
GAsyncResult * result
#define FML_DCHECK(condition)
Definition: logging.h:103
double y
double x
unsigned useCenter Optional< SkMatrix > matrix
Definition: SkRecords.h:258
Optional< SkRect > bounds
Definition: SkRecords.h:189
SkRRect rrect
Definition: SkRecords.h:232
sk_sp< SkBlender > blender SkRect rect
Definition: SkRecords.h:350
SkScalar startAngle
Definition: SkRecords.h:250
SkScalar sweepAngle
Definition: SkRecords.h:251
skia_private::AutoTArray< sk_sp< SkImageFilter > > filters TypedMatrix matrix TypedMatrix matrix SkScalar dx
Definition: SkRecords.h:208
IMPLEMENT_WRAPPERTYPEINFO(flutter_gpu, FlutterGpuTestClass)
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: switches.h:57
static float SafeNarrow(double value)
CanvasPath Path
Definition: dart_ui.cc:58
constexpr SkMatrix ToSkMatrix(const DlMatrix &matrix)
constexpr bool contains(std::string_view str, std::string_view needle)
Definition: SkStringView.h:41
Definition: ref_ptr.h:256
Dart_Handle ToDart(const T &object)
static SkColor4f transform(SkColor4f c, SkColorSpace *src, SkColorSpace *dst)
Definition: p3.cpp:47
SkScalar w
static constexpr SkRect MakeLTRB(float l, float t, float r, float b)
Definition: SkRect.h:646