@@ -67,43 +67,69 @@ void CanvasPath::RegisterNatives(tonic::DartLibraryNatives* natives) {
6767 FOR_EACH_BINDING (DART_REGISTER_NATIVE)});
6868}
6969
70- CanvasPath::CanvasPath () {}
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+ }
7187
72- CanvasPath::~CanvasPath () {}
88+ void CanvasPath::ReleaseDartWrappableReference () const {
89+ FML_DCHECK (path_tracker_);
90+ path_tracker_->Erase (tracked_path_);
91+ }
7392
7493int CanvasPath::getFillType () {
75- return static_cast <int >(path_ .getFillType ());
94+ return static_cast <int >(path () .getFillType ());
7695}
7796
7897void CanvasPath::setFillType (int fill_type) {
79- path_.setFillType (static_cast <SkPathFillType>(fill_type));
98+ mutable_path ().setFillType (static_cast <SkPathFillType>(fill_type));
99+ resetVolatility ();
80100}
81101
82102void CanvasPath::moveTo (float x, float y) {
83- path_.moveTo (x, y);
103+ mutable_path ().moveTo (x, y);
104+ resetVolatility ();
84105}
85106
86107void CanvasPath::relativeMoveTo (float x, float y) {
87- path_.rMoveTo (x, y);
108+ mutable_path ().rMoveTo (x, y);
109+ resetVolatility ();
88110}
89111
90112void CanvasPath::lineTo (float x, float y) {
91- path_.lineTo (x, y);
113+ mutable_path ().lineTo (x, y);
114+ resetVolatility ();
92115}
93116
94117void CanvasPath::relativeLineTo (float x, float y) {
95- path_.rLineTo (x, y);
118+ mutable_path ().rLineTo (x, y);
119+ resetVolatility ();
96120}
97121
98122void CanvasPath::quadraticBezierTo (float x1, float y1, float x2, float y2) {
99- path_.quadTo (x1, y1, x2, y2);
123+ mutable_path ().quadTo (x1, y1, x2, y2);
124+ resetVolatility ();
100125}
101126
102127void CanvasPath::relativeQuadraticBezierTo (float x1,
103128 float y1,
104129 float x2,
105130 float y2) {
106- path_.rQuadTo (x1, y1, x2, y2);
131+ mutable_path ().rQuadTo (x1, y1, x2, y2);
132+ resetVolatility ();
107133}
108134
109135void CanvasPath::cubicTo (float x1,
@@ -112,7 +138,8 @@ void CanvasPath::cubicTo(float x1,
112138 float y2,
113139 float x3,
114140 float y3) {
115- path_.cubicTo (x1, y1, x2, y2, x3, y3);
141+ mutable_path ().cubicTo (x1, y1, x2, y2, x3, y3);
142+ resetVolatility ();
116143}
117144
118145void CanvasPath::relativeCubicTo (float x1,
@@ -121,19 +148,22 @@ void CanvasPath::relativeCubicTo(float x1,
121148 float y2,
122149 float x3,
123150 float y3) {
124- path_.rCubicTo (x1, y1, x2, y2, x3, y3);
151+ mutable_path ().rCubicTo (x1, y1, x2, y2, x3, y3);
152+ resetVolatility ();
125153}
126154
127155void CanvasPath::conicTo (float x1, float y1, float x2, float y2, float w) {
128- path_.conicTo (x1, y1, x2, y2, w);
156+ mutable_path ().conicTo (x1, y1, x2, y2, w);
157+ resetVolatility ();
129158}
130159
131160void CanvasPath::relativeConicTo (float x1,
132161 float y1,
133162 float x2,
134163 float y2,
135164 float w) {
136- path_.rConicTo (x1, y1, x2, y2, w);
165+ mutable_path ().rConicTo (x1, y1, x2, y2, w);
166+ resetVolatility ();
137167}
138168
139169void CanvasPath::arcTo (float left,
@@ -143,9 +173,10 @@ void CanvasPath::arcTo(float left,
143173 float startAngle,
144174 float sweepAngle,
145175 bool forceMoveTo) {
146- path_.arcTo (SkRect::MakeLTRB (left, top, right, bottom),
147- startAngle * 180.0 / M_PI, sweepAngle * 180.0 / M_PI,
148- forceMoveTo);
176+ mutable_path ().arcTo (SkRect::MakeLTRB (left, top, right, bottom),
177+ startAngle * 180.0 / M_PI, sweepAngle * 180.0 / M_PI,
178+ forceMoveTo);
179+ resetVolatility ();
149180}
150181
151182void CanvasPath::arcToPoint (float arcEndX,
@@ -160,8 +191,9 @@ void CanvasPath::arcToPoint(float arcEndX,
160191 const auto direction =
161192 isClockwiseDirection ? SkPathDirection::kCW : SkPathDirection::kCCW ;
162193
163- path_.arcTo (radiusX, radiusY, xAxisRotation, arcSize, direction, arcEndX,
164- arcEndY);
194+ mutable_path ().arcTo (radiusX, radiusY, xAxisRotation, arcSize, direction,
195+ arcEndX, arcEndY);
196+ resetVolatility ();
165197}
166198
167199void CanvasPath::relativeArcToPoint (float arcEndDeltaX,
@@ -175,16 +207,19 @@ void CanvasPath::relativeArcToPoint(float arcEndDeltaX,
175207 : SkPath::ArcSize::kSmall_ArcSize ;
176208 const auto direction =
177209 isClockwiseDirection ? SkPathDirection::kCW : SkPathDirection::kCCW ;
178- path_.rArcTo (radiusX, radiusY, xAxisRotation, arcSize, direction,
179- arcEndDeltaX, arcEndDeltaY);
210+ mutable_path ().rArcTo (radiusX, radiusY, xAxisRotation, arcSize, direction,
211+ arcEndDeltaX, arcEndDeltaY);
212+ resetVolatility ();
180213}
181214
182215void CanvasPath::addRect (float left, float top, float right, float bottom) {
183- path_.addRect (SkRect::MakeLTRB (left, top, right, bottom));
216+ mutable_path ().addRect (SkRect::MakeLTRB (left, top, right, bottom));
217+ resetVolatility ();
184218}
185219
186220void CanvasPath::addOval (float left, float top, float right, float bottom) {
187- path_.addOval (SkRect::MakeLTRB (left, top, right, bottom));
221+ mutable_path ().addOval (SkRect::MakeLTRB (left, top, right, bottom));
222+ resetVolatility ();
188223}
189224
190225void CanvasPath::addArc (float left,
@@ -193,25 +228,29 @@ void CanvasPath::addArc(float left,
193228 float bottom,
194229 float startAngle,
195230 float sweepAngle) {
196- path_.addArc (SkRect::MakeLTRB (left, top, right, bottom),
197- startAngle * 180.0 / M_PI, sweepAngle * 180.0 / M_PI);
231+ mutable_path ().addArc (SkRect::MakeLTRB (left, top, right, bottom),
232+ startAngle * 180.0 / M_PI, sweepAngle * 180.0 / M_PI);
233+ resetVolatility ();
198234}
199235
200236void CanvasPath::addPolygon (const tonic::Float32List& points, bool close) {
201- path_.addPoly (reinterpret_cast <const SkPoint*>(points.data ()),
202- points.num_elements () / 2 , close);
237+ mutable_path ().addPoly (reinterpret_cast <const SkPoint*>(points.data ()),
238+ points.num_elements () / 2 , close);
239+ resetVolatility ();
203240}
204241
205242void CanvasPath::addRRect (const RRect& rrect) {
206- path_.addRRect (rrect.sk_rrect );
243+ mutable_path ().addRRect (rrect.sk_rrect );
244+ resetVolatility ();
207245}
208246
209247void CanvasPath::addPath (CanvasPath* path, double dx, double dy) {
210248 if (!path) {
211249 Dart_ThrowException (ToDart (" Path.addPath called with non-genuine Path." ));
212250 return ;
213251 }
214- path_.addPath (path->path (), dx, dy, SkPath::kAppend_AddPathMode );
252+ mutable_path ().addPath (path->path (), dx, dy, SkPath::kAppend_AddPathMode );
253+ resetVolatility ();
215254}
216255
217256void CanvasPath::addPathWithMatrix (CanvasPath* path,
@@ -227,8 +266,9 @@ void CanvasPath::addPathWithMatrix(CanvasPath* path,
227266 SkMatrix matrix = ToSkMatrix (matrix4);
228267 matrix.setTranslateX (matrix.getTranslateX () + dx);
229268 matrix.setTranslateY (matrix.getTranslateY () + dy);
230- path_ .addPath (path->path (), matrix, SkPath::kAppend_AddPathMode );
269+ mutable_path () .addPath (path->path (), matrix, SkPath::kAppend_AddPathMode );
231270 matrix4.Release ();
271+ resetVolatility ();
232272}
233273
234274void CanvasPath::extendWithPath (CanvasPath* path, double dx, double dy) {
@@ -237,7 +277,8 @@ void CanvasPath::extendWithPath(CanvasPath* path, double dx, double dy) {
237277 ToDart (" Path.extendWithPath called with non-genuine Path." ));
238278 return ;
239279 }
240- path_.addPath (path->path (), dx, dy, SkPath::kExtend_AddPathMode );
280+ mutable_path ().addPath (path->path (), dx, dy, SkPath::kExtend_AddPathMode );
281+ resetVolatility ();
241282}
242283
243284void CanvasPath::extendWithPathAndMatrix (CanvasPath* path,
@@ -253,37 +294,43 @@ void CanvasPath::extendWithPathAndMatrix(CanvasPath* path,
253294 SkMatrix matrix = ToSkMatrix (matrix4);
254295 matrix.setTranslateX (matrix.getTranslateX () + dx);
255296 matrix.setTranslateY (matrix.getTranslateY () + dy);
256- path_ .addPath (path->path (), matrix, SkPath::kExtend_AddPathMode );
297+ mutable_path () .addPath (path->path (), matrix, SkPath::kExtend_AddPathMode );
257298 matrix4.Release ();
299+ resetVolatility ();
258300}
259301
260302void CanvasPath::close () {
261- path_.close ();
303+ mutable_path ().close ();
304+ resetVolatility ();
262305}
263306
264307void CanvasPath::reset () {
265- path_.reset ();
308+ mutable_path ().reset ();
309+ resetVolatility ();
266310}
267311
268312bool CanvasPath::contains (double x, double y) {
269- return path_ .contains (x, y);
313+ return path () .contains (x, y);
270314}
271315
272316void CanvasPath::shift (Dart_Handle path_handle, double dx, double dy) {
273317 fml::RefPtr<CanvasPath> path = CanvasPath::Create (path_handle);
274- path_.offset (dx, dy, &path->path_ );
318+ auto & other_mutable_path = path->mutable_path ();
319+ mutable_path ().offset (dx, dy, &other_mutable_path);
320+ resetVolatility ();
275321}
276322
277323void CanvasPath::transform (Dart_Handle path_handle,
278324 tonic::Float64List& matrix4) {
279325 fml::RefPtr<CanvasPath> path = CanvasPath::Create (path_handle);
280- path_.transform (ToSkMatrix (matrix4), &path->path_ );
326+ auto & other_mutable_path = path->mutable_path ();
327+ mutable_path ().transform (ToSkMatrix (matrix4), &other_mutable_path);
281328 matrix4.Release ();
282329}
283330
284331tonic::Float32List CanvasPath::getBounds () {
285332 tonic::Float32List rect (Dart_NewTypedData (Dart_TypedData_kFloat32, 4 ));
286- const SkRect& bounds = path_ .getBounds ();
333+ const SkRect& bounds = path () .getBounds ();
287334 rect[0 ] = bounds.left ();
288335 rect[1 ] = bounds.top ();
289336 rect[2 ] = bounds.right ();
@@ -293,21 +340,22 @@ tonic::Float32List CanvasPath::getBounds() {
293340
294341bool CanvasPath::op (CanvasPath* path1, CanvasPath* path2, int operation) {
295342 return Op (path1->path (), path2->path (), static_cast <SkPathOp>(operation),
296- &path_);
343+ &tracked_path_->path );
344+ resetVolatility ();
297345}
298346
299347void CanvasPath::clone (Dart_Handle path_handle) {
300348 fml::RefPtr<CanvasPath> path = CanvasPath::Create (path_handle);
301349 // per Skia docs, this will create a fast copy
302350 // data is shared until the source path or dest path are mutated
303- path->path_ = path_ ;
351+ path->mutable_path () = this -> path () ;
304352}
305353
306354// This is doomed to be called too early, since Paths are mutable.
307355// However, it can help for some of the clone/shift/transform type methods
308356// where the resultant path will initially have a meaningful size.
309357size_t CanvasPath::GetAllocationSize () const {
310- return sizeof (CanvasPath) + path_ .approximateBytesUsed ();
358+ return sizeof (CanvasPath) + path () .approximateBytesUsed ();
311359}
312360
313361} // namespace flutter
0 commit comments