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/painting/matrix.h"
10 #include "flutter/lib/ui/ui_dart_state.h"
15 
16 using tonic::ToDart;
17 
18 namespace flutter {
19 
20 typedef CanvasPath Path;
21 
22 static void Path_constructor(Dart_NativeArguments args) {
25 }
26 
28 
29 #define FOR_EACH_BINDING(V) \
30  V(Path, addArc) \
31  V(Path, addOval) \
32  V(Path, addPath) \
33  V(Path, addPolygon) \
34  V(Path, addRect) \
35  V(Path, addRRect) \
36  V(Path, arcTo) \
37  V(Path, arcToPoint) \
38  V(Path, close) \
39  V(Path, conicTo) \
40  V(Path, contains) \
41  V(Path, cubicTo) \
42  V(Path, extendWithPath) \
43  V(Path, extendWithPathAndMatrix) \
44  V(Path, getFillType) \
45  V(Path, lineTo) \
46  V(Path, moveTo) \
47  V(Path, quadraticBezierTo) \
48  V(Path, relativeArcToPoint) \
49  V(Path, relativeConicTo) \
50  V(Path, relativeCubicTo) \
51  V(Path, relativeLineTo) \
52  V(Path, relativeMoveTo) \
53  V(Path, relativeQuadraticBezierTo) \
54  V(Path, reset) \
55  V(Path, setFillType) \
56  V(Path, shift) \
57  V(Path, transform) \
58  V(Path, getBounds) \
59  V(Path, addPathWithMatrix) \
60  V(Path, op) \
61  V(Path, clone)
62 
64 
65 void CanvasPath::RegisterNatives(tonic::DartLibraryNatives* natives) {
66  natives->Register({{"Path_constructor", Path_constructor, 1, true},
68 }
69 
70 CanvasPath::CanvasPath()
71  : path_tracker_(UIDartState::Current()->GetVolatilePathTracker()),
72  tracked_path_(std::make_shared<VolatilePathTracker::TrackedPath>()) {
73  FML_DCHECK(path_tracker_);
74  resetVolatility();
75 }
76 
77 CanvasPath::~CanvasPath() = default;
78 
79 void CanvasPath::resetVolatility() {
80  if (!tracked_path_->tracking_volatility) {
81  mutable_path().setIsVolatile(true);
82  tracked_path_->frame_count = 0;
83  tracked_path_->tracking_volatility = true;
84  path_tracker_->Insert(tracked_path_);
85  }
86 }
87 
89  FML_DCHECK(path_tracker_);
90  path_tracker_->Erase(tracked_path_);
92 }
93 
95  return static_cast<int>(path().getFillType());
96 }
97 
98 void CanvasPath::setFillType(int fill_type) {
99  mutable_path().setFillType(static_cast<SkPathFillType>(fill_type));
100  resetVolatility();
101 }
102 
103 void CanvasPath::moveTo(float x, float y) {
104  mutable_path().moveTo(x, y);
105  resetVolatility();
106 }
107 
108 void CanvasPath::relativeMoveTo(float x, float y) {
109  mutable_path().rMoveTo(x, y);
110  resetVolatility();
111 }
112 
113 void CanvasPath::lineTo(float x, float y) {
114  mutable_path().lineTo(x, y);
115  resetVolatility();
116 }
117 
118 void CanvasPath::relativeLineTo(float x, float y) {
119  mutable_path().rLineTo(x, y);
120  resetVolatility();
121 }
122 
123 void CanvasPath::quadraticBezierTo(float x1, float y1, float x2, float y2) {
124  mutable_path().quadTo(x1, y1, x2, y2);
125  resetVolatility();
126 }
127 
129  float y1,
130  float x2,
131  float y2) {
132  mutable_path().rQuadTo(x1, y1, x2, y2);
133  resetVolatility();
134 }
135 
136 void CanvasPath::cubicTo(float x1,
137  float y1,
138  float x2,
139  float y2,
140  float x3,
141  float y3) {
142  mutable_path().cubicTo(x1, y1, x2, y2, x3, y3);
143  resetVolatility();
144 }
145 
147  float y1,
148  float x2,
149  float y2,
150  float x3,
151  float y3) {
152  mutable_path().rCubicTo(x1, y1, x2, y2, x3, y3);
153  resetVolatility();
154 }
155 
156 void CanvasPath::conicTo(float x1, float y1, float x2, float y2, float w) {
157  mutable_path().conicTo(x1, y1, x2, y2, w);
158  resetVolatility();
159 }
160 
162  float y1,
163  float x2,
164  float y2,
165  float w) {
166  mutable_path().rConicTo(x1, y1, x2, y2, w);
167  resetVolatility();
168 }
169 
170 void CanvasPath::arcTo(float left,
171  float top,
172  float right,
173  float bottom,
174  float startAngle,
175  float sweepAngle,
176  bool forceMoveTo) {
177  mutable_path().arcTo(SkRect::MakeLTRB(left, top, right, bottom),
178  startAngle * 180.0 / M_PI, sweepAngle * 180.0 / M_PI,
179  forceMoveTo);
180  resetVolatility();
181 }
182 
183 void CanvasPath::arcToPoint(float arcEndX,
184  float arcEndY,
185  float radiusX,
186  float radiusY,
187  float xAxisRotation,
188  bool isLargeArc,
189  bool isClockwiseDirection) {
190  const auto arcSize = isLargeArc ? SkPath::ArcSize::kLarge_ArcSize
191  : SkPath::ArcSize::kSmall_ArcSize;
192  const auto direction =
193  isClockwiseDirection ? SkPathDirection::kCW : SkPathDirection::kCCW;
194 
195  mutable_path().arcTo(radiusX, radiusY, xAxisRotation, arcSize, direction,
196  arcEndX, arcEndY);
197  resetVolatility();
198 }
199 
200 void CanvasPath::relativeArcToPoint(float arcEndDeltaX,
201  float arcEndDeltaY,
202  float radiusX,
203  float radiusY,
204  float xAxisRotation,
205  bool isLargeArc,
206  bool isClockwiseDirection) {
207  const auto arcSize = isLargeArc ? SkPath::ArcSize::kLarge_ArcSize
208  : SkPath::ArcSize::kSmall_ArcSize;
209  const auto direction =
210  isClockwiseDirection ? SkPathDirection::kCW : SkPathDirection::kCCW;
211  mutable_path().rArcTo(radiusX, radiusY, xAxisRotation, arcSize, direction,
212  arcEndDeltaX, arcEndDeltaY);
213  resetVolatility();
214 }
215 
216 void CanvasPath::addRect(float left, float top, float right, float bottom) {
217  mutable_path().addRect(SkRect::MakeLTRB(left, top, right, bottom));
218  resetVolatility();
219 }
220 
221 void CanvasPath::addOval(float left, float top, float right, float bottom) {
222  mutable_path().addOval(SkRect::MakeLTRB(left, top, right, bottom));
223  resetVolatility();
224 }
225 
226 void CanvasPath::addArc(float left,
227  float top,
228  float right,
229  float bottom,
230  float startAngle,
231  float sweepAngle) {
232  mutable_path().addArc(SkRect::MakeLTRB(left, top, right, bottom),
233  startAngle * 180.0 / M_PI, sweepAngle * 180.0 / M_PI);
234  resetVolatility();
235 }
236 
237 void CanvasPath::addPolygon(const tonic::Float32List& points, bool close) {
238  mutable_path().addPoly(reinterpret_cast<const SkPoint*>(points.data()),
239  points.num_elements() / 2, close);
240  resetVolatility();
241 }
242 
243 void CanvasPath::addRRect(const RRect& rrect) {
244  mutable_path().addRRect(rrect.sk_rrect);
245  resetVolatility();
246 }
247 
248 void CanvasPath::addPath(CanvasPath* path, double dx, double dy) {
249  if (!path) {
250  Dart_ThrowException(ToDart("Path.addPath called with non-genuine Path."));
251  return;
252  }
253  mutable_path().addPath(path->path(), dx, dy, SkPath::kAppend_AddPathMode);
254  resetVolatility();
255 }
256 
258  double dx,
259  double dy,
260  tonic::Float64List& matrix4) {
261  if (!path) {
262  Dart_ThrowException(
263  ToDart("Path.addPathWithMatrix called with non-genuine Path."));
264  return;
265  }
266 
267  SkMatrix matrix = ToSkMatrix(matrix4);
268  matrix.setTranslateX(matrix.getTranslateX() + dx);
269  matrix.setTranslateY(matrix.getTranslateY() + dy);
270  mutable_path().addPath(path->path(), matrix, SkPath::kAppend_AddPathMode);
271  matrix4.Release();
272  resetVolatility();
273 }
274 
275 void CanvasPath::extendWithPath(CanvasPath* path, double dx, double dy) {
276  if (!path) {
277  Dart_ThrowException(
278  ToDart("Path.extendWithPath called with non-genuine Path."));
279  return;
280  }
281  mutable_path().addPath(path->path(), dx, dy, SkPath::kExtend_AddPathMode);
282  resetVolatility();
283 }
284 
286  double dx,
287  double dy,
288  tonic::Float64List& matrix4) {
289  if (!path) {
290  Dart_ThrowException(
291  ToDart("Path.addPathWithMatrix called with non-genuine Path."));
292  return;
293  }
294 
295  SkMatrix matrix = ToSkMatrix(matrix4);
296  matrix.setTranslateX(matrix.getTranslateX() + dx);
297  matrix.setTranslateY(matrix.getTranslateY() + dy);
298  mutable_path().addPath(path->path(), matrix, SkPath::kExtend_AddPathMode);
299  matrix4.Release();
300  resetVolatility();
301 }
302 
304  mutable_path().close();
305  resetVolatility();
306 }
307 
309  mutable_path().reset();
310  resetVolatility();
311 }
312 
313 bool CanvasPath::contains(double x, double y) {
314  return path().contains(x, y);
315 }
316 
317 void CanvasPath::shift(Dart_Handle path_handle, double dx, double dy) {
319  auto& other_mutable_path = path->mutable_path();
320  mutable_path().offset(dx, dy, &other_mutable_path);
321  resetVolatility();
322 }
323 
324 void CanvasPath::transform(Dart_Handle path_handle,
325  tonic::Float64List& matrix4) {
327  auto& other_mutable_path = path->mutable_path();
328  mutable_path().transform(ToSkMatrix(matrix4), &other_mutable_path);
329  matrix4.Release();
330 }
331 
332 tonic::Float32List CanvasPath::getBounds() {
333  tonic::Float32List rect(Dart_NewTypedData(Dart_TypedData_kFloat32, 4));
334  const SkRect& bounds = path().getBounds();
335  rect[0] = bounds.left();
336  rect[1] = bounds.top();
337  rect[2] = bounds.right();
338  rect[3] = bounds.bottom();
339  return rect;
340 }
341 
342 bool CanvasPath::op(CanvasPath* path1, CanvasPath* path2, int operation) {
343  return Op(path1->path(), path2->path(), static_cast<SkPathOp>(operation),
344  &tracked_path_->path);
345  resetVolatility();
346 }
347 
348 void CanvasPath::clone(Dart_Handle path_handle) {
350  // per Skia docs, this will create a fast copy
351  // data is shared until the source path or dest path are mutated
352  path->mutable_path() = this->path();
353 }
354 
355 // This is doomed to be called too early, since Paths are mutable.
356 // However, it can help for some of the clone/shift/transform type methods
357 // where the resultant path will initially have a meaningful size.
359  return sizeof(CanvasPath) + path().approximateBytesUsed();
360 }
361 
362 } // namespace flutter
virtual void ReleaseDartWrappableReference() const override
Definition: path.cc:88
virtual void ReleaseDartWrappableReference() const override
Definition: dart_wrapper.h:21
G_BEGIN_DECLS FlValue * args
SkRRect sk_rrect
Definition: rrect.h:16
void arcTo(float left, float top, float right, float bottom, float startAngle, float sweepAngle, bool forceMoveTo)
Definition: path.cc:170
static fml::RefPtr< CanvasPath > Create(Dart_Handle path_handle)
Definition: path.h:31
void cubicTo(float x1, float y1, float x2, float y2, float x3, float y3)
Definition: path.cc:136
#define FML_DCHECK(condition)
Definition: logging.h:86
void moveTo(float x, float y)
Definition: path.cc:103
void DartCallConstructor(Sig func, Dart_NativeArguments args)
Definition: dart_args.h:218
void conicTo(float x1, float y1, float x2, float y2, float w)
Definition: path.cc:156
bool op(CanvasPath *path1, CanvasPath *path2, int operation)
Definition: path.cc:342
#define DART_NATIVE_CALLBACK(CLASS, METHOD)
static void Path_constructor(Dart_NativeArguments args)
Definition: path.cc:22
#define FOR_EACH_BINDING(V)
Definition: path.cc:29
void addPath(CanvasPath *path, double dx, double dy)
Definition: path.cc:248
void clone(Dart_Handle path_handle)
Definition: path.cc:348
size_t GetAllocationSize() const override
Definition: path.cc:358
void relativeConicTo(float x1, float y1, float x2, float y2, float w)
Definition: path.cc:161
void addOval(float left, float top, float right, float bottom)
Definition: path.cc:221
void extendWithPathAndMatrix(CanvasPath *path, double dx, double dy, tonic::Float64List &matrix4)
Definition: path.cc:285
void addArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle)
Definition: path.cc:226
void lineTo(float x, float y)
Definition: path.cc:113
IMPLEMENT_WRAPPERTYPEINFO(ui, Scene)
const SkPath & path() const
Definition: path.h:112
void relativeCubicTo(float x1, float y1, float x2, float y2, float x3, float y3)
Definition: path.cc:146
void shift(Dart_Handle path_handle, double dx, double dy)
Definition: path.cc:317
static void ThrowIfUIOperationsProhibited()
void addRect(float left, float top, float right, float bottom)
Definition: path.cc:216
void addPathWithMatrix(CanvasPath *path, double dx, double dy, tonic::Float64List &matrix4)
Definition: path.cc:257
void arcToPoint(float arcEndX, float arcEndY, float radiusX, float radiusY, float xAxisRotation, bool isLargeArc, bool isClockwiseDirection)
Definition: path.cc:183
void relativeLineTo(float x, float y)
Definition: path.cc:118
int getFillType()
Definition: path.cc:94
void addPolygon(const tonic::Float32List &points, bool close)
Definition: path.cc:237
void extendWithPath(CanvasPath *path, double dx, double dy)
Definition: path.cc:275
void relativeArcToPoint(float arcEndDeltaX, float arcEndDeltaY, float radiusX, float radiusY, float xAxisRotation, bool isLargeArc, bool isClockwiseDirection)
Definition: path.cc:200
static fml::RefPtr< CanvasPath > CreateNew(Dart_Handle path_handle)
Definition: path.h:27
void setFillType(int fill_type)
Definition: path.cc:98
#define DART_REGISTER_NATIVE(CLASS, METHOD)
void quadraticBezierTo(float x1, float y1, float x2, float y2)
Definition: path.cc:123
void transform(Dart_Handle path_handle, tonic::Float64List &matrix4)
Definition: path.cc:324
Dart_Handle ToDart(const T &object)
void relativeQuadraticBezierTo(float x1, float y1, float x2, float y2)
Definition: path.cc:128
SkMatrix ToSkMatrix(const tonic::Float64List &matrix4)
Definition: matrix.cc:20
void relativeMoveTo(float x, float y)
Definition: path.cc:108
bool contains(double x, double y)
Definition: path.cc:313
void addRRect(const RRect &rrect)
Definition: path.cc:243
CanvasPath Path
Definition: path.cc:20
tonic::Float32List getBounds()
Definition: path.cc:332
static UIDartState * Current()
~CanvasPath() override