Update all uses of mutable SkPath methods to use SkPathBuilder (#177738)
Skia is removing the APIs that allow changing an SkPath. This updates
those callsites to use SkPathBuilder where appropriate.
## Pre-launch Checklist
- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [x] I signed the [CLA].
- [ ] I listed at least one issue that this PR fixes in the description
above.
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [x] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [ ] All existing and new tests are passing.
If you need help, consider asking for advice on the #hackers-new channel
on [Discord].
**Note**: The Flutter team is currently trialing the use of [Gemini Code
Assist for
GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code).
Comments from the `gemini-code-assist` bot should not be taken as
authoritative feedback from the Flutter team. If you find its comments
useful you can update your code accordingly, but if you are unsure or
disagree with the feedback, please feel free to wait for a Flutter team
member's review for guidance on which automated comments should be
addressed.
<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview
[Tree Hygiene]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
[test-exempt]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes
[Discord]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md
[Data Driven Fixes]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
diff --git a/engine/src/flutter/display_list/geometry/dl_path.cc b/engine/src/flutter/display_list/geometry/dl_path.cc
index 1ce4a0d..b6b3fbe 100644
--- a/engine/src/flutter/display_list/geometry/dl_path.cc
+++ b/engine/src/flutter/display_list/geometry/dl_path.cc
@@ -44,14 +44,14 @@
DlScalar top,
DlScalar right,
DlScalar bottom) {
- return DlPath(SkPath().addRect(left, top, right, bottom));
+ return DlPath(SkPath::Rect(SkRect::MakeLTRB(left, top, right, bottom)));
}
DlPath DlPath::MakeRectXYWH(DlScalar x,
DlScalar y,
DlScalar width,
DlScalar height) {
- return DlPath(SkPath().addRect(SkRect::MakeXYWH(x, y, width, height)));
+ return DlPath(SkPath::Rect(SkRect::MakeXYWH(x, y, width, height)));
}
DlPath DlPath::MakeOval(const DlRect& bounds) {
@@ -102,7 +102,7 @@
DlDegrees start,
DlDegrees sweep,
bool use_center) {
- SkPath path;
+ SkPathBuilder path;
if (use_center) {
path.moveTo(ToSkPoint(bounds.GetCenter()));
}
@@ -110,7 +110,7 @@
if (use_center) {
path.close();
}
- return DlPath(path);
+ return DlPath(path.detach());
}
const SkPath& DlPath::GetSkPath() const {
@@ -188,9 +188,7 @@
if (!offset.IsFinite()) {
return DlPath();
}
- SkPath path = data_->sk_path;
- path = path.offset(offset.x, offset.y);
- return DlPath(path);
+ return DlPath(data_->sk_path.makeOffset(offset.x, offset.y));
}
[[nodiscard]] DlPath DlPath::WithFillType(DlPathFillType type) const {
@@ -259,9 +257,9 @@
}
DlPath DlPath::operator+(const DlPath& other) const {
- SkPath path = GetSkPath();
+ SkPathBuilder path = SkPathBuilder(GetSkPath());
path.addPath(other.GetSkPath());
- return DlPath(path);
+ return DlPath(path.detach());
}
void DlPath::ReduceConic(DlPathReceiver& receiver,
diff --git a/engine/src/flutter/display_list/geometry/dl_path_builder.cc b/engine/src/flutter/display_list/geometry/dl_path_builder.cc
index 7f78c7d..8f65ed1 100644
--- a/engine/src/flutter/display_list/geometry/dl_path_builder.cc
+++ b/engine/src/flutter/display_list/geometry/dl_path_builder.cc
@@ -57,31 +57,38 @@
}
DlPathBuilder& DlPathBuilder::MoveTo(DlPoint p2) {
- path_.moveTo(p2.x, p2.y);
+ path_.moveTo({p2.x, p2.y});
return *this;
}
DlPathBuilder& DlPathBuilder::LineTo(DlPoint p2) {
- path_.lineTo(p2.x, p2.y);
+ path_.lineTo({p2.x, p2.y});
return *this;
}
DlPathBuilder& DlPathBuilder::QuadraticCurveTo(DlPoint cp, DlPoint p2) {
- path_.quadTo(cp.x, cp.y, p2.x, p2.y);
+ path_.quadTo({cp.x, cp.y}, {p2.x, p2.y});
return *this;
}
DlPathBuilder& DlPathBuilder::ConicCurveTo(DlPoint cp,
DlPoint p2,
DlScalar weight) {
- path_.conicTo(cp.x, cp.y, p2.x, p2.y, weight);
+ // Skia's SkPath object used to do these checks, but SkPathBuilder does not.
+ if (!(weight > 0)) {
+ return this->LineTo(p2);
+ } else if (!std::isfinite(weight)) {
+ this->LineTo(cp);
+ return this->LineTo(p2);
+ }
+ path_.conicTo({cp.x, cp.y}, {p2.x, p2.y}, weight);
return *this;
}
DlPathBuilder& DlPathBuilder::CubicCurveTo(DlPoint cp1,
DlPoint cp2,
DlPoint p2) {
- path_.cubicTo(cp1.x, cp1.y, cp2.x, cp2.y, p2.x, p2.y);
+ path_.cubicTo({cp1.x, cp1.y}, {cp2.x, cp2.y}, {p2.x, p2.y});
return *this;
}
@@ -139,13 +146,11 @@
}
const DlPath DlPathBuilder::CopyPath() {
- return DlPath(path_);
+ return DlPath(path_.snapshot());
}
const DlPath DlPathBuilder::TakePath() {
- DlPath path = DlPath(path_);
- path_.reset();
- return path;
+ return DlPath(path_.detach());
}
} // namespace flutter
diff --git a/engine/src/flutter/display_list/geometry/dl_path_builder.h b/engine/src/flutter/display_list/geometry/dl_path_builder.h
index 9a07616..e150698 100644
--- a/engine/src/flutter/display_list/geometry/dl_path_builder.h
+++ b/engine/src/flutter/display_list/geometry/dl_path_builder.h
@@ -7,7 +7,7 @@
#include "flutter/display_list/geometry/dl_geometry_types.h"
#include "flutter/display_list/geometry/dl_path.h"
-#include "flutter/third_party/skia/include/core/SkPath.h"
+#include "flutter/third_party/skia/include/core/SkPathBuilder.h"
namespace flutter {
@@ -132,7 +132,7 @@
const DlPath TakePath();
private:
- SkPath path_;
+ SkPathBuilder path_;
};
} // namespace flutter
diff --git a/engine/src/flutter/display_list/geometry/dl_path_unittests.cc b/engine/src/flutter/display_list/geometry/dl_path_unittests.cc
index 7be51c1..38b6b7c 100644
--- a/engine/src/flutter/display_list/geometry/dl_path_unittests.cc
+++ b/engine/src/flutter/display_list/geometry/dl_path_unittests.cc
@@ -9,6 +9,7 @@
#include "flutter/display_list/geometry/dl_path_builder.h"
#include "flutter/display_list/testing/dl_test_mock_path_receiver.h"
#include "flutter/third_party/skia/include/core/SkPath.h"
+#include "flutter/third_party/skia/include/core/SkPoint.h"
#include "flutter/third_party/skia/include/core/SkRRect.h"
namespace flutter {
@@ -392,14 +393,18 @@
}
TEST(DisplayListPath, ConstructFromPath) {
- SkPath sk_path1;
- sk_path1.moveTo(10, 10);
- sk_path1.lineTo(20, 20);
- sk_path1.lineTo(20, 10);
- SkPath sk_path2;
- sk_path2.moveTo(10, 10);
- sk_path2.lineTo(20, 20);
- sk_path2.lineTo(20, 10);
+ SkPathBuilder pb1;
+ pb1.moveTo({10, 10});
+ pb1.lineTo({20, 20});
+ pb1.lineTo({20, 10});
+ SkPathBuilder pb2;
+ pb2.moveTo({10, 10});
+ pb2.lineTo({20, 20});
+ pb2.lineTo({20, 10});
+
+ SkPath sk_path1 = pb1.detach();
+ SkPath sk_path2 = pb2.detach();
+
DlPath path(sk_path1);
ASSERT_EQ(sk_path1, sk_path2);
@@ -428,22 +433,21 @@
path_builder.LineTo({0, 100});
path_builder.Close();
- SkPath sk_path;
- sk_path.setFillType(SkPathFillType::kWinding);
- sk_path.moveTo(0, 0);
- sk_path.lineTo(100, 0);
- sk_path.lineTo(0, 100);
+ SkPathBuilder sk_path(SkPathFillType::kWinding);
+ sk_path.moveTo({0, 0});
+ sk_path.lineTo({100, 0});
+ sk_path.lineTo({0, 100});
sk_path.close();
- EXPECT_EQ(path_builder.TakePath(), DlPath(sk_path));
+ EXPECT_EQ(path_builder.TakePath(), DlPath(sk_path.detach()));
}
TEST(DisplayListPath, IsLineFromSkPath) {
- SkPath sk_path;
- sk_path.moveTo(SkPoint::Make(0, 0));
- sk_path.lineTo(SkPoint::Make(100, 100));
+ SkPathBuilder sk_path;
+ sk_path.moveTo({0, 0});
+ sk_path.lineTo({100, 100});
- DlPath path = DlPath(sk_path);
+ DlPath path = DlPath(sk_path.detach());
DlPoint start;
DlPoint end;
@@ -507,16 +511,16 @@
}
TEST(DisplayListPath, DispatchSkiaPathOneOfEachVerb) {
- SkPath path;
+ SkPathBuilder path;
- path.moveTo(100, 200);
- path.lineTo(101, 201);
- path.quadTo(110, 202, 102, 210);
- path.conicTo(150, 240, 250, 140, 0.5);
- path.cubicTo(300, 300, 350, 300, 300, 350);
+ path.moveTo({100, 200});
+ path.lineTo({101, 201});
+ path.quadTo({110, 202}, {102, 210});
+ path.conicTo({150, 240}, {250, 140}, 0.5);
+ path.cubicTo({300, 300}, {350, 300}, {300, 350});
path.close();
- TestPathDispatchOneOfEachVerb(DlPath(path));
+ TestPathDispatchOneOfEachVerb(DlPath(path.detach()));
}
TEST(DisplayListPath, DispatchImpellerPathOneOfEachVerb) {
@@ -558,11 +562,11 @@
static void TestSkiaPathDispatchConicToQuads(
DlScalar weight,
const std::array<DlPoint, 4>& quad_points) {
- SkPath sk_path;
- sk_path.moveTo(10, 10);
- sk_path.conicTo(20, 10, 20, 20, weight);
+ SkPathBuilder sk_path;
+ sk_path.moveTo({10, 10});
+ sk_path.conicTo({20, 10}, {20, 20}, weight);
- TestPathDispatchConicToQuads(DlPath(sk_path), weight, quad_points);
+ TestPathDispatchConicToQuads(DlPath(sk_path.detach()), weight, quad_points);
}
static void TestImpellerPathDispatchConicToQuads(
@@ -662,12 +666,12 @@
}
TEST(DisplayListPath, DispatchUnclosedSkiaTriangle) {
- SkPath sk_path;
- sk_path.moveTo(10, 10);
- sk_path.lineTo(20, 10);
- sk_path.lineTo(10, 20);
+ SkPathBuilder sk_path;
+ sk_path.moveTo({10, 10});
+ sk_path.lineTo({20, 10});
+ sk_path.lineTo({10, 20});
- TestPathDispatchUnclosedTriangle(DlPath(sk_path));
+ TestPathDispatchUnclosedTriangle(DlPath(sk_path.detach()));
}
TEST(DisplayListPath, DispatchUnclosedImpellerTriangle) {
@@ -696,13 +700,13 @@
}
TEST(DisplayListPath, DispatchClosedSkiaTriangle) {
- SkPath sk_path;
- sk_path.moveTo(10, 10);
- sk_path.lineTo(20, 10);
- sk_path.lineTo(10, 20);
+ SkPathBuilder sk_path;
+ sk_path.moveTo({10, 10});
+ sk_path.lineTo({20, 10});
+ sk_path.lineTo({10, 20});
sk_path.close();
- TestPathDispatchClosedTriangle(DlPath(sk_path));
+ TestPathDispatchClosedTriangle(DlPath(sk_path.detach()));
}
TEST(DisplayListPath, DispatchClosedPathBuilderTriangle) {
@@ -738,19 +742,19 @@
}
TEST(DisplayListPath, DispatchMixedCloseSkiaPath) {
- SkPath sk_path;
- sk_path.moveTo(10, 10);
- sk_path.lineTo(20, 10);
- sk_path.lineTo(10, 20);
- sk_path.moveTo(110, 10);
- sk_path.lineTo(120, 10);
- sk_path.lineTo(110, 20);
+ SkPathBuilder sk_path;
+ sk_path.moveTo({10, 10});
+ sk_path.lineTo({20, 10});
+ sk_path.lineTo({10, 20});
+ sk_path.moveTo({110, 10});
+ sk_path.lineTo({120, 10});
+ sk_path.lineTo({110, 20});
sk_path.close();
- sk_path.moveTo(210, 10);
- sk_path.lineTo(220, 10);
- sk_path.lineTo(210, 20);
+ sk_path.moveTo({210, 10});
+ sk_path.lineTo({220, 10});
+ sk_path.lineTo({210, 20});
- TestPathDispatchMixedCloseTriangles(DlPath(sk_path));
+ TestPathDispatchMixedCloseTriangles(DlPath(sk_path.detach()));
}
TEST(DisplayListPath, DispatchMixedCloseImpellerPath) {
@@ -789,15 +793,15 @@
}
TEST(DisplayListPath, DispatchImplicitMoveAfterCloseSkiaPath) {
- SkPath sk_path;
- sk_path.moveTo(10, 10);
- sk_path.lineTo(20, 10);
- sk_path.lineTo(10, 20);
+ SkPathBuilder sk_path;
+ sk_path.moveTo({10, 10});
+ sk_path.lineTo({20, 10});
+ sk_path.lineTo({10, 20});
sk_path.close();
- sk_path.lineTo(-20, 10);
- sk_path.lineTo(10, -20);
+ sk_path.lineTo({-20, 10});
+ sk_path.lineTo({10, -20});
- TestPathDispatchImplicitMoveAfterClose(DlPath(sk_path));
+ TestPathDispatchImplicitMoveAfterClose(DlPath(sk_path.detach()));
}
TEST(DisplayListPath, DispatchImplicitMoveAfterClosePathBuilder) {
@@ -817,25 +821,25 @@
// supported by either Flutter public APIs or Impeller
TEST(DisplayListPath, CannotConstructFromSkiaInverseWinding) {
- SkPath sk_path;
- sk_path.setFillType(SkPathFillType::kInverseWinding);
- sk_path.moveTo(0, 0);
- sk_path.lineTo(100, 0);
- sk_path.lineTo(0, 100);
+ SkPathBuilder sk_path(SkPathFillType::kInverseWinding);
+ sk_path.moveTo({0, 0});
+ sk_path.lineTo({100, 0});
+ sk_path.lineTo({0, 100});
sk_path.close();
- EXPECT_DEATH_IF_SUPPORTED(new DlPath(sk_path), "SkPathFillType_IsInverse");
+ EXPECT_DEATH_IF_SUPPORTED(new DlPath(sk_path.detach()),
+ "SkPathFillType_IsInverse");
}
TEST(DisplayListPath, CannotConstructFromSkiaInverseEvenOdd) {
- SkPath sk_path;
- sk_path.setFillType(SkPathFillType::kInverseEvenOdd);
- sk_path.moveTo(0, 0);
- sk_path.lineTo(100, 0);
- sk_path.lineTo(0, 100);
+ SkPathBuilder sk_path(SkPathFillType::kInverseEvenOdd);
+ sk_path.moveTo({0, 0});
+ sk_path.lineTo({100, 0});
+ sk_path.lineTo({0, 100});
sk_path.close();
- EXPECT_DEATH_IF_SUPPORTED(new DlPath(sk_path), "SkPathFillType_IsInverse");
+ EXPECT_DEATH_IF_SUPPORTED(new DlPath(sk_path.detach()),
+ "SkPathFillType_IsInverse");
}
#endif
diff --git a/engine/src/flutter/impeller/toolkit/interop/path.cc b/engine/src/flutter/impeller/toolkit/interop/path.cc
index d7f09c0..f85f732 100644
--- a/engine/src/flutter/impeller/toolkit/interop/path.cc
+++ b/engine/src/flutter/impeller/toolkit/interop/path.cc
@@ -4,18 +4,20 @@
#include "impeller/toolkit/interop/path.h"
+#include "third_party/skia/include/core/SkRect.h"
+
namespace impeller::interop {
-Path::Path(const SkPath& path) : path_(path) {}
+Path::Path(const SkPath& path) : path_(SkPathBuilder(path)) {}
Path::~Path() = default;
-const SkPath& Path::GetPath() const {
- return path_;
+SkPath Path::GetPath() const {
+ return path_.snapshot();
}
ImpellerRect Path::GetBounds() const {
- const auto bounds = path_.getBounds();
+ const auto bounds = path_.computeFiniteBounds().value_or(SkRect());
return ImpellerRect{
.x = bounds.x(),
.y = bounds.y(),
diff --git a/engine/src/flutter/impeller/toolkit/interop/path.h b/engine/src/flutter/impeller/toolkit/interop/path.h
index bd68d9e..c1c0481 100644
--- a/engine/src/flutter/impeller/toolkit/interop/path.h
+++ b/engine/src/flutter/impeller/toolkit/interop/path.h
@@ -6,6 +6,7 @@
#define FLUTTER_IMPELLER_TOOLKIT_INTEROP_PATH_H_
#include "flutter/third_party/skia/include/core/SkPath.h"
+#include "flutter/third_party/skia/include/core/SkPathBuilder.h"
#include "impeller/toolkit/interop/impeller.h"
#include "impeller/toolkit/interop/object.h"
@@ -22,12 +23,12 @@
Path& operator=(const Path&) = delete;
- const SkPath& GetPath() const;
+ SkPath GetPath() const;
ImpellerRect GetBounds() const;
private:
- SkPath path_;
+ SkPathBuilder path_;
};
} // namespace impeller::interop
diff --git a/engine/src/flutter/impeller/toolkit/interop/path_builder.cc b/engine/src/flutter/impeller/toolkit/interop/path_builder.cc
index 978b271..08fc057 100644
--- a/engine/src/flutter/impeller/toolkit/interop/path_builder.cc
+++ b/engine/src/flutter/impeller/toolkit/interop/path_builder.cc
@@ -61,12 +61,12 @@
ScopedObject<Path> PathBuilder::TakePath(FillType fill) {
builder_.setFillType(ToSkiaType(fill));
- return Create<Path>(std::move(builder_));
+ return Create<Path>(builder_.detach());
}
ScopedObject<Path> PathBuilder::CopyPath(FillType fill) {
builder_.setFillType(ToSkiaType(fill));
- return Create<Path>(builder_);
+ return Create<Path>(builder_.snapshot());
}
} // namespace impeller::interop
diff --git a/engine/src/flutter/impeller/toolkit/interop/path_builder.h b/engine/src/flutter/impeller/toolkit/interop/path_builder.h
index e491927..762d492 100644
--- a/engine/src/flutter/impeller/toolkit/interop/path_builder.h
+++ b/engine/src/flutter/impeller/toolkit/interop/path_builder.h
@@ -5,7 +5,7 @@
#ifndef FLUTTER_IMPELLER_TOOLKIT_INTEROP_PATH_BUILDER_H_
#define FLUTTER_IMPELLER_TOOLKIT_INTEROP_PATH_BUILDER_H_
-#include "flutter/third_party/skia/include/core/SkPath.h"
+#include "flutter/third_party/skia/include/core/SkPathBuilder.h"
#include "impeller/geometry/path_source.h"
#include "impeller/geometry/point.h"
#include "impeller/geometry/rect.h"
@@ -53,7 +53,7 @@
ScopedObject<Path> CopyPath(FillType fill);
private:
- SkPath builder_;
+ SkPathBuilder builder_;
};
} // namespace impeller::interop
diff --git a/engine/src/flutter/lib/ui/painting/path.cc b/engine/src/flutter/lib/ui/painting/path.cc
index 5357cf0..7adfaa0 100644
--- a/engine/src/flutter/lib/ui/painting/path.cc
+++ b/engine/src/flutter/lib/ui/painting/path.cc
@@ -37,7 +37,7 @@
}
int CanvasPath::getFillType() {
- return static_cast<int>(sk_path_.getFillType());
+ return static_cast<int>(sk_path_.fillType());
}
void CanvasPath::setFillType(int fill_type) {
@@ -51,23 +51,23 @@
}
void CanvasPath::relativeMoveTo(double x, double y) {
- sk_path_.rMoveTo(SafeNarrow(x), SafeNarrow(y));
+ sk_path_.rMoveTo({SafeNarrow(x), SafeNarrow(y)});
resetVolatility();
}
void CanvasPath::lineTo(double x, double y) {
- sk_path_.lineTo(SafeNarrow(x), SafeNarrow(y));
+ sk_path_.lineTo({SafeNarrow(x), SafeNarrow(y)});
resetVolatility();
}
void CanvasPath::relativeLineTo(double x, double y) {
- sk_path_.rLineTo(SafeNarrow(x), SafeNarrow(y));
+ sk_path_.rLineTo({SafeNarrow(x), SafeNarrow(y)});
resetVolatility();
}
void CanvasPath::quadraticBezierTo(double x1, double y1, double x2, double y2) {
- sk_path_.quadTo(SafeNarrow(x1), SafeNarrow(y1), SafeNarrow(x2),
- SafeNarrow(y2));
+ sk_path_.quadTo({SafeNarrow(x1), SafeNarrow(y1)},
+ {SafeNarrow(x2), SafeNarrow(y2)});
resetVolatility();
}
@@ -75,8 +75,8 @@
double y1,
double x2,
double y2) {
- sk_path_.rQuadTo(SafeNarrow(x1), SafeNarrow(y1), SafeNarrow(x2),
- SafeNarrow(y2));
+ sk_path_.rQuadTo({SafeNarrow(x1), SafeNarrow(y1)},
+ {SafeNarrow(x2), SafeNarrow(y2)});
resetVolatility();
}
@@ -86,8 +86,9 @@
double y2,
double x3,
double y3) {
- sk_path_.cubicTo(SafeNarrow(x1), SafeNarrow(y1), SafeNarrow(x2),
- SafeNarrow(y2), SafeNarrow(x3), SafeNarrow(y3));
+ sk_path_.cubicTo({SafeNarrow(x1), SafeNarrow(y1)},
+ {SafeNarrow(x2), SafeNarrow(y2)},
+ {SafeNarrow(x3), SafeNarrow(y3)});
resetVolatility();
}
@@ -97,14 +98,15 @@
double y2,
double x3,
double y3) {
- sk_path_.rCubicTo(SafeNarrow(x1), SafeNarrow(y1), SafeNarrow(x2),
- SafeNarrow(y2), SafeNarrow(x3), SafeNarrow(y3));
+ sk_path_.rCubicTo({SafeNarrow(x1), SafeNarrow(y1)},
+ {SafeNarrow(x2), SafeNarrow(y2)},
+ {SafeNarrow(x3), SafeNarrow(y3)});
resetVolatility();
}
void CanvasPath::conicTo(double x1, double y1, double x2, double y2, double w) {
- sk_path_.conicTo(SafeNarrow(x1), SafeNarrow(y1), SafeNarrow(x2),
- SafeNarrow(y2), SafeNarrow(w));
+ sk_path_.conicTo({SafeNarrow(x1), SafeNarrow(y1)},
+ {SafeNarrow(x2), SafeNarrow(y2)}, SafeNarrow(w));
resetVolatility();
}
@@ -113,8 +115,8 @@
double x2,
double y2,
double w) {
- sk_path_.rConicTo(SafeNarrow(x1), SafeNarrow(y1), SafeNarrow(x2),
- SafeNarrow(y2), SafeNarrow(w));
+ sk_path_.rConicTo({SafeNarrow(x1), SafeNarrow(y1)},
+ {SafeNarrow(x2), SafeNarrow(y2)}, SafeNarrow(w));
resetVolatility();
}
@@ -140,14 +142,14 @@
double xAxisRotation,
bool isLargeArc,
bool isClockwiseDirection) {
- const auto arcSize = isLargeArc ? SkPath::ArcSize::kLarge_ArcSize
- : SkPath::ArcSize::kSmall_ArcSize;
+ const auto arcSize = isLargeArc ? SkPathBuilder::ArcSize::kLarge_ArcSize
+ : SkPathBuilder::ArcSize::kSmall_ArcSize;
const auto direction =
isClockwiseDirection ? SkPathDirection::kCW : SkPathDirection::kCCW;
- sk_path_.arcTo(SafeNarrow(radiusX), SafeNarrow(radiusY),
+ sk_path_.arcTo({SafeNarrow(radiusX), SafeNarrow(radiusY)},
SafeNarrow(xAxisRotation), arcSize, direction,
- SafeNarrow(arcEndX), SafeNarrow(arcEndY));
+ {SafeNarrow(arcEndX), SafeNarrow(arcEndY)});
resetVolatility();
}
@@ -158,13 +160,13 @@
double xAxisRotation,
bool isLargeArc,
bool isClockwiseDirection) {
- const auto arcSize = isLargeArc ? SkPath::ArcSize::kLarge_ArcSize
- : SkPath::ArcSize::kSmall_ArcSize;
+ const auto arcSize = isLargeArc ? SkPathBuilder::ArcSize::kLarge_ArcSize
+ : SkPathBuilder::ArcSize::kSmall_ArcSize;
const auto direction =
isClockwiseDirection ? SkPathDirection::kCW : SkPathDirection::kCCW;
- sk_path_.rArcTo(SafeNarrow(radiusX), SafeNarrow(radiusY),
+ sk_path_.rArcTo({SafeNarrow(radiusX), SafeNarrow(radiusY)},
SafeNarrow(xAxisRotation), arcSize, direction,
- SafeNarrow(arcEndDeltaX), SafeNarrow(arcEndDeltaY));
+ {SafeNarrow(arcEndDeltaX), SafeNarrow(arcEndDeltaY)});
resetVolatility();
}
@@ -197,7 +199,7 @@
SkSpan<const SkPoint> ptsSpan = {
reinterpret_cast<const SkPoint*>(points.data()),
points.num_elements() / 2};
- sk_path_.addPoly(ptsSpan, close);
+ sk_path_.addPolygon(ptsSpan, close);
resetVolatility();
}
@@ -220,7 +222,7 @@
Dart_ThrowException(ToDart("Path.addPath called with non-genuine Path."));
return;
}
- sk_path_.addPath(path->sk_path_, SafeNarrow(dx), SafeNarrow(dy),
+ sk_path_.addPath(path->sk_path_.snapshot(), SafeNarrow(dx), SafeNarrow(dy),
SkPath::kAppend_AddPathMode);
resetVolatility();
}
@@ -242,7 +244,8 @@
matrix4.Release();
matrix.setTranslateX(matrix.getTranslateX() + SafeNarrow(dx));
matrix.setTranslateY(matrix.getTranslateY() + SafeNarrow(dy));
- sk_path_.addPath(path->sk_path_, matrix, SkPath::kAppend_AddPathMode);
+ sk_path_.addPath(path->sk_path_.snapshot(), matrix,
+ SkPath::kAppend_AddPathMode);
resetVolatility();
}
@@ -252,7 +255,7 @@
ToDart("Path.extendWithPath called with non-genuine Path."));
return;
}
- sk_path_.addPath(path->sk_path_, SafeNarrow(dx), SafeNarrow(dy),
+ sk_path_.addPath(path->sk_path_.snapshot(), SafeNarrow(dx), SafeNarrow(dy),
SkPath::kExtend_AddPathMode);
resetVolatility();
}
@@ -274,7 +277,8 @@
matrix4.Release();
matrix.setTranslateX(matrix.getTranslateX() + SafeNarrow(dx));
matrix.setTranslateY(matrix.getTranslateY() + SafeNarrow(dy));
- sk_path_.addPath(path->sk_path_, matrix, SkPath::kExtend_AddPathMode);
+ sk_path_.addPath(path->sk_path_.snapshot(), matrix,
+ SkPath::kExtend_AddPathMode);
resetVolatility();
}
@@ -289,13 +293,14 @@
}
bool CanvasPath::contains(double x, double y) {
- return sk_path_.contains(SafeNarrow(x), SafeNarrow(y));
+ return sk_path_.contains({SafeNarrow(x), SafeNarrow(y)});
}
void CanvasPath::shift(Dart_Handle path_handle, double dx, double dy) {
fml::RefPtr<CanvasPath> path = Create(path_handle);
auto& other_mutable_path = path->sk_path_;
- sk_path_.offset(SafeNarrow(dx), SafeNarrow(dy), &other_mutable_path);
+ other_mutable_path =
+ sk_path_.snapshot().makeOffset(SafeNarrow(dx), SafeNarrow(dy));
resetVolatility();
}
@@ -306,12 +311,12 @@
matrix4.Release();
fml::RefPtr<CanvasPath> path = Create(path_handle);
auto& other_mutable_path = path->sk_path_;
- sk_path_.transform(sk_matrix, &other_mutable_path);
+ other_mutable_path = sk_path_.snapshot().makeTransform(sk_matrix);
}
tonic::Float32List CanvasPath::getBounds() {
tonic::Float32List rect(Dart_NewTypedData(Dart_TypedData_kFloat32, 4));
- const SkRect& bounds = sk_path_.getBounds();
+ const SkRect& bounds = sk_path_.computeFiniteBounds().value_or(SkRect());
rect[0] = bounds.left();
rect[1] = bounds.top();
rect[2] = bounds.right();
@@ -320,10 +325,15 @@
}
bool CanvasPath::op(CanvasPath* path1, CanvasPath* path2, int operation) {
- bool result = Op(path1->sk_path_, path2->sk_path_,
- static_cast<SkPathOp>(operation), &sk_path_);
- resetVolatility();
- return result;
+ std::optional<SkPath> result =
+ Op(path1->sk_path_.snapshot(), path2->sk_path_.snapshot(),
+ static_cast<SkPathOp>(operation));
+ if (result) {
+ sk_path_ = result.value();
+ resetVolatility();
+ return true;
+ }
+ return false;
}
void CanvasPath::clone(Dart_Handle path_handle) {
@@ -335,7 +345,7 @@
const DlPath& CanvasPath::path() const {
if (!dl_path_.has_value()) {
- dl_path_.emplace(sk_path_);
+ dl_path_.emplace(sk_path_.snapshot());
}
return dl_path_.value();
}
diff --git a/engine/src/flutter/lib/ui/painting/path.h b/engine/src/flutter/lib/ui/painting/path.h
index c7816a5..dc82a18 100644
--- a/engine/src/flutter/lib/ui/painting/path.h
+++ b/engine/src/flutter/lib/ui/painting/path.h
@@ -10,6 +10,7 @@
#include "flutter/lib/ui/painting/rsuperellipse.h"
#include "flutter/lib/ui/ui_dart_state.h"
#include "third_party/skia/include/core/SkPath.h"
+#include "third_party/skia/include/core/SkPathBuilder.h"
#include "third_party/skia/include/pathops/SkPathOps.h"
#include "third_party/tonic/typed_data/typed_list.h"
@@ -120,7 +121,7 @@
private:
CanvasPath();
- SkPath sk_path_;
+ SkPathBuilder sk_path_;
mutable std::optional<const DlPath> dl_path_;
// Must be called whenever the path is created or mutated.
diff --git a/engine/src/flutter/lib/web_ui/skwasm/canvas.cpp b/engine/src/flutter/lib/web_ui/skwasm/canvas.cpp
index 973257f..ab999ce 100644
--- a/engine/src/flutter/lib/web_ui/skwasm/canvas.cpp
+++ b/engine/src/flutter/lib/web_ui/skwasm/canvas.cpp
@@ -7,6 +7,8 @@
#include "text/text_types.h"
#include "wrappers.h"
+#include "third_party/skia/include/core/SkPath.h"
+#include "third_party/skia/include/core/SkPathBuilder.h"
#include "third_party/skia/modules/skparagraph/include/Paragraph.h"
#include "flutter/display_list/dl_builder.h"
@@ -191,9 +193,9 @@
}
SKWASM_EXPORT void canvas_clipPath(DisplayListBuilder* canvas,
- SkPath* path,
+ SkPathBuilder* path,
bool antialias) {
- canvas->ClipPath(DlPath(*path), DlClipOp::kIntersect, antialias);
+ canvas->ClipPath(DlPath(path->snapshot()), DlClipOp::kIntersect, antialias);
}
SKWASM_EXPORT void canvas_drawColor(DisplayListBuilder* canvas,
@@ -263,18 +265,18 @@
}
SKWASM_EXPORT void canvas_drawPath(DisplayListBuilder* canvas,
- SkPath* path,
+ SkPathBuilder* path,
DlPaint* paint) {
- canvas->DrawPath(DlPath(*path), paint ? *paint : DlPaint());
+ canvas->DrawPath(DlPath(path->snapshot()), paint ? *paint : DlPaint());
}
SKWASM_EXPORT void canvas_drawShadow(DisplayListBuilder* canvas,
- SkPath* path,
+ SkPathBuilder* path,
DlScalar elevation,
DlScalar devicePixelRatio,
uint32_t color,
bool transparentOccluder) {
- canvas->DrawShadow(DlPath(*path), DlColor(color), elevation,
+ canvas->DrawShadow(DlPath(path->snapshot()), DlColor(color), elevation,
transparentOccluder, devicePixelRatio);
}
diff --git a/engine/src/flutter/lib/web_ui/skwasm/contour_measure.cpp b/engine/src/flutter/lib/web_ui/skwasm/contour_measure.cpp
index d8abb1f..2726e4a 100644
--- a/engine/src/flutter/lib/web_ui/skwasm/contour_measure.cpp
+++ b/engine/src/flutter/lib/web_ui/skwasm/contour_measure.cpp
@@ -8,13 +8,16 @@
#include "third_party/skia/include/core/SkContourMeasure.h"
#include "third_party/skia/include/core/SkPath.h"
+#include "third_party/skia/include/core/SkPathBuilder.h"
using namespace Skwasm;
-SKWASM_EXPORT SkContourMeasureIter*
-contourMeasureIter_create(SkPath* path, bool forceClosed, SkScalar resScale) {
+SKWASM_EXPORT SkContourMeasureIter* contourMeasureIter_create(
+ SkPathBuilder* path,
+ bool forceClosed,
+ SkScalar resScale) {
liveCountourMeasureIterCount++;
- return new SkContourMeasureIter(*path, forceClosed, resScale);
+ return new SkContourMeasureIter(path->snapshot(), forceClosed, resScale);
}
SKWASM_EXPORT SkContourMeasure* contourMeasureIter_next(
@@ -52,11 +55,12 @@
return measure->getPosTan(distance, outPosition, outTangent);
}
-SKWASM_EXPORT SkPath* contourMeasure_getSegment(SkContourMeasure* measure,
- SkScalar startD,
- SkScalar stopD,
- bool startWithMoveTo) {
- SkPath* outPath = new SkPath();
+SKWASM_EXPORT SkPathBuilder* contourMeasure_getSegment(
+ SkContourMeasure* measure,
+ SkScalar startD,
+ SkScalar stopD,
+ bool startWithMoveTo) {
+ SkPathBuilder* outPath = new SkPathBuilder();
if (!measure->getSegment(startD, stopD, outPath, startWithMoveTo)) {
delete outPath;
return nullptr;
diff --git a/engine/src/flutter/lib/web_ui/skwasm/path.cpp b/engine/src/flutter/lib/web_ui/skwasm/path.cpp
index 530168e..56de7c9 100644
--- a/engine/src/flutter/lib/web_ui/skwasm/path.cpp
+++ b/engine/src/flutter/lib/web_ui/skwasm/path.cpp
@@ -5,107 +5,112 @@
#include "export.h"
#include "helpers.h"
#include "live_objects.h"
-#include "third_party/skia/include/core/SkPath.h"
+#include "third_party/skia/include/core/SkPathBuilder.h"
#include "third_party/skia/include/core/SkString.h"
#include "third_party/skia/include/pathops/SkPathOps.h"
#include "third_party/skia/include/utils/SkParsePath.h"
using namespace Skwasm;
-SKWASM_EXPORT SkPath* path_create() {
+SKWASM_EXPORT SkPathBuilder* path_create() {
livePathCount++;
- return new SkPath();
+ return new SkPathBuilder();
}
-SKWASM_EXPORT void path_dispose(SkPath* path) {
+SKWASM_EXPORT void path_dispose(SkPathBuilder* path) {
livePathCount--;
delete path;
}
-SKWASM_EXPORT SkPath* path_copy(SkPath* path) {
+SKWASM_EXPORT SkPathBuilder* path_copy(SkPathBuilder* path) {
livePathCount++;
- return new SkPath(*path);
+ return new SkPathBuilder(path->snapshot());
}
-SKWASM_EXPORT void path_setFillType(SkPath* path, SkPathFillType fillType) {
+SKWASM_EXPORT void path_setFillType(SkPathBuilder* path,
+ SkPathFillType fillType) {
path->setFillType(fillType);
}
-SKWASM_EXPORT SkPathFillType path_getFillType(SkPath* path) {
- return path->getFillType();
+SKWASM_EXPORT SkPathFillType path_getFillType(SkPathBuilder* path) {
+ return path->fillType();
}
-SKWASM_EXPORT void path_moveTo(SkPath* path, SkScalar x, SkScalar y) {
- path->moveTo(x, y);
+SKWASM_EXPORT void path_moveTo(SkPathBuilder* path, SkScalar x, SkScalar y) {
+ path->moveTo({x, y});
}
-SKWASM_EXPORT void path_relativeMoveTo(SkPath* path, SkScalar x, SkScalar y) {
- path->rMoveTo(x, y);
+SKWASM_EXPORT void path_relativeMoveTo(SkPathBuilder* path,
+ SkScalar x,
+ SkScalar y) {
+ path->rMoveTo({x, y});
}
-SKWASM_EXPORT void path_lineTo(SkPath* path, SkScalar x, SkScalar y) {
- path->lineTo(x, y);
+SKWASM_EXPORT void path_lineTo(SkPathBuilder* path, SkScalar x, SkScalar y) {
+ path->lineTo({x, y});
}
-SKWASM_EXPORT void path_relativeLineTo(SkPath* path, SkScalar x, SkScalar y) {
- path->rLineTo(x, y);
+SKWASM_EXPORT void path_relativeLineTo(SkPathBuilder* path,
+ SkScalar x,
+ SkScalar y) {
+ path->rLineTo({x, y});
}
-SKWASM_EXPORT void path_quadraticBezierTo(SkPath* path,
+SKWASM_EXPORT void path_quadraticBezierTo(SkPathBuilder* path,
SkScalar x1,
SkScalar y1,
SkScalar x2,
SkScalar y2) {
- path->quadTo(x1, y1, x2, y2);
+ path->quadTo({x1, y1}, {x2, y2});
}
-SKWASM_EXPORT void path_relativeQuadraticBezierTo(SkPath* path,
+SKWASM_EXPORT void path_relativeQuadraticBezierTo(SkPathBuilder* path,
SkScalar x1,
SkScalar y1,
SkScalar x2,
SkScalar y2) {
- path->rQuadTo(x1, y1, x2, y2);
+ path->rQuadTo({x1, y1}, {x2, y2});
}
-SKWASM_EXPORT void path_cubicTo(SkPath* path,
+SKWASM_EXPORT void path_cubicTo(SkPathBuilder* path,
SkScalar x1,
SkScalar y1,
SkScalar x2,
SkScalar y2,
SkScalar x3,
SkScalar y3) {
- path->cubicTo(x1, y1, x2, y2, x3, y3);
+ path->cubicTo({x1, y1}, {x2, y2}, {x3, y3});
}
-SKWASM_EXPORT void path_relativeCubicTo(SkPath* path,
+SKWASM_EXPORT void path_relativeCubicTo(SkPathBuilder* path,
SkScalar x1,
SkScalar y1,
SkScalar x2,
SkScalar y2,
SkScalar x3,
SkScalar y3) {
- path->rCubicTo(x1, y1, x2, y2, x3, y3);
+ path->rCubicTo({x1, y1}, {x2, y2}, {x3, y3});
}
-SKWASM_EXPORT void path_conicTo(SkPath* path,
+SKWASM_EXPORT void path_conicTo(SkPathBuilder* path,
SkScalar x1,
SkScalar y1,
SkScalar x2,
SkScalar y2,
SkScalar w) {
- path->conicTo(x1, y1, x2, y2, w);
+ path->conicTo({x1, y1}, {x2, y2}, w);
}
-SKWASM_EXPORT void path_relativeConicTo(SkPath* path,
+SKWASM_EXPORT void path_relativeConicTo(SkPathBuilder* path,
SkScalar x1,
SkScalar y1,
SkScalar x2,
SkScalar y2,
SkScalar w) {
- path->rConicTo(x1, y1, x2, y2, w);
+ path->rConicTo({x1, y1}, {x2, y2}, w);
}
-SKWASM_EXPORT void path_arcToOval(SkPath* path,
+SKWASM_EXPORT void path_arcToOval(SkPathBuilder* path,
const SkRect* rect,
SkScalar startAngle,
SkScalar sweepAngle,
@@ -113,97 +118,98 @@
path->arcTo(*rect, startAngle, sweepAngle, forceMoveTo);
}
-SKWASM_EXPORT void path_arcToRotated(SkPath* path,
+SKWASM_EXPORT void path_arcToRotated(SkPathBuilder* path,
SkScalar rx,
SkScalar ry,
SkScalar xAxisRotate,
- SkPath::ArcSize arcSize,
+ SkPathBuilder::ArcSize arcSize,
SkPathDirection pathDirection,
SkScalar x,
SkScalar y) {
- path->arcTo(rx, ry, xAxisRotate, arcSize, pathDirection, x, y);
+ path->arcTo({rx, ry}, xAxisRotate, arcSize, pathDirection, {x, y});
}
-SKWASM_EXPORT void path_relativeArcToRotated(SkPath* path,
+SKWASM_EXPORT void path_relativeArcToRotated(SkPathBuilder* path,
SkScalar rx,
SkScalar ry,
SkScalar xAxisRotate,
- SkPath::ArcSize arcSize,
+ SkPathBuilder::ArcSize arcSize,
SkPathDirection pathDirection,
SkScalar x,
SkScalar y) {
- path->rArcTo(rx, ry, xAxisRotate, arcSize, pathDirection, x, y);
+ path->rArcTo({rx, ry}, xAxisRotate, arcSize, pathDirection, {x, y});
}
-SKWASM_EXPORT void path_addRect(SkPath* path, const SkRect* rect) {
+SKWASM_EXPORT void path_addRect(SkPathBuilder* path, const SkRect* rect) {
path->addRect(*rect);
}
-SKWASM_EXPORT void path_addOval(SkPath* path, const SkRect* oval) {
+SKWASM_EXPORT void path_addOval(SkPathBuilder* path, const SkRect* oval) {
path->addOval(*oval, SkPathDirection::kCW, 1);
}
-SKWASM_EXPORT void path_addArc(SkPath* path,
+SKWASM_EXPORT void path_addArc(SkPathBuilder* path,
const SkRect* oval,
SkScalar startAngle,
SkScalar sweepAngle) {
path->addArc(*oval, startAngle, sweepAngle);
}
-SKWASM_EXPORT void path_addPolygon(SkPath* path,
+SKWASM_EXPORT void path_addPolygon(SkPathBuilder* path,
const SkPoint* points,
int count,
bool close) {
- path->addPoly({points, count}, close);
+ path->addPolygon({points, count}, close);
}
-SKWASM_EXPORT void path_addRRect(SkPath* path, const SkScalar* rrectValues) {
+SKWASM_EXPORT void path_addRRect(SkPathBuilder* path,
+ const SkScalar* rrectValues) {
path->addRRect(createSkRRect(rrectValues), SkPathDirection::kCW);
}
-SKWASM_EXPORT void path_addPath(SkPath* path,
- const SkPath* other,
+SKWASM_EXPORT void path_addPath(SkPathBuilder* path,
+ const SkPathBuilder* other,
const SkScalar* matrix33,
SkPath::AddPathMode extendPath) {
- path->addPath(*other, createSkMatrix(matrix33), extendPath);
+ path->addPath(other->snapshot(), createSkMatrix(matrix33), extendPath);
}
-SKWASM_EXPORT void path_close(SkPath* path) {
+SKWASM_EXPORT void path_close(SkPathBuilder* path) {
path->close();
}
-SKWASM_EXPORT void path_reset(SkPath* path) {
+SKWASM_EXPORT void path_reset(SkPathBuilder* path) {
path->reset();
}
-SKWASM_EXPORT bool path_contains(SkPath* path, SkScalar x, SkScalar y) {
- return path->contains(x, y);
+SKWASM_EXPORT bool path_contains(SkPathBuilder* path, SkScalar x, SkScalar y) {
+ return path->contains({x, y});
}
-SKWASM_EXPORT void path_transform(SkPath* path, const SkScalar* matrix33) {
+SKWASM_EXPORT void path_transform(SkPathBuilder* path,
+ const SkScalar* matrix33) {
path->transform(createSkMatrix(matrix33));
}
-SKWASM_EXPORT void path_getBounds(SkPath* path, SkRect* rect) {
- *rect = path->getBounds();
+SKWASM_EXPORT void path_getBounds(SkPathBuilder* path, SkRect* rect) {
+ *rect = path->computeFiniteBounds().value_or(SkRect());
}
-SKWASM_EXPORT SkPath* path_combine(SkPathOp operation,
- const SkPath* path1,
- const SkPath* path2) {
- livePathCount++;
- SkPath* output = new SkPath();
- if (Op(*path1, *path2, operation, output)) {
- output->setFillType(path1->getFillType());
+SKWASM_EXPORT SkPathBuilder* path_combine(SkPathOp operation,
+ const SkPathBuilder* path1,
+ const SkPathBuilder* path2) {
+ if (auto result = Op(path1->snapshot(), path2->snapshot(), operation)) {
+ livePathCount++;
+ SkPathBuilder* output = new SkPathBuilder(result.value());
+ output->setFillType(path1->fillType());
return output;
} else {
- delete output;
return nullptr;
}
}
-SKWASM_EXPORT SkString* path_getSvgString(SkPath* path) {
+SKWASM_EXPORT SkString* path_getSvgString(SkPathBuilder* path) {
liveStringCount++;
- SkString* string = new SkString(SkParsePath::ToSVGString(*path));
+ SkString* string = new SkString(SkParsePath::ToSVGString(path->snapshot()));
return string;
}
diff --git a/engine/src/flutter/skia/flutter_defines.gni b/engine/src/flutter/skia/flutter_defines.gni
index 4fd1771..298ddcc 100644
--- a/engine/src/flutter/skia/flutter_defines.gni
+++ b/engine/src/flutter/skia/flutter_defines.gni
@@ -12,6 +12,7 @@
"SK_DISABLE_LEGACY_PNG_WRITEBUFFER",
"SK_DISABLE_LEGACY_IMAGE_READBUFFER",
+ "SK_HIDE_PATH_EDIT_METHODS",
# Fast low-precision software rendering isn't a priority for Flutter.
"SK_DISABLE_LEGACY_SHADERCONTEXT",
diff --git a/engine/src/flutter/third_party/canvaskit/BUILD.gn b/engine/src/flutter/third_party/canvaskit/BUILD.gn
index 5cae86f..24a2bc6 100644
--- a/engine/src/flutter/third_party/canvaskit/BUILD.gn
+++ b/engine/src/flutter/third_party/canvaskit/BUILD.gn
@@ -85,7 +85,6 @@
skia_enable_skparagraph = false
skia_canvaskit_enable_paragraph = false
skia_enable_shaper = false
- skia_enable_harfbuzz = false
skia_use_harfbuzz = false
skia_use_freetype = false
flutter_use_freetype_woff2 = false
diff --git a/engine/src/flutter/tools/path_ops/dart/lib/path_ops.dart b/engine/src/flutter/tools/path_ops/dart/lib/path_ops.dart
index 2a8661a..1c66f40 100644
--- a/engine/src/flutter/tools/path_ops/dart/lib/path_ops.dart
+++ b/engine/src/flutter/tools/path_ops/dart/lib/path_ops.dart
@@ -144,7 +144,7 @@
return FillType.values[_getFillTypeFn(_path!)];
}
- ffi.Pointer<_SkPath>? _path;
+ ffi.Pointer<_SkPathBuilder>? _path;
ffi.Pointer<_PathData>? _pathData;
/// The number of points used by each [PathVerb].
@@ -293,7 +293,7 @@
throw UnsupportedError('Unknown platform: ${Platform.operatingSystem}');
}();
-final class _SkPath extends ffi.Opaque {}
+final class _SkPathBuilder extends ffi.Opaque {}
final class _PathData extends ffi.Struct {
external ffi.Pointer<ffi.Uint8> verbs;
@@ -307,28 +307,28 @@
external int point_count;
}
-typedef _CreatePathType = ffi.Pointer<_SkPath> Function(int);
-typedef _create_path_type = ffi.Pointer<_SkPath> Function(ffi.Int);
+typedef _CreatePathType = ffi.Pointer<_SkPathBuilder> Function(int);
+typedef _create_path_type = ffi.Pointer<_SkPathBuilder> Function(ffi.Int);
final _CreatePathType _createPathFn = _dylib.lookupFunction<_create_path_type, _CreatePathType>(
'CreatePath',
);
-typedef _MoveToType = void Function(ffi.Pointer<_SkPath>, double, double);
-typedef _move_to_type = ffi.Void Function(ffi.Pointer<_SkPath>, ffi.Float, ffi.Float);
+typedef _MoveToType = void Function(ffi.Pointer<_SkPathBuilder>, double, double);
+typedef _move_to_type = ffi.Void Function(ffi.Pointer<_SkPathBuilder>, ffi.Float, ffi.Float);
final _MoveToType _moveToFn = _dylib.lookupFunction<_move_to_type, _MoveToType>('MoveTo');
-typedef _LineToType = void Function(ffi.Pointer<_SkPath>, double, double);
-typedef _line_to_type = ffi.Void Function(ffi.Pointer<_SkPath>, ffi.Float, ffi.Float);
+typedef _LineToType = void Function(ffi.Pointer<_SkPathBuilder>, double, double);
+typedef _line_to_type = ffi.Void Function(ffi.Pointer<_SkPathBuilder>, ffi.Float, ffi.Float);
final _LineToType _lineToFn = _dylib.lookupFunction<_line_to_type, _LineToType>('LineTo');
typedef _CubicToType =
- void Function(ffi.Pointer<_SkPath>, double, double, double, double, double, double);
+ void Function(ffi.Pointer<_SkPathBuilder>, double, double, double, double, double, double);
typedef _cubic_to_type =
ffi.Void Function(
- ffi.Pointer<_SkPath>,
+ ffi.Pointer<_SkPathBuilder>,
ffi.Float,
ffi.Float,
ffi.Float,
@@ -339,28 +339,29 @@
final _CubicToType _cubicToFn = _dylib.lookupFunction<_cubic_to_type, _CubicToType>('CubicTo');
-typedef _CloseType = void Function(ffi.Pointer<_SkPath>, bool);
-typedef _close_type = ffi.Void Function(ffi.Pointer<_SkPath>, ffi.Bool);
+typedef _CloseType = void Function(ffi.Pointer<_SkPathBuilder>, bool);
+typedef _close_type = ffi.Void Function(ffi.Pointer<_SkPathBuilder>, ffi.Bool);
final _CloseType _closeFn = _dylib.lookupFunction<_close_type, _CloseType>('Close');
-typedef _ResetType = void Function(ffi.Pointer<_SkPath>);
-typedef _reset_type = ffi.Void Function(ffi.Pointer<_SkPath>);
+typedef _ResetType = void Function(ffi.Pointer<_SkPathBuilder>);
+typedef _reset_type = ffi.Void Function(ffi.Pointer<_SkPathBuilder>);
final _ResetType _resetFn = _dylib.lookupFunction<_reset_type, _ResetType>('Reset');
-typedef _DestroyType = void Function(ffi.Pointer<_SkPath>);
-typedef _destroy_type = ffi.Void Function(ffi.Pointer<_SkPath>);
+typedef _DestroyType = void Function(ffi.Pointer<_SkPathBuilder>);
+typedef _destroy_type = ffi.Void Function(ffi.Pointer<_SkPathBuilder>);
final _DestroyType _destroyFn = _dylib.lookupFunction<_destroy_type, _DestroyType>('DestroyPath');
-typedef _OpType = void Function(ffi.Pointer<_SkPath>, ffi.Pointer<_SkPath>, int);
-typedef _op_type = ffi.Void Function(ffi.Pointer<_SkPath>, ffi.Pointer<_SkPath>, ffi.Int);
+typedef _OpType = void Function(ffi.Pointer<_SkPathBuilder>, ffi.Pointer<_SkPathBuilder>, int);
+typedef _op_type =
+ ffi.Void Function(ffi.Pointer<_SkPathBuilder>, ffi.Pointer<_SkPathBuilder>, ffi.Int);
final _OpType _opFn = _dylib.lookupFunction<_op_type, _OpType>('Op');
-typedef _PathDataType = ffi.Pointer<_PathData> Function(ffi.Pointer<_SkPath>);
-typedef _path_data_type = ffi.Pointer<_PathData> Function(ffi.Pointer<_SkPath>);
+typedef _PathDataType = ffi.Pointer<_PathData> Function(ffi.Pointer<_SkPathBuilder>);
+typedef _path_data_type = ffi.Pointer<_PathData> Function(ffi.Pointer<_SkPathBuilder>);
final _PathDataType _dataFn = _dylib.lookupFunction<_path_data_type, _PathDataType>('Data');
@@ -371,8 +372,8 @@
'DestroyData',
);
-typedef _GetFillTypeType = int Function(ffi.Pointer<_SkPath>);
-typedef _get_fill_type_type = ffi.Int32 Function(ffi.Pointer<_SkPath>);
+typedef _GetFillTypeType = int Function(ffi.Pointer<_SkPathBuilder>);
+typedef _get_fill_type_type = ffi.Int32 Function(ffi.Pointer<_SkPathBuilder>);
final _GetFillTypeType _getFillTypeFn = _dylib
.lookupFunction<_get_fill_type_type, _GetFillTypeType>('GetFillType');
diff --git a/engine/src/flutter/tools/path_ops/path_ops.cc b/engine/src/flutter/tools/path_ops/path_ops.cc
index aa01c7b..4157f50 100644
--- a/engine/src/flutter/tools/path_ops/path_ops.cc
+++ b/engine/src/flutter/tools/path_ops/path_ops.cc
@@ -4,26 +4,26 @@
#include "path_ops.h"
+#include "third_party/skia/include/core/SkPath.h"
+
namespace flutter {
-SkPath* CreatePath(SkPathFillType fill_type) {
- auto* path = new SkPath();
- path->setFillType(fill_type);
- return path;
+SkPathBuilder* CreatePath(SkPathFillType fill_type) {
+ return new SkPathBuilder(fill_type);
}
-void DestroyPath(SkPath* path) {
+void DestroyPath(SkPathBuilder* path) {
delete path;
}
-void MoveTo(SkPath* path, SkScalar x, SkScalar y) {
+void MoveTo(SkPathBuilder* path, SkScalar x, SkScalar y) {
path->moveTo(x, y);
}
-void LineTo(SkPath* path, SkScalar x, SkScalar y) {
+void LineTo(SkPathBuilder* path, SkScalar x, SkScalar y) {
path->lineTo(x, y);
}
-void CubicTo(SkPath* path,
+void CubicTo(SkPathBuilder* path,
SkScalar x1,
SkScalar y1,
SkScalar x2,
@@ -33,25 +33,30 @@
path->cubicTo(x1, y1, x2, y2, x3, y3);
}
-void Close(SkPath* path) {
+void Close(SkPathBuilder* path) {
path->close();
}
-void Reset(SkPath* path) {
+void Reset(SkPathBuilder* path) {
path->reset();
}
-void Op(SkPath* one, SkPath* two, SkPathOp op) {
- Op(*one, *two, op, one);
+void Op(SkPathBuilder* one, SkPathBuilder* two, SkPathOp op) {
+ SkPath p1 = one->detach();
+ SkPath p2 = two->snapshot();
+ if (std::optional<SkPath> result = Op(p1, p2, op)) {
+ one->addPath(result.value());
+ }
}
-int GetFillType(SkPath* path) {
- return static_cast<int>(path->getFillType());
+int GetFillType(SkPathBuilder* path) {
+ return static_cast<int>(path->fillType());
}
-struct PathData* Data(SkPath* path) {
- int point_count = path->countPoints();
- int verb_count = path->countVerbs();
+struct PathData* Data(SkPathBuilder* pb) {
+ SkPath path = pb->snapshot();
+ int point_count = path.countPoints();
+ int verb_count = path.countVerbs();
auto data = new PathData();
data->points = new float[point_count * 2];
@@ -60,10 +65,10 @@
data->verb_count = verb_count;
SkSpan<uint8_t> outVerbs(data->verbs, verb_count);
- path->getVerbs(outVerbs);
+ path.getVerbs(outVerbs);
SkSpan<SkPoint> outPoints(reinterpret_cast<SkPoint*>(data->points),
point_count);
- path->getPoints(outPoints);
+ path.getPoints(outPoints);
return data;
}
diff --git a/engine/src/flutter/tools/path_ops/path_ops.h b/engine/src/flutter/tools/path_ops/path_ops.h
index 5384305..5dcc404 100644
--- a/engine/src/flutter/tools/path_ops/path_ops.h
+++ b/engine/src/flutter/tools/path_ops/path_ops.h
@@ -5,7 +5,6 @@
#ifndef FLUTTER_TOOLS_PATH_OPS_PATH_OPS_H_
#define FLUTTER_TOOLS_PATH_OPS_PATH_OPS_H_
-#include "third_party/skia/include/core/SkPath.h"
#include "third_party/skia/include/core/SkPathBuilder.h"
#include "third_party/skia/include/core/SkPathTypes.h"
#include "third_party/skia/include/pathops/SkPathOps.h"
@@ -20,15 +19,15 @@
namespace flutter {
-API SkPath* CreatePath(SkPathFillType fill_type);
+API SkPathBuilder* CreatePath(SkPathFillType fill_type);
-API void DestroyPathBuilder(SkPath* path);
+API void DestroyPath(SkPathBuilder* path);
-API void MoveTo(SkPath* path, SkScalar x, SkScalar y);
+API void MoveTo(SkPathBuilder* path, SkScalar x, SkScalar y);
-API void LineTo(SkPath* path, SkScalar x, SkScalar y);
+API void LineTo(SkPathBuilder* path, SkScalar x, SkScalar y);
-API void CubicTo(SkPath* path,
+API void CubicTo(SkPathBuilder* path,
SkScalar x1,
SkScalar y1,
SkScalar x2,
@@ -36,15 +35,13 @@
SkScalar x3,
SkScalar y3);
-API void Close(SkPath* path);
+API void Close(SkPathBuilder* path);
-API void Reset(SkPath* path);
+API void Reset(SkPathBuilder* path);
-API void DestroyPath(SkPath* path);
+API void Op(SkPathBuilder* one, SkPathBuilder* two, SkPathOp op);
-API void Op(SkPath* one, SkPath* two, SkPathOp op);
-
-API int GetFillType(SkPath* path);
+API int GetFillType(SkPathBuilder* path);
struct API PathData {
uint8_t* verbs;
@@ -53,7 +50,7 @@
size_t point_count;
};
-API struct PathData* Data(SkPath* path);
+API struct PathData* Data(SkPathBuilder* path);
API void DestroyData(PathData* data);