-
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 8 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,71 @@ 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; | ||
|
|
||
| CanvasPath::~CanvasPath() {} | ||
| void CanvasPath::resetVolatility() { | ||
| if (!tracked_path_->tracking_volatility) { | ||
| mutable_path().setIsVolatile(true); | ||
| tracked_path_->frame_count = 0; | ||
|
Member
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. Seems redundant.
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. If this path had previously been marked as non-volatile, but now has been mutated and is volatile again, we have to reset the frame count so that we don't immediately mark it volatile if it is only drawn for e.g. 1 frame. |
||
| tracked_path_->tracking_volatility = true; | ||
| path_tracker_->Insert(tracked_path_); | ||
| } | ||
| } | ||
|
|
||
| void CanvasPath::ReleaseDartWrappableReference() const { | ||
| FML_DCHECK(path_tracker_); | ||
| if (tracked_path_->tracking_volatility) { | ||
|
||
| path_tracker_->Erase(tracked_path_); | ||
| } | ||
| } | ||
|
|
||
| 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 +140,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 +150,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 +175,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 +193,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 +209,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 +230,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 +268,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 +279,8 @@ 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); | ||
| mutable_path().addPath(path->path(), dx, dy, SkPath::kExtend_AddPathMode); | ||
| resetVolatility(); | ||
| } | ||
|
|
||
| void CanvasPath::extendWithPathAndMatrix(CanvasPath* path, | ||
|
|
@@ -253,37 +296,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); | ||
| 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(); | ||
|
||
| 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(); | ||
| } | ||
|
|
||
| tonic::Float32List CanvasPath::getBounds() { | ||
| tonic::Float32List rect(Dart_NewTypedData(Dart_TypedData_kFloat32, 4)); | ||
| const SkRect& bounds = path_.getBounds(); | ||
| const SkRect& bounds = path().getBounds(); | ||
| FML_DLOG(ERROR) << "Bounds " << bounds.left() << " " << bounds.top() << " " | ||
| << bounds.right() << " " << bounds.bottom(); | ||
|
||
| rect[0] = bounds.left(); | ||
| rect[1] = bounds.top(); | ||
| rect[2] = bounds.right(); | ||
|
|
@@ -293,21 +344,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->mutable_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 | ||
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