@@ -67,43 +67,70 @@ 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+ RefCountedDartWrappable::ReleaseDartWrappableReference ();
92+ }
7393
7494int CanvasPath::getFillType () {
75- return static_cast <int >(path_ .getFillType ());
95+ return static_cast <int >(path () .getFillType ());
7696}
7797
7898void CanvasPath::setFillType (int fill_type) {
79- path_.setFillType (static_cast <SkPathFillType>(fill_type));
99+ mutable_path ().setFillType (static_cast <SkPathFillType>(fill_type));
100+ resetVolatility ();
80101}
81102
82103void CanvasPath::moveTo (float x, float y) {
83- path_.moveTo (x, y);
104+ mutable_path ().moveTo (x, y);
105+ resetVolatility ();
84106}
85107
86108void CanvasPath::relativeMoveTo (float x, float y) {
87- path_.rMoveTo (x, y);
109+ mutable_path ().rMoveTo (x, y);
110+ resetVolatility ();
88111}
89112
90113void CanvasPath::lineTo (float x, float y) {
91- path_.lineTo (x, y);
114+ mutable_path ().lineTo (x, y);
115+ resetVolatility ();
92116}
93117
94118void CanvasPath::relativeLineTo (float x, float y) {
95- path_.rLineTo (x, y);
119+ mutable_path ().rLineTo (x, y);
120+ resetVolatility ();
96121}
97122
98123void CanvasPath::quadraticBezierTo (float x1, float y1, float x2, float y2) {
99- path_.quadTo (x1, y1, x2, y2);
124+ mutable_path ().quadTo (x1, y1, x2, y2);
125+ resetVolatility ();
100126}
101127
102128void CanvasPath::relativeQuadraticBezierTo (float x1,
103129 float y1,
104130 float x2,
105131 float y2) {
106- path_.rQuadTo (x1, y1, x2, y2);
132+ mutable_path ().rQuadTo (x1, y1, x2, y2);
133+ resetVolatility ();
107134}
108135
109136void CanvasPath::cubicTo (float x1,
@@ -112,7 +139,8 @@ void CanvasPath::cubicTo(float x1,
112139 float y2,
113140 float x3,
114141 float y3) {
115- path_.cubicTo (x1, y1, x2, y2, x3, y3);
142+ mutable_path ().cubicTo (x1, y1, x2, y2, x3, y3);
143+ resetVolatility ();
116144}
117145
118146void CanvasPath::relativeCubicTo (float x1,
@@ -121,19 +149,22 @@ void CanvasPath::relativeCubicTo(float x1,
121149 float y2,
122150 float x3,
123151 float y3) {
124- path_.rCubicTo (x1, y1, x2, y2, x3, y3);
152+ mutable_path ().rCubicTo (x1, y1, x2, y2, x3, y3);
153+ resetVolatility ();
125154}
126155
127156void CanvasPath::conicTo (float x1, float y1, float x2, float y2, float w) {
128- path_.conicTo (x1, y1, x2, y2, w);
157+ mutable_path ().conicTo (x1, y1, x2, y2, w);
158+ resetVolatility ();
129159}
130160
131161void CanvasPath::relativeConicTo (float x1,
132162 float y1,
133163 float x2,
134164 float y2,
135165 float w) {
136- path_.rConicTo (x1, y1, x2, y2, w);
166+ mutable_path ().rConicTo (x1, y1, x2, y2, w);
167+ resetVolatility ();
137168}
138169
139170void CanvasPath::arcTo (float left,
@@ -143,9 +174,10 @@ void CanvasPath::arcTo(float left,
143174 float startAngle,
144175 float sweepAngle,
145176 bool forceMoveTo) {
146- path_.arcTo (SkRect::MakeLTRB (left, top, right, bottom),
147- startAngle * 180.0 / M_PI, sweepAngle * 180.0 / M_PI,
148- 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 ();
149181}
150182
151183void CanvasPath::arcToPoint (float arcEndX,
@@ -160,8 +192,9 @@ void CanvasPath::arcToPoint(float arcEndX,
160192 const auto direction =
161193 isClockwiseDirection ? SkPathDirection::kCW : SkPathDirection::kCCW ;
162194
163- path_.arcTo (radiusX, radiusY, xAxisRotation, arcSize, direction, arcEndX,
164- arcEndY);
195+ mutable_path ().arcTo (radiusX, radiusY, xAxisRotation, arcSize, direction,
196+ arcEndX, arcEndY);
197+ resetVolatility ();
165198}
166199
167200void CanvasPath::relativeArcToPoint (float arcEndDeltaX,
@@ -175,16 +208,19 @@ void CanvasPath::relativeArcToPoint(float arcEndDeltaX,
175208 : SkPath::ArcSize::kSmall_ArcSize ;
176209 const auto direction =
177210 isClockwiseDirection ? SkPathDirection::kCW : SkPathDirection::kCCW ;
178- path_.rArcTo (radiusX, radiusY, xAxisRotation, arcSize, direction,
179- arcEndDeltaX, arcEndDeltaY);
211+ mutable_path ().rArcTo (radiusX, radiusY, xAxisRotation, arcSize, direction,
212+ arcEndDeltaX, arcEndDeltaY);
213+ resetVolatility ();
180214}
181215
182216void CanvasPath::addRect (float left, float top, float right, float bottom) {
183- path_.addRect (SkRect::MakeLTRB (left, top, right, bottom));
217+ mutable_path ().addRect (SkRect::MakeLTRB (left, top, right, bottom));
218+ resetVolatility ();
184219}
185220
186221void CanvasPath::addOval (float left, float top, float right, float bottom) {
187- path_.addOval (SkRect::MakeLTRB (left, top, right, bottom));
222+ mutable_path ().addOval (SkRect::MakeLTRB (left, top, right, bottom));
223+ resetVolatility ();
188224}
189225
190226void CanvasPath::addArc (float left,
@@ -193,25 +229,29 @@ void CanvasPath::addArc(float left,
193229 float bottom,
194230 float startAngle,
195231 float sweepAngle) {
196- path_.addArc (SkRect::MakeLTRB (left, top, right, bottom),
197- startAngle * 180.0 / M_PI, sweepAngle * 180.0 / M_PI);
232+ mutable_path ().addArc (SkRect::MakeLTRB (left, top, right, bottom),
233+ startAngle * 180.0 / M_PI, sweepAngle * 180.0 / M_PI);
234+ resetVolatility ();
198235}
199236
200237void CanvasPath::addPolygon (const tonic::Float32List& points, bool close) {
201- path_.addPoly (reinterpret_cast <const SkPoint*>(points.data ()),
202- points.num_elements () / 2 , close);
238+ mutable_path ().addPoly (reinterpret_cast <const SkPoint*>(points.data ()),
239+ points.num_elements () / 2 , close);
240+ resetVolatility ();
203241}
204242
205243void CanvasPath::addRRect (const RRect& rrect) {
206- path_.addRRect (rrect.sk_rrect );
244+ mutable_path ().addRRect (rrect.sk_rrect );
245+ resetVolatility ();
207246}
208247
209248void CanvasPath::addPath (CanvasPath* path, double dx, double dy) {
210249 if (!path) {
211250 Dart_ThrowException (ToDart (" Path.addPath called with non-genuine Path." ));
212251 return ;
213252 }
214- path_.addPath (path->path (), dx, dy, SkPath::kAppend_AddPathMode );
253+ mutable_path ().addPath (path->path (), dx, dy, SkPath::kAppend_AddPathMode );
254+ resetVolatility ();
215255}
216256
217257void CanvasPath::addPathWithMatrix (CanvasPath* path,
@@ -227,8 +267,9 @@ void CanvasPath::addPathWithMatrix(CanvasPath* path,
227267 SkMatrix matrix = ToSkMatrix (matrix4);
228268 matrix.setTranslateX (matrix.getTranslateX () + dx);
229269 matrix.setTranslateY (matrix.getTranslateY () + dy);
230- path_ .addPath (path->path (), matrix, SkPath::kAppend_AddPathMode );
270+ mutable_path () .addPath (path->path (), matrix, SkPath::kAppend_AddPathMode );
231271 matrix4.Release ();
272+ resetVolatility ();
232273}
233274
234275void CanvasPath::extendWithPath (CanvasPath* path, double dx, double dy) {
@@ -237,7 +278,8 @@ void CanvasPath::extendWithPath(CanvasPath* path, double dx, double dy) {
237278 ToDart (" Path.extendWithPath called with non-genuine Path." ));
238279 return ;
239280 }
240- path_.addPath (path->path (), dx, dy, SkPath::kExtend_AddPathMode );
281+ mutable_path ().addPath (path->path (), dx, dy, SkPath::kExtend_AddPathMode );
282+ resetVolatility ();
241283}
242284
243285void CanvasPath::extendWithPathAndMatrix (CanvasPath* path,
@@ -253,37 +295,43 @@ void CanvasPath::extendWithPathAndMatrix(CanvasPath* path,
253295 SkMatrix matrix = ToSkMatrix (matrix4);
254296 matrix.setTranslateX (matrix.getTranslateX () + dx);
255297 matrix.setTranslateY (matrix.getTranslateY () + dy);
256- path_ .addPath (path->path (), matrix, SkPath::kExtend_AddPathMode );
298+ mutable_path () .addPath (path->path (), matrix, SkPath::kExtend_AddPathMode );
257299 matrix4.Release ();
300+ resetVolatility ();
258301}
259302
260303void CanvasPath::close () {
261- path_.close ();
304+ mutable_path ().close ();
305+ resetVolatility ();
262306}
263307
264308void CanvasPath::reset () {
265- path_.reset ();
309+ mutable_path ().reset ();
310+ resetVolatility ();
266311}
267312
268313bool CanvasPath::contains (double x, double y) {
269- return path_ .contains (x, y);
314+ return path () .contains (x, y);
270315}
271316
272317void CanvasPath::shift (Dart_Handle path_handle, double dx, double dy) {
273318 fml::RefPtr<CanvasPath> path = CanvasPath::Create (path_handle);
274- path_.offset (dx, dy, &path->path_ );
319+ auto & other_mutable_path = path->mutable_path ();
320+ mutable_path ().offset (dx, dy, &other_mutable_path);
321+ resetVolatility ();
275322}
276323
277324void CanvasPath::transform (Dart_Handle path_handle,
278325 tonic::Float64List& matrix4) {
279326 fml::RefPtr<CanvasPath> path = CanvasPath::Create (path_handle);
280- path_.transform (ToSkMatrix (matrix4), &path->path_ );
327+ auto & other_mutable_path = path->mutable_path ();
328+ mutable_path ().transform (ToSkMatrix (matrix4), &other_mutable_path);
281329 matrix4.Release ();
282330}
283331
284332tonic::Float32List CanvasPath::getBounds () {
285333 tonic::Float32List rect (Dart_NewTypedData (Dart_TypedData_kFloat32, 4 ));
286- const SkRect& bounds = path_ .getBounds ();
334+ const SkRect& bounds = path () .getBounds ();
287335 rect[0 ] = bounds.left ();
288336 rect[1 ] = bounds.top ();
289337 rect[2 ] = bounds.right ();
@@ -293,21 +341,22 @@ tonic::Float32List CanvasPath::getBounds() {
293341
294342bool CanvasPath::op (CanvasPath* path1, CanvasPath* path2, int operation) {
295343 return Op (path1->path (), path2->path (), static_cast <SkPathOp>(operation),
296- &path_);
344+ &tracked_path_->path );
345+ resetVolatility ();
297346}
298347
299348void CanvasPath::clone (Dart_Handle path_handle) {
300349 fml::RefPtr<CanvasPath> path = CanvasPath::Create (path_handle);
301350 // per Skia docs, this will create a fast copy
302351 // data is shared until the source path or dest path are mutated
303- path->path_ = path_ ;
352+ path->mutable_path () = this -> path () ;
304353}
305354
306355// This is doomed to be called too early, since Paths are mutable.
307356// However, it can help for some of the clone/shift/transform type methods
308357// where the resultant path will initially have a meaningful size.
309358size_t CanvasPath::GetAllocationSize () const {
310- return sizeof (CanvasPath) + path_ .approximateBytesUsed ();
359+ return sizeof (CanvasPath) + path () .approximateBytesUsed ();
311360}
312361
313362} // namespace flutter
0 commit comments