-
Notifications
You must be signed in to change notification settings - Fork 6k
Set SkPath::setIsVolatile based on whether the path survives at least two frames #22620
Changes from 6 commits
bc78eea
f2867c8
34e2523
100b2ec
6a84f9e
24df8c7
280b3c9
07d2d99
88d4125
62c238f
9fc3504
c8171ad
17eefed
9cd0ac9
e087e3d
50dadd3
38281c2
7767698
b1d122e
847a998
cfaa5b0
71153fe
1eac95f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -67,43 +67,68 @@ void CanvasPath::RegisterNatives(tonic::DartLibraryNatives* natives) { | |
| FOR_EACH_BINDING(DART_REGISTER_NATIVE)}); | ||
| } | ||
|
|
||
| CanvasPath::CanvasPath() {} | ||
| CanvasPath::CanvasPath() | ||
| : path_tracker_(UIDartState::Current()->GetVolatilePathTracker()), | ||
| tracked_path_(std::make_shared<VolatilePathTracker::Path>()) { | ||
| FML_DCHECK(path_tracker_); | ||
| resetVolatility(); | ||
| } | ||
|
|
||
| CanvasPath::~CanvasPath() = default; | ||
|
|
||
| void CanvasPath::resetVolatility() { | ||
| if (!tracked_path_->tracking_volatility) { | ||
| mutable_path().setIsVolatile(true); | ||
| tracked_path_->tracking_volatility = true; | ||
| path_tracker_->insert(tracked_path_); | ||
| } | ||
| } | ||
|
|
||
| CanvasPath::~CanvasPath() {} | ||
| void CanvasPath::ReleaseDartWrappableReference() const { | ||
| FML_DCHECK(path_tracker_); | ||
| path_tracker_->erase(tracked_path_); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we do the following? This seems to be able to save some
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice, done |
||
| } | ||
|
|
||
| int CanvasPath::getFillType() { | ||
| return static_cast<int>(path_.getFillType()); | ||
| return static_cast<int>(path().getFillType()); | ||
| } | ||
|
|
||
| void CanvasPath::setFillType(int fill_type) { | ||
| path_.setFillType(static_cast<SkPathFillType>(fill_type)); | ||
| mutable_path().setFillType(static_cast<SkPathFillType>(fill_type)); | ||
| resetVolatility(); | ||
| } | ||
|
|
||
| void CanvasPath::moveTo(float x, float y) { | ||
| path_.moveTo(x, y); | ||
| mutable_path().moveTo(x, y); | ||
| resetVolatility(); | ||
| } | ||
|
|
||
| void CanvasPath::relativeMoveTo(float x, float y) { | ||
| path_.rMoveTo(x, y); | ||
| mutable_path().rMoveTo(x, y); | ||
| resetVolatility(); | ||
| } | ||
|
|
||
| void CanvasPath::lineTo(float x, float y) { | ||
| path_.lineTo(x, y); | ||
| mutable_path().lineTo(x, y); | ||
| resetVolatility(); | ||
| } | ||
|
|
||
| void CanvasPath::relativeLineTo(float x, float y) { | ||
| path_.rLineTo(x, y); | ||
| mutable_path().rLineTo(x, y); | ||
| resetVolatility(); | ||
| } | ||
|
|
||
| void CanvasPath::quadraticBezierTo(float x1, float y1, float x2, float y2) { | ||
| path_.quadTo(x1, y1, x2, y2); | ||
| mutable_path().quadTo(x1, y1, x2, y2); | ||
| resetVolatility(); | ||
| } | ||
|
|
||
| void CanvasPath::relativeQuadraticBezierTo(float x1, | ||
| float y1, | ||
| float x2, | ||
| float y2) { | ||
| path_.rQuadTo(x1, y1, x2, y2); | ||
| mutable_path().rQuadTo(x1, y1, x2, y2); | ||
| resetVolatility(); | ||
| } | ||
|
|
||
| void CanvasPath::cubicTo(float x1, | ||
|
|
@@ -112,7 +137,8 @@ void CanvasPath::cubicTo(float x1, | |
| float y2, | ||
| float x3, | ||
| float y3) { | ||
| path_.cubicTo(x1, y1, x2, y2, x3, y3); | ||
| mutable_path().cubicTo(x1, y1, x2, y2, x3, y3); | ||
| resetVolatility(); | ||
| } | ||
|
|
||
| void CanvasPath::relativeCubicTo(float x1, | ||
|
|
@@ -121,19 +147,22 @@ void CanvasPath::relativeCubicTo(float x1, | |
| float y2, | ||
| float x3, | ||
| float y3) { | ||
| path_.rCubicTo(x1, y1, x2, y2, x3, y3); | ||
| mutable_path().rCubicTo(x1, y1, x2, y2, x3, y3); | ||
| resetVolatility(); | ||
| } | ||
|
|
||
| void CanvasPath::conicTo(float x1, float y1, float x2, float y2, float w) { | ||
| path_.conicTo(x1, y1, x2, y2, w); | ||
| mutable_path().conicTo(x1, y1, x2, y2, w); | ||
| resetVolatility(); | ||
| } | ||
|
|
||
| void CanvasPath::relativeConicTo(float x1, | ||
| float y1, | ||
| float x2, | ||
| float y2, | ||
| float w) { | ||
| path_.rConicTo(x1, y1, x2, y2, w); | ||
| mutable_path().rConicTo(x1, y1, x2, y2, w); | ||
| resetVolatility(); | ||
| } | ||
|
|
||
| void CanvasPath::arcTo(float left, | ||
|
|
@@ -143,9 +172,10 @@ void CanvasPath::arcTo(float left, | |
| float startAngle, | ||
| float sweepAngle, | ||
| bool forceMoveTo) { | ||
| path_.arcTo(SkRect::MakeLTRB(left, top, right, bottom), | ||
| startAngle * 180.0 / M_PI, sweepAngle * 180.0 / M_PI, | ||
| forceMoveTo); | ||
| mutable_path().arcTo(SkRect::MakeLTRB(left, top, right, bottom), | ||
| startAngle * 180.0 / M_PI, sweepAngle * 180.0 / M_PI, | ||
| forceMoveTo); | ||
| resetVolatility(); | ||
| } | ||
|
|
||
| void CanvasPath::arcToPoint(float arcEndX, | ||
|
|
@@ -160,8 +190,9 @@ void CanvasPath::arcToPoint(float arcEndX, | |
| const auto direction = | ||
| isClockwiseDirection ? SkPathDirection::kCW : SkPathDirection::kCCW; | ||
|
|
||
| path_.arcTo(radiusX, radiusY, xAxisRotation, arcSize, direction, arcEndX, | ||
| arcEndY); | ||
| mutable_path().arcTo(radiusX, radiusY, xAxisRotation, arcSize, direction, | ||
| arcEndX, arcEndY); | ||
| resetVolatility(); | ||
| } | ||
|
|
||
| void CanvasPath::relativeArcToPoint(float arcEndDeltaX, | ||
|
|
@@ -175,16 +206,19 @@ void CanvasPath::relativeArcToPoint(float arcEndDeltaX, | |
| : SkPath::ArcSize::kSmall_ArcSize; | ||
| const auto direction = | ||
| isClockwiseDirection ? SkPathDirection::kCW : SkPathDirection::kCCW; | ||
| path_.rArcTo(radiusX, radiusY, xAxisRotation, arcSize, direction, | ||
| arcEndDeltaX, arcEndDeltaY); | ||
| mutable_path().rArcTo(radiusX, radiusY, xAxisRotation, arcSize, direction, | ||
| arcEndDeltaX, arcEndDeltaY); | ||
| resetVolatility(); | ||
| } | ||
|
|
||
| void CanvasPath::addRect(float left, float top, float right, float bottom) { | ||
| path_.addRect(SkRect::MakeLTRB(left, top, right, bottom)); | ||
| mutable_path().addRect(SkRect::MakeLTRB(left, top, right, bottom)); | ||
| resetVolatility(); | ||
| } | ||
|
|
||
| void CanvasPath::addOval(float left, float top, float right, float bottom) { | ||
| path_.addOval(SkRect::MakeLTRB(left, top, right, bottom)); | ||
| mutable_path().addOval(SkRect::MakeLTRB(left, top, right, bottom)); | ||
| resetVolatility(); | ||
| } | ||
|
|
||
| void CanvasPath::addArc(float left, | ||
|
|
@@ -193,25 +227,29 @@ void CanvasPath::addArc(float left, | |
| float bottom, | ||
| float startAngle, | ||
| float sweepAngle) { | ||
| path_.addArc(SkRect::MakeLTRB(left, top, right, bottom), | ||
| startAngle * 180.0 / M_PI, sweepAngle * 180.0 / M_PI); | ||
| mutable_path().addArc(SkRect::MakeLTRB(left, top, right, bottom), | ||
| startAngle * 180.0 / M_PI, sweepAngle * 180.0 / M_PI); | ||
| resetVolatility(); | ||
| } | ||
|
|
||
| void CanvasPath::addPolygon(const tonic::Float32List& points, bool close) { | ||
| path_.addPoly(reinterpret_cast<const SkPoint*>(points.data()), | ||
| points.num_elements() / 2, close); | ||
| mutable_path().addPoly(reinterpret_cast<const SkPoint*>(points.data()), | ||
| points.num_elements() / 2, close); | ||
| resetVolatility(); | ||
| } | ||
|
|
||
| void CanvasPath::addRRect(const RRect& rrect) { | ||
| path_.addRRect(rrect.sk_rrect); | ||
| mutable_path().addRRect(rrect.sk_rrect); | ||
| resetVolatility(); | ||
| } | ||
|
|
||
| void CanvasPath::addPath(CanvasPath* path, double dx, double dy) { | ||
| if (!path) { | ||
| Dart_ThrowException(ToDart("Path.addPath called with non-genuine Path.")); | ||
| return; | ||
| } | ||
| path_.addPath(path->path(), dx, dy, SkPath::kAppend_AddPathMode); | ||
| mutable_path().addPath(path->path(), dx, dy, SkPath::kAppend_AddPathMode); | ||
| resetVolatility(); | ||
| } | ||
|
|
||
| void CanvasPath::addPathWithMatrix(CanvasPath* path, | ||
|
|
@@ -227,8 +265,9 @@ void CanvasPath::addPathWithMatrix(CanvasPath* path, | |
| SkMatrix matrix = ToSkMatrix(matrix4); | ||
| matrix.setTranslateX(matrix.getTranslateX() + dx); | ||
| matrix.setTranslateY(matrix.getTranslateY() + dy); | ||
| path_.addPath(path->path(), matrix, SkPath::kAppend_AddPathMode); | ||
| mutable_path().addPath(path->path(), matrix, SkPath::kAppend_AddPathMode); | ||
| matrix4.Release(); | ||
| resetVolatility(); | ||
| } | ||
|
|
||
| void CanvasPath::extendWithPath(CanvasPath* path, double dx, double dy) { | ||
|
|
@@ -237,7 +276,9 @@ void CanvasPath::extendWithPath(CanvasPath* path, double dx, double dy) { | |
| ToDart("Path.extendWithPath called with non-genuine Path.")); | ||
| return; | ||
| } | ||
| path_.addPath(path->path(), dx, dy, SkPath::kExtend_AddPathMode); | ||
| path->mutable_path().addPath(path->path(), dx, dy, | ||
| SkPath::kExtend_AddPathMode); | ||
| resetVolatility(); | ||
| } | ||
|
|
||
| void CanvasPath::extendWithPathAndMatrix(CanvasPath* path, | ||
|
|
@@ -253,37 +294,45 @@ void CanvasPath::extendWithPathAndMatrix(CanvasPath* path, | |
| SkMatrix matrix = ToSkMatrix(matrix4); | ||
| matrix.setTranslateX(matrix.getTranslateX() + dx); | ||
| matrix.setTranslateY(matrix.getTranslateY() + dy); | ||
| path_.addPath(path->path(), matrix, SkPath::kExtend_AddPathMode); | ||
| path->mutable_path().addPath(path->path(), matrix, | ||
| SkPath::kExtend_AddPathMode); | ||
| matrix4.Release(); | ||
| resetVolatility(); | ||
| } | ||
|
|
||
| void CanvasPath::close() { | ||
| path_.close(); | ||
| mutable_path().close(); | ||
| resetVolatility(); | ||
| } | ||
|
|
||
| void CanvasPath::reset() { | ||
| path_.reset(); | ||
| mutable_path().reset(); | ||
| resetVolatility(); | ||
| } | ||
|
|
||
| bool CanvasPath::contains(double x, double y) { | ||
| return path_.contains(x, y); | ||
| return path().contains(x, y); | ||
| } | ||
|
|
||
| void CanvasPath::shift(Dart_Handle path_handle, double dx, double dy) { | ||
| fml::RefPtr<CanvasPath> path = CanvasPath::Create(path_handle); | ||
| path_.offset(dx, dy, &path->path_); | ||
| auto other_mutable_path = path->mutable_path(); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this should be
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You are right - adding a test to cover this |
||
| mutable_path().offset(dx, dy, &other_mutable_path); | ||
| resetVolatility(); | ||
| } | ||
|
|
||
| void CanvasPath::transform(Dart_Handle path_handle, | ||
| tonic::Float64List& matrix4) { | ||
| fml::RefPtr<CanvasPath> path = CanvasPath::Create(path_handle); | ||
| path_.transform(ToSkMatrix(matrix4), &path->path_); | ||
| auto other_mutable_path = path->mutable_path(); | ||
| mutable_path().transform(ToSkMatrix(matrix4), &other_mutable_path); | ||
| matrix4.Release(); | ||
| resetVolatility(); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This method does not seem to mutate the current path. Can we do the following?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ahh it mutates the new path, got it. Done. |
||
| } | ||
|
|
||
| tonic::Float32List CanvasPath::getBounds() { | ||
| tonic::Float32List rect(Dart_NewTypedData(Dart_TypedData_kFloat32, 4)); | ||
| const SkRect& bounds = path_.getBounds(); | ||
| const SkRect& bounds = path().getBounds(); | ||
| rect[0] = bounds.left(); | ||
| rect[1] = bounds.top(); | ||
| rect[2] = bounds.right(); | ||
|
|
@@ -293,21 +342,22 @@ tonic::Float32List CanvasPath::getBounds() { | |
|
|
||
| bool CanvasPath::op(CanvasPath* path1, CanvasPath* path2, int operation) { | ||
| return Op(path1->path(), path2->path(), static_cast<SkPathOp>(operation), | ||
| &path_); | ||
| &tracked_path_->path_); | ||
| resetVolatility(); | ||
| } | ||
|
|
||
| void CanvasPath::clone(Dart_Handle path_handle) { | ||
| fml::RefPtr<CanvasPath> path = CanvasPath::Create(path_handle); | ||
| // per Skia docs, this will create a fast copy | ||
| // data is shared until the source path or dest path are mutated | ||
| path->path_ = path_; | ||
| path->tracked_path_->path_ = this->path(); | ||
| } | ||
|
|
||
| // This is doomed to be called too early, since Paths are mutable. | ||
| // However, it can help for some of the clone/shift/transform type methods | ||
| // where the resultant path will initially have a meaningful size. | ||
| size_t CanvasPath::GetAllocationSize() const { | ||
| return sizeof(CanvasPath) + path_.approximateBytesUsed(); | ||
| return sizeof(CanvasPath) + path().approximateBytesUsed(); | ||
| } | ||
|
|
||
| } // namespace flutter | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -7,6 +7,7 @@ | |
|
|
||
| #include "flutter/lib/ui/dart_wrapper.h" | ||
| #include "flutter/lib/ui/painting/rrect.h" | ||
| #include "flutter/lib/ui/volatile_path_tracker.h" | ||
| #include "third_party/skia/include/core/SkPath.h" | ||
| #include "third_party/skia/include/pathops/SkPathOps.h" | ||
| #include "third_party/tonic/typed_data/typed_list.h" | ||
|
|
@@ -36,7 +37,7 @@ class CanvasPath : public RefCountedDartWrappable<CanvasPath> { | |
| static fml::RefPtr<CanvasPath> CreateFrom(Dart_Handle path_handle, | ||
| const SkPath& src) { | ||
| fml::RefPtr<CanvasPath> path = CanvasPath::Create(path_handle); | ||
| path->path_ = src; | ||
| path->tracked_path_->path_ = src; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit:
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. |
||
| return path; | ||
| } | ||
|
|
||
|
|
@@ -108,16 +109,24 @@ class CanvasPath : public RefCountedDartWrappable<CanvasPath> { | |
| bool op(CanvasPath* path1, CanvasPath* path2, int operation); | ||
| void clone(Dart_Handle path_handle); | ||
|
|
||
| const SkPath& path() const { return path_; } | ||
| const SkPath& path() const { return tracked_path_->path_; } | ||
|
|
||
| size_t GetAllocationSize() const override; | ||
|
|
||
| static void RegisterNatives(tonic::DartLibraryNatives* natives); | ||
|
|
||
| virtual void ReleaseDartWrappableReference() const override; | ||
|
|
||
| private: | ||
| CanvasPath(); | ||
|
|
||
| SkPath path_; | ||
| std::shared_ptr<VolatilePathTracker> path_tracker_; | ||
| std::shared_ptr<VolatilePathTracker::Path> tracked_path_; | ||
|
|
||
| // Must be called whenever the path is created or mutated. | ||
| void resetVolatility(); | ||
|
|
||
| SkPath& mutable_path() { return tracked_path_->path_; } | ||
| }; | ||
|
|
||
| } // namespace flutter | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The name
resetVolatilitysounds like it will also reset the volatility frame count but that does not seem to be the case. I believe resetting the count is the intended behavior as it's called in those methods that mutate the path.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done