[DisplayList] DlPath object provides auto-conversion from Skia to Impeller (#55055)
Switch from using the clumsy manual CacheablePath object to a more automatic DlPath object for holding paths in DisplayLists and dispatching them to either Skia or Impeller with auto-conversion.
For now DlPath is just a wrapper around SkPath with an auto-generating Impeller Path object which is very similar in design from what was done with the CacheablePath object except that it manages the caching of the Impeller path internally without extra burden on Impeller or Skia. There is also no need to communicate with the Dispatch method as to which type of path you prefer, they're all "auto-converting" DlPath objects now.
For now, ui.Path still generates an SkPath and so we wrap it when we record it into a DisplayList, just like the former CacheablePath mechanism. It will be a simple conversion to create the DlPath wrapper in ui.Path, though, so as to maintain the cached Impeller paths across frames even if the DisplayList itself is not preserved.
Eventually DlPath will take on more of a role of hiding the construction and internal representation of the paths so that we could be using SkPath, impeller::Path, or some other internal storage. For now, SkPath will likely remain primary storage for a while so that we can deal with PathOps.
diff --git a/ci/licenses_golden/excluded_files b/ci/licenses_golden/excluded_files
index 24267d3..cd9d77a 100644
--- a/ci/licenses_golden/excluded_files
+++ b/ci/licenses_golden/excluded_files
@@ -41,6 +41,7 @@
../../../flutter/display_list/effects/dl_image_filter_unittests.cc
../../../flutter/display_list/effects/dl_mask_filter_unittests.cc
../../../flutter/display_list/geometry/dl_geometry_types_unittests.cc
+../../../flutter/display_list/geometry/dl_path_unittests.cc
../../../flutter/display_list/geometry/dl_region_unittests.cc
../../../flutter/display_list/geometry/dl_rtree_unittests.cc
../../../flutter/display_list/skia/dl_sk_conversions_unittests.cc
diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter
index 832c014..b2cb8d6 100644
--- a/ci/licenses_golden/licenses_flutter
+++ b/ci/licenses_golden/licenses_flutter
@@ -42345,6 +42345,8 @@
ORIGIN: ../../../flutter/display_list/effects/dl_runtime_effect.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/display_list/effects/dl_runtime_effect.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/display_list/geometry/dl_geometry_types.h + ../../../flutter/LICENSE
+ORIGIN: ../../../flutter/display_list/geometry/dl_path.cc + ../../../flutter/LICENSE
+ORIGIN: ../../../flutter/display_list/geometry/dl_path.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/display_list/geometry/dl_region.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/display_list/geometry/dl_region.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/display_list/geometry/dl_rtree.cc + ../../../flutter/LICENSE
@@ -45240,6 +45242,8 @@
FILE: ../../../flutter/display_list/effects/dl_runtime_effect.cc
FILE: ../../../flutter/display_list/effects/dl_runtime_effect.h
FILE: ../../../flutter/display_list/geometry/dl_geometry_types.h
+FILE: ../../../flutter/display_list/geometry/dl_path.cc
+FILE: ../../../flutter/display_list/geometry/dl_path.h
FILE: ../../../flutter/display_list/geometry/dl_region.cc
FILE: ../../../flutter/display_list/geometry/dl_region.h
FILE: ../../../flutter/display_list/geometry/dl_rtree.cc
diff --git a/display_list/BUILD.gn b/display_list/BUILD.gn
index 781e5b0..dbb81d4 100644
--- a/display_list/BUILD.gn
+++ b/display_list/BUILD.gn
@@ -60,6 +60,8 @@
"effects/dl_runtime_effect.cc",
"effects/dl_runtime_effect.h",
"geometry/dl_geometry_types.h",
+ "geometry/dl_path.cc",
+ "geometry/dl_path.h",
"geometry/dl_region.cc",
"geometry/dl_region.h",
"geometry/dl_rtree.cc",
@@ -119,6 +121,7 @@
"effects/dl_image_filter_unittests.cc",
"effects/dl_mask_filter_unittests.cc",
"geometry/dl_geometry_types_unittests.cc",
+ "geometry/dl_path_unittests.cc",
"geometry/dl_region_unittests.cc",
"geometry/dl_rtree_unittests.cc",
"skia/dl_sk_conversions_unittests.cc",
diff --git a/display_list/benchmarking/dl_complexity_gl.cc b/display_list/benchmarking/dl_complexity_gl.cc
index 28ca569..44f658b 100644
--- a/display_list/benchmarking/dl_complexity_gl.cc
+++ b/display_list/benchmarking/dl_complexity_gl.cc
@@ -332,7 +332,7 @@
AccumulateComplexity(complexity);
}
-void DisplayListGLComplexityCalculator::GLHelper::drawPath(const SkPath& path) {
+void DisplayListGLComplexityCalculator::GLHelper::drawPath(const DlPath& path) {
if (IsComplex()) {
return;
}
@@ -655,7 +655,7 @@
DlScalar y) {}
void DisplayListGLComplexityCalculator::GLHelper::drawShadow(
- const SkPath& path,
+ const DlPath& path,
const DlColor color,
const DlScalar elevation,
bool transparent_occluder,
diff --git a/display_list/benchmarking/dl_complexity_gl.h b/display_list/benchmarking/dl_complexity_gl.h
index 5384959..d0fcbb9 100644
--- a/display_list/benchmarking/dl_complexity_gl.h
+++ b/display_list/benchmarking/dl_complexity_gl.h
@@ -49,7 +49,7 @@
void drawCircle(const DlPoint& center, DlScalar radius) override;
void drawRRect(const SkRRect& rrect) override;
void drawDRRect(const SkRRect& outer, const SkRRect& inner) override;
- void drawPath(const SkPath& path) override;
+ void drawPath(const DlPath& path) override;
void drawArc(const DlRect& oval_bounds,
DlScalar start_degrees,
DlScalar sweep_degrees,
@@ -76,7 +76,7 @@
void drawTextFrame(const std::shared_ptr<impeller::TextFrame>& text_frame,
DlScalar x,
DlScalar y) override;
- void drawShadow(const SkPath& path,
+ void drawShadow(const DlPath& path,
const DlColor color,
const DlScalar elevation,
bool transparent_occluder,
diff --git a/display_list/benchmarking/dl_complexity_helper.h b/display_list/benchmarking/dl_complexity_helper.h
index 8393151..1303ff3 100644
--- a/display_list/benchmarking/dl_complexity_helper.h
+++ b/display_list/benchmarking/dl_complexity_helper.h
@@ -214,11 +214,12 @@
inline unsigned int Ceiling() { return ceiling_; }
inline unsigned int CurrentComplexityScore() { return complexity_score_; }
- unsigned int CalculatePathComplexity(const SkPath& path,
+ unsigned int CalculatePathComplexity(const DlPath& dl_path,
unsigned int line_verb_cost,
unsigned int quad_verb_cost,
unsigned int conic_verb_cost,
unsigned int cubic_verb_cost) {
+ const SkPath& path = dl_path.GetSkPath();
int verb_count = path.countVerbs();
std::vector<uint8_t> verbs(verb_count);
path.getVerbs(verbs.data(), verbs.size());
diff --git a/display_list/benchmarking/dl_complexity_metal.cc b/display_list/benchmarking/dl_complexity_metal.cc
index 6f69eb8..82f641e 100644
--- a/display_list/benchmarking/dl_complexity_metal.cc
+++ b/display_list/benchmarking/dl_complexity_metal.cc
@@ -329,7 +329,7 @@
}
void DisplayListMetalComplexityCalculator::MetalHelper::drawPath(
- const SkPath& path) {
+ const DlPath& path) {
if (IsComplex()) {
return;
}
@@ -599,7 +599,7 @@
DlScalar y) {}
void DisplayListMetalComplexityCalculator::MetalHelper::drawShadow(
- const SkPath& path,
+ const DlPath& path,
const DlColor color,
const DlScalar elevation,
bool transparent_occluder,
diff --git a/display_list/benchmarking/dl_complexity_metal.h b/display_list/benchmarking/dl_complexity_metal.h
index 8c428cd..d11d0ff 100644
--- a/display_list/benchmarking/dl_complexity_metal.h
+++ b/display_list/benchmarking/dl_complexity_metal.h
@@ -49,7 +49,7 @@
void drawCircle(const DlPoint& center, DlScalar radius) override;
void drawRRect(const SkRRect& rrect) override;
void drawDRRect(const SkRRect& outer, const SkRRect& inner) override;
- void drawPath(const SkPath& path) override;
+ void drawPath(const DlPath& path) override;
void drawArc(const DlRect& oval_bounds,
DlScalar start_degrees,
DlScalar sweep_degrees,
@@ -76,7 +76,7 @@
void drawTextFrame(const std::shared_ptr<impeller::TextFrame>& text_frame,
DlScalar x,
DlScalar y) override;
- void drawShadow(const SkPath& path,
+ void drawShadow(const DlPath& path,
const DlColor color,
const DlScalar elevation,
bool transparent_occluder,
diff --git a/display_list/display_list_unittests.cc b/display_list/display_list_unittests.cc
index 8d67422..9838573 100644
--- a/display_list/display_list_unittests.cc
+++ b/display_list/display_list_unittests.cc
@@ -3618,98 +3618,6 @@
});
}
-TEST_F(DisplayListTest, ImpellerPathPreferenceIsHonored) {
- class Tester : public virtual DlOpReceiver,
- public IgnoreClipDispatchHelper,
- public IgnoreDrawDispatchHelper,
- public IgnoreAttributeDispatchHelper,
- public IgnoreTransformDispatchHelper {
- public:
- explicit Tester(bool prefer_impeller_paths)
- : prefer_impeller_paths_(prefer_impeller_paths) {}
-
- bool PrefersImpellerPaths() const override {
- return prefer_impeller_paths_;
- }
-
- void drawPath(const SkPath& path) override { skia_draw_path_calls_++; }
-
- void drawPath(const CacheablePath& cache) override {
- impeller_draw_path_calls_++;
- }
-
- void clipPath(const SkPath& path, ClipOp op, bool is_aa) override {
- skia_clip_path_calls_++;
- }
-
- void clipPath(const CacheablePath& cache, ClipOp op, bool is_aa) override {
- impeller_clip_path_calls_++;
- }
-
- virtual void drawShadow(const SkPath& sk_path,
- const DlColor color,
- const SkScalar elevation,
- bool transparent_occluder,
- SkScalar dpr) override {
- skia_draw_shadow_calls_++;
- }
-
- virtual void drawShadow(const CacheablePath& cache,
- const DlColor color,
- const SkScalar elevation,
- bool transparent_occluder,
- SkScalar dpr) override {
- impeller_draw_shadow_calls_++;
- }
-
- int skia_draw_path_calls() const { return skia_draw_path_calls_; }
- int skia_clip_path_calls() const { return skia_draw_path_calls_; }
- int skia_draw_shadow_calls() const { return skia_draw_path_calls_; }
- int impeller_draw_path_calls() const { return impeller_draw_path_calls_; }
- int impeller_clip_path_calls() const { return impeller_draw_path_calls_; }
- int impeller_draw_shadow_calls() const { return impeller_draw_path_calls_; }
-
- private:
- const bool prefer_impeller_paths_;
- int skia_draw_path_calls_ = 0;
- int skia_clip_path_calls_ = 0;
- int skia_draw_shadow_calls_ = 0;
- int impeller_draw_path_calls_ = 0;
- int impeller_clip_path_calls_ = 0;
- int impeller_draw_shadow_calls_ = 0;
- };
-
- DisplayListBuilder builder;
- builder.DrawPath(SkPath::Rect(SkRect::MakeLTRB(0, 0, 100, 100)), DlPaint());
- builder.ClipPath(SkPath::Rect(SkRect::MakeLTRB(0, 0, 100, 100)),
- ClipOp::kIntersect, true);
- builder.DrawShadow(SkPath::Rect(SkRect::MakeLTRB(20, 20, 80, 80)),
- DlColor::kBlue(), 1.0f, true, 1.0f);
- auto display_list = builder.Build();
-
- {
- Tester skia_tester(false);
- display_list->Dispatch(skia_tester);
- EXPECT_EQ(skia_tester.skia_draw_path_calls(), 1);
- EXPECT_EQ(skia_tester.skia_clip_path_calls(), 1);
- EXPECT_EQ(skia_tester.skia_draw_shadow_calls(), 1);
- EXPECT_EQ(skia_tester.impeller_draw_path_calls(), 0);
- EXPECT_EQ(skia_tester.impeller_clip_path_calls(), 0);
- EXPECT_EQ(skia_tester.impeller_draw_shadow_calls(), 0);
- }
-
- {
- Tester impeller_tester(true);
- display_list->Dispatch(impeller_tester);
- EXPECT_EQ(impeller_tester.skia_draw_path_calls(), 0);
- EXPECT_EQ(impeller_tester.skia_clip_path_calls(), 0);
- EXPECT_EQ(impeller_tester.skia_draw_shadow_calls(), 0);
- EXPECT_EQ(impeller_tester.impeller_draw_path_calls(), 1);
- EXPECT_EQ(impeller_tester.impeller_clip_path_calls(), 1);
- EXPECT_EQ(impeller_tester.impeller_draw_shadow_calls(), 1);
- }
-}
-
class SaveLayerBoundsExpector : public virtual DlOpReceiver,
public IgnoreAttributeDispatchHelper,
public IgnoreClipDispatchHelper,
@@ -4616,7 +4524,7 @@
#define CLIP_EXPECTOR(name) ClipExpector name(__FILE__, __LINE__)
struct ClipExpectation {
- std::variant<DlRect, SkRRect, SkPath> shape;
+ std::variant<DlRect, SkRRect, DlPath> shape;
bool is_oval;
ClipOp clip_op;
bool is_aa;
@@ -4628,7 +4536,7 @@
case 1:
return "SkRRect";
case 2:
- return "SkPath";
+ return "DlPath";
default:
return "Unknown";
}
@@ -4648,7 +4556,7 @@
os << std::get<SkRRect>(expect.shape);
break;
case 2:
- os << std::get<SkPath>(expect.shape);
+ os << std::get<DlPath>(expect.shape).GetSkPath();
break;
case 3:
os << "Unknown";
@@ -4713,7 +4621,7 @@
return *this;
}
- ClipExpector& addExpectation(const SkPath& path,
+ ClipExpector& addExpectation(const DlPath& path,
ClipOp clip_op = ClipOp::kIntersect,
bool is_aa = false) {
clip_expectations_.push_back({
@@ -4725,6 +4633,12 @@
return *this;
}
+ ClipExpector& addExpectation(const SkPath& path,
+ ClipOp clip_op = ClipOp::kIntersect,
+ bool is_aa = false) {
+ return addExpectation(DlPath(path), clip_op, is_aa);
+ }
+
void clipRect(const DlRect& rect,
DlCanvas::ClipOp clip_op,
bool is_aa) override {
@@ -4740,7 +4654,7 @@
bool is_aa) override {
check(rrect, clip_op, is_aa);
}
- void clipPath(const SkPath& path,
+ void clipPath(const DlPath& path,
DlCanvas::ClipOp clip_op,
bool is_aa) override {
check(path, clip_op, is_aa);
diff --git a/display_list/dl_builder.cc b/display_list/dl_builder.cc
index d1f3707..c5329c6 100644
--- a/display_list/dl_builder.cc
+++ b/display_list/dl_builder.cc
@@ -1044,30 +1044,30 @@
break;
}
}
-void DisplayListBuilder::ClipPath(const SkPath& path,
+void DisplayListBuilder::ClipPath(const DlPath& path,
ClipOp clip_op,
bool is_aa) {
if (current_info().is_nop) {
return;
}
- if (!path.isInverseFillType()) {
+ if (!path.IsInverseFillType()) {
SkRect rect;
- if (path.isRect(&rect)) {
+ if (path.IsSkRect(&rect)) {
ClipRect(rect, clip_op, is_aa);
return;
}
- if (path.isOval(&rect)) {
+ if (path.IsSkOval(&rect)) {
ClipOval(rect, clip_op, is_aa);
return;
}
SkRRect rrect;
- if (path.isRRect(&rrect)) {
+ if (path.IsSkRRect(&rrect)) {
ClipRRect(rrect, clip_op, is_aa);
return;
}
}
- global_state().clipPath(path, clip_op, is_aa);
- layer_local_state().clipPath(path, clip_op, is_aa);
+ global_state().clipPath(path.GetSkPath(), clip_op, is_aa);
+ layer_local_state().clipPath(path.GetSkPath(), clip_op, is_aa);
if (global_state().is_cull_rect_empty() ||
layer_local_state().is_cull_rect_empty()) {
current_info().is_nop = true;
@@ -1234,13 +1234,14 @@
SetAttributesFromPaint(paint, DisplayListOpFlags::kDrawDRRectFlags);
drawDRRect(outer, inner);
}
-void DisplayListBuilder::drawPath(const SkPath& path) {
+void DisplayListBuilder::drawPath(const DlPath& path) {
DisplayListAttributeFlags flags = kDrawPathFlags;
OpResult result = PaintResult(current_, flags);
if (result != OpResult::kNoEffect) {
- bool is_visible = path.isInverseFillType()
- ? AccumulateUnbounded()
- : AccumulateOpBounds(path.getBounds(), flags);
+ bool is_visible =
+ path.IsInverseFillType()
+ ? AccumulateUnbounded()
+ : AccumulateOpBounds(ToSkRect(path.GetBounds()), flags);
if (is_visible) {
Push<DrawPathOp>(0, path);
CheckLayerOpacityHairlineCompatibility();
@@ -1250,6 +1251,11 @@
}
void DisplayListBuilder::DrawPath(const SkPath& path, const DlPaint& paint) {
SetAttributesFromPaint(paint, DisplayListOpFlags::kDrawPathFlags);
+ DlPath dl_path(path);
+ drawPath(dl_path);
+}
+void DisplayListBuilder::DrawPath(const DlPath& path, const DlPaint& paint) {
+ SetAttributesFromPaint(paint, DisplayListOpFlags::kDrawPathFlags);
drawPath(path);
}
@@ -1731,15 +1737,15 @@
drawTextFrame(text_frame, x, y);
}
-void DisplayListBuilder::DrawShadow(const SkPath& path,
+void DisplayListBuilder::DrawShadow(const DlPath& path,
const DlColor color,
const DlScalar elevation,
bool transparent_occluder,
DlScalar dpr) {
OpResult result = PaintResult(DlPaint(color));
if (result != OpResult::kNoEffect) {
- SkRect shadow_bounds =
- DlCanvas::ComputeShadowBounds(path, elevation, dpr, GetTransform());
+ SkRect shadow_bounds = DlCanvas::ComputeShadowBounds(
+ path.GetSkPath(), elevation, dpr, GetTransform());
if (AccumulateOpBounds(shadow_bounds, kDrawShadowFlags)) {
transparent_occluder //
? Push<DrawShadowTransparentOccluderOp>(0, path, color, elevation,
diff --git a/display_list/dl_builder.h b/display_list/dl_builder.h
index f6a7069..ed2a5a8 100644
--- a/display_list/dl_builder.h
+++ b/display_list/dl_builder.h
@@ -127,6 +127,12 @@
// |DlCanvas|
void ClipPath(const SkPath& path,
ClipOp clip_op = ClipOp::kIntersect,
+ bool is_aa = false) override {
+ ClipPath(DlPath(path), clip_op, is_aa);
+ }
+ // |DlCanvas|
+ void ClipPath(const DlPath& path,
+ ClipOp clip_op = ClipOp::kIntersect,
bool is_aa = false) override;
/// Conservative estimate of the bounds of all outstanding clip operations
@@ -181,6 +187,8 @@
// |DlCanvas|
void DrawPath(const SkPath& path, const DlPaint& paint) override;
// |DlCanvas|
+ void DrawPath(const DlPath& path, const DlPaint& paint) override;
+ // |DlCanvas|
void DrawArc(const SkRect& bounds,
DlScalar start,
DlScalar sweep,
@@ -248,6 +256,14 @@
const DlColor color,
const DlScalar elevation,
bool transparent_occluder,
+ DlScalar dpr) override {
+ DrawShadow(DlPath(path), color, elevation, transparent_occluder, dpr);
+ }
+ // |DlCanvas|
+ void DrawShadow(const DlPath& path,
+ const DlColor color,
+ const DlScalar elevation,
+ bool transparent_occluder,
DlScalar dpr) override;
// |DlCanvas|
@@ -412,7 +428,7 @@
ClipRRect(rrect, clip_op, is_aa);
}
// |DlOpReceiver|
- void clipPath(const SkPath& path, ClipOp clip_op, bool is_aa) override {
+ void clipPath(const DlPath& path, ClipOp clip_op, bool is_aa) override {
ClipPath(path, clip_op, is_aa);
}
@@ -440,7 +456,7 @@
// |DlOpReceiver|
void drawDRRect(const SkRRect& outer, const SkRRect& inner) override;
// |DlOpReceiver|
- void drawPath(const SkPath& path) override;
+ void drawPath(const DlPath& path) override;
// |DlOpReceiver|
void drawArc(const DlRect& bounds,
DlScalar start,
@@ -492,7 +508,7 @@
DlScalar x,
DlScalar y) override;
// |DlOpReceiver|
- void drawShadow(const SkPath& path,
+ void drawShadow(const DlPath& path,
const DlColor color,
const DlScalar elevation,
bool transparent_occluder,
diff --git a/display_list/dl_canvas.h b/display_list/dl_canvas.h
index f21e54a..43771e3 100644
--- a/display_list/dl_canvas.h
+++ b/display_list/dl_canvas.h
@@ -9,6 +9,7 @@
#include "flutter/display_list/dl_paint.h"
#include "flutter/display_list/dl_vertices.h"
#include "flutter/display_list/geometry/dl_geometry_types.h"
+#include "flutter/display_list/geometry/dl_path.h"
#include "flutter/display_list/image/dl_image.h"
#include "third_party/skia/include/core/SkM44.h"
@@ -114,6 +115,11 @@
virtual void ClipPath(const SkPath& path,
ClipOp clip_op = ClipOp::kIntersect,
bool is_aa = false) = 0;
+ virtual void ClipPath(const DlPath& path,
+ ClipOp clip_op = ClipOp::kIntersect,
+ bool is_aa = false) {
+ ClipPath(path.GetSkPath(), clip_op, is_aa);
+ }
/// Conservative estimate of the bounds of all outstanding clip operations
/// measured in the coordinate space within which this DisplayList will
@@ -151,6 +157,9 @@
const SkRRect& inner,
const DlPaint& paint) = 0;
virtual void DrawPath(const SkPath& path, const DlPaint& paint) = 0;
+ virtual void DrawPath(const DlPath& path, const DlPaint& paint) {
+ DrawPath(path.GetSkPath(), paint);
+ }
virtual void DrawArc(const SkRect& bounds,
DlScalar start,
DlScalar sweep,
@@ -222,6 +231,13 @@
const DlScalar elevation,
bool transparent_occluder,
DlScalar dpr) = 0;
+ virtual void DrawShadow(const DlPath& path,
+ const DlColor color,
+ const DlScalar elevation,
+ bool transparent_occluder,
+ DlScalar dpr) {
+ DrawShadow(path.GetSkPath(), color, elevation, transparent_occluder, dpr);
+ }
virtual void Flush() = 0;
diff --git a/display_list/dl_op_receiver.h b/display_list/dl_op_receiver.h
index 6f0ebae..091ed6f 100644
--- a/display_list/dl_op_receiver.h
+++ b/display_list/dl_op_receiver.h
@@ -96,46 +96,6 @@
// MaxDrawPointsCount * sizeof(DlPoint) must be less than 1 << 32
static constexpr int kMaxDrawPointsCount = ((1 << 29) - 1);
- // ---------------------------------------------------------------------
- // The CacheablePath forms of the drawPath, clipPath, and drawShadow
- // methods are only called if the DlOpReceiver indicates that it prefers
- // impeller paths by returning true from |PrefersImpellerPaths|.
- // Note that we pass in both the SkPath and (a place to cache the)
- // impeller::Path forms of the path since the SkPath version can contain
- // information about the type of path that lets the receiver optimize
- // the operation (and potentially avoid the need to cache it).
- // It is up to the receiver to convert the path to Impeller form and
- // cache it to avoid needing to do a lot of Impeller-specific processing
- // inside the DisplayList code.
-
- virtual bool PrefersImpellerPaths() const { return false; }
-
- struct CacheablePath {
- explicit CacheablePath(const SkPath& path) : sk_path(path) {}
-
- const SkPath sk_path;
- mutable impeller::Path cached_impeller_path;
-
- bool operator==(const CacheablePath& other) const {
- return sk_path == other.sk_path;
- }
- };
-
- virtual void clipPath(const CacheablePath& cache,
- ClipOp clip_op,
- bool is_aa) {
- FML_UNREACHABLE();
- }
- virtual void drawPath(const CacheablePath& cache) { FML_UNREACHABLE(); }
- virtual void drawShadow(const CacheablePath& cache,
- const DlColor color,
- const DlScalar elevation,
- bool transparent_occluder,
- DlScalar dpr) {
- FML_UNREACHABLE();
- }
- // ---------------------------------------------------------------------
-
// The following methods are nearly 1:1 with the methods on DlPaint and
// carry the same meanings. Each method sets a persistent value for the
// attribute for the rest of the display list or until it is reset by
@@ -330,7 +290,7 @@
virtual void clipRect(const DlRect& rect, ClipOp clip_op, bool is_aa) = 0;
virtual void clipOval(const DlRect& bounds, ClipOp clip_op, bool is_aa) = 0;
virtual void clipRRect(const SkRRect& rrect, ClipOp clip_op, bool is_aa) = 0;
- virtual void clipPath(const SkPath& path, ClipOp clip_op, bool is_aa) = 0;
+ virtual void clipPath(const DlPath& path, ClipOp clip_op, bool is_aa) = 0;
// The following rendering methods all take their rendering attributes
// from the last value set by the attribute methods above (regardless
@@ -351,7 +311,7 @@
virtual void drawCircle(const DlPoint& center, DlScalar radius) = 0;
virtual void drawRRect(const SkRRect& rrect) = 0;
virtual void drawDRRect(const SkRRect& outer, const SkRRect& inner) = 0;
- virtual void drawPath(const SkPath& path) = 0;
+ virtual void drawPath(const DlPath& path) = 0;
virtual void drawArc(const DlRect& oval_bounds,
DlScalar start_degrees,
DlScalar sweep_degrees,
@@ -395,7 +355,7 @@
const std::shared_ptr<impeller::TextFrame>& text_frame,
DlScalar x,
DlScalar y) = 0;
- virtual void drawShadow(const SkPath& path,
+ virtual void drawShadow(const DlPath& path,
const DlColor color,
const DlScalar elevation,
bool transparent_occluder,
diff --git a/display_list/dl_op_records.h b/display_list/dl_op_records.h
index 9bc5385..f14025b 100644
--- a/display_list/dl_op_records.h
+++ b/display_list/dl_op_records.h
@@ -510,30 +510,25 @@
DEFINE_CLIP_SHAPE_OP(RRect, SkRRect, Difference)
#undef DEFINE_CLIP_SHAPE_OP
-#define DEFINE_CLIP_PATH_OP(clipop) \
- struct Clip##clipop##PathOp final : TransformClipOpBase { \
- static constexpr auto kType = DisplayListOpType::kClip##clipop##Path; \
- \
- Clip##clipop##PathOp(const SkPath& path, bool is_aa) \
- : is_aa(is_aa), cached_path(path) {} \
- \
- const bool is_aa; \
- const DlOpReceiver::CacheablePath cached_path; \
- \
- void dispatch(DlOpReceiver& receiver) const { \
- if (receiver.PrefersImpellerPaths()) { \
- receiver.clipPath(cached_path, DlCanvas::ClipOp::k##clipop, is_aa); \
- } else { \
- receiver.clipPath(cached_path.sk_path, DlCanvas::ClipOp::k##clipop, \
- is_aa); \
- } \
- } \
- \
- DisplayListCompare equals(const Clip##clipop##PathOp* other) const { \
- return is_aa == other->is_aa && cached_path == other->cached_path \
- ? DisplayListCompare::kEqual \
- : DisplayListCompare::kNotEqual; \
- } \
+#define DEFINE_CLIP_PATH_OP(clipop) \
+ struct Clip##clipop##PathOp final : TransformClipOpBase { \
+ static constexpr auto kType = DisplayListOpType::kClip##clipop##Path; \
+ \
+ Clip##clipop##PathOp(const DlPath& path, bool is_aa) \
+ : is_aa(is_aa), path(path) {} \
+ \
+ const bool is_aa; \
+ const DlPath path; \
+ \
+ void dispatch(DlOpReceiver& receiver) const { \
+ receiver.clipPath(path, DlCanvas::ClipOp::k##clipop, is_aa); \
+ } \
+ \
+ DisplayListCompare equals(const Clip##clipop##PathOp* other) const { \
+ return is_aa == other->is_aa && path == other->path \
+ ? DisplayListCompare::kEqual \
+ : DisplayListCompare::kNotEqual; \
+ } \
};
DEFINE_CLIP_PATH_OP(Intersect)
DEFINE_CLIP_PATH_OP(Difference)
@@ -596,21 +591,17 @@
struct DrawPathOp final : DrawOpBase {
static constexpr auto kType = DisplayListOpType::kDrawPath;
- explicit DrawPathOp(const SkPath& path) : cached_path(path) {}
+ explicit DrawPathOp(const DlPath& path) : path(path) {}
- const DlOpReceiver::CacheablePath cached_path;
+ const DlPath path;
- void dispatch(DlOpReceiver& receiver) const {
- if (receiver.PrefersImpellerPaths()) {
- receiver.drawPath(cached_path);
- } else {
- receiver.drawPath(cached_path.sk_path);
- }
+ void dispatch(DlOpReceiver& receiver) const { //
+ receiver.drawPath(path);
}
DisplayListCompare equals(const DrawPathOp* other) const {
- return cached_path == other->cached_path ? DisplayListCompare::kEqual
- : DisplayListCompare::kNotEqual;
+ return path == other->path ? DisplayListCompare::kEqual
+ : DisplayListCompare::kNotEqual;
}
};
@@ -1005,37 +996,31 @@
};
// 4 byte header + 140 byte payload packs evenly into 140 bytes
-#define DEFINE_DRAW_SHADOW_OP(name, transparent_occluder) \
- struct Draw##name##Op final : DrawOpBase { \
- static constexpr auto kType = DisplayListOpType::kDraw##name; \
- \
- Draw##name##Op(const SkPath& path, \
- DlColor color, \
- DlScalar elevation, \
- DlScalar dpr) \
- : color(color), elevation(elevation), dpr(dpr), cached_path(path) {} \
- \
- const DlColor color; \
- const DlScalar elevation; \
- const DlScalar dpr; \
- const DlOpReceiver::CacheablePath cached_path; \
- \
- void dispatch(DlOpReceiver& receiver) const { \
- if (receiver.PrefersImpellerPaths()) { \
- receiver.drawShadow(cached_path, color, elevation, \
- transparent_occluder, dpr); \
- } else { \
- receiver.drawShadow(cached_path.sk_path, color, elevation, \
- transparent_occluder, dpr); \
- } \
- } \
- \
- DisplayListCompare equals(const Draw##name##Op* other) const { \
- return color == other->color && elevation == other->elevation && \
- dpr == other->dpr && cached_path == other->cached_path \
- ? DisplayListCompare::kEqual \
- : DisplayListCompare::kNotEqual; \
- } \
+#define DEFINE_DRAW_SHADOW_OP(name, transparent_occluder) \
+ struct Draw##name##Op final : DrawOpBase { \
+ static constexpr auto kType = DisplayListOpType::kDraw##name; \
+ \
+ Draw##name##Op(const DlPath& path, \
+ DlColor color, \
+ DlScalar elevation, \
+ DlScalar dpr) \
+ : color(color), elevation(elevation), dpr(dpr), path(path) {} \
+ \
+ const DlColor color; \
+ const DlScalar elevation; \
+ const DlScalar dpr; \
+ const DlPath path; \
+ \
+ void dispatch(DlOpReceiver& receiver) const { \
+ receiver.drawShadow(path, color, elevation, transparent_occluder, dpr); \
+ } \
+ \
+ DisplayListCompare equals(const Draw##name##Op* other) const { \
+ return color == other->color && elevation == other->elevation && \
+ dpr == other->dpr && path == other->path \
+ ? DisplayListCompare::kEqual \
+ : DisplayListCompare::kNotEqual; \
+ } \
};
DEFINE_DRAW_SHADOW_OP(Shadow, false)
DEFINE_DRAW_SHADOW_OP(ShadowTransparentOccluder, true)
diff --git a/display_list/geometry/dl_geometry_types.h b/display_list/geometry/dl_geometry_types.h
index d50cb36..0825ebe 100644
--- a/display_list/geometry/dl_geometry_types.h
+++ b/display_list/geometry/dl_geometry_types.h
@@ -51,6 +51,10 @@
return *reinterpret_cast<const DlIRect*>(&rect);
}
+inline DlRect* ToDlRect(SkRect* rect) {
+ return rect == nullptr ? nullptr : reinterpret_cast<DlRect*>(rect);
+}
+
inline const DlRect* ToDlRect(const SkRect* rect) {
return rect == nullptr ? nullptr : reinterpret_cast<const DlRect*>(rect);
}
@@ -100,6 +104,10 @@
return rect == nullptr ? nullptr : reinterpret_cast<const SkRect*>(rect);
}
+inline SkRect* ToSkRect(DlRect* rect) {
+ return rect == nullptr ? nullptr : reinterpret_cast<SkRect*>(rect);
+}
+
inline const SkRect* ToSkRects(const DlRect* rects) {
return rects == nullptr ? nullptr : reinterpret_cast<const SkRect*>(rects);
}
diff --git a/display_list/geometry/dl_path.cc b/display_list/geometry/dl_path.cc
new file mode 100644
index 0000000..4ab67ae
--- /dev/null
+++ b/display_list/geometry/dl_path.cc
@@ -0,0 +1,159 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "flutter/display_list/geometry/dl_path.h"
+
+#include "flutter/display_list/geometry/dl_geometry_types.h"
+#include "flutter/impeller/geometry/path_builder.h"
+
+namespace flutter {
+
+const SkPath& DlPath::GetSkPath() const {
+ return sk_path_;
+}
+
+impeller::Path DlPath::GetPath() const {
+ if (path_.IsEmpty() && !sk_path_.isEmpty()) {
+ path_ = ConvertToImpellerPath(sk_path_);
+ }
+
+ return path_;
+}
+
+bool DlPath::IsInverseFillType() const {
+ return sk_path_.isInverseFillType();
+}
+
+bool DlPath::IsRect(DlRect* rect, bool* is_closed) const {
+ return sk_path_.isRect(ToSkRect(rect), is_closed);
+}
+
+bool DlPath::IsOval(DlRect* bounds) const {
+ return sk_path_.isOval(ToSkRect(bounds));
+}
+
+bool DlPath::IsSkRect(SkRect* rect, bool* is_closed) const {
+ return sk_path_.isRect(rect, is_closed);
+}
+
+bool DlPath::IsSkOval(SkRect* bounds) const {
+ return sk_path_.isOval(bounds);
+}
+
+bool DlPath::IsSkRRect(SkRRect* rrect) const {
+ return sk_path_.isRRect(rrect);
+}
+
+SkRect DlPath::GetSkBounds() const {
+ return sk_path_.getBounds();
+}
+
+DlRect DlPath::GetBounds() const {
+ return ToDlRect(sk_path_.getBounds());
+}
+
+bool DlPath::operator==(const DlPath& other) const {
+ return sk_path_ == other.sk_path_;
+}
+
+bool DlPath::IsConverted() const {
+ if (!path_.IsEmpty()) {
+ return true;
+ }
+ if (sk_path_.isEmpty()) {
+ return true;
+ }
+ return false;
+}
+
+using Path = impeller::Path;
+using PathBuilder = impeller::PathBuilder;
+using FillType = impeller::FillType;
+using Convexity = impeller::Convexity;
+
+Path DlPath::ConvertToImpellerPath(const SkPath& path, const DlPoint& shift) {
+ auto iterator = SkPath::Iter(path, false);
+
+ struct PathData {
+ union {
+ SkPoint points[4];
+ };
+ };
+
+ PathBuilder builder;
+ PathData data;
+ // Reserve a path size with some arbitrarily additional padding.
+ builder.Reserve(path.countPoints() + 8, path.countVerbs() + 8);
+ auto verb = SkPath::Verb::kDone_Verb;
+ do {
+ verb = iterator.next(data.points);
+ switch (verb) {
+ case SkPath::kMove_Verb:
+ builder.MoveTo(ToDlPoint(data.points[0]));
+ break;
+ case SkPath::kLine_Verb:
+ builder.LineTo(ToDlPoint(data.points[1]));
+ break;
+ case SkPath::kQuad_Verb:
+ builder.QuadraticCurveTo(ToDlPoint(data.points[1]),
+ ToDlPoint(data.points[2]));
+ break;
+ case SkPath::kConic_Verb: {
+ constexpr auto kPow2 = 1; // Only works for sweeps up to 90 degrees.
+ constexpr auto kQuadCount = 1 + (2 * (1 << kPow2));
+ SkPoint points[kQuadCount];
+ const auto curve_count =
+ SkPath::ConvertConicToQuads(data.points[0], //
+ data.points[1], //
+ data.points[2], //
+ iterator.conicWeight(), //
+ points, //
+ kPow2 //
+ );
+
+ for (int curve_index = 0, point_index = 0; //
+ curve_index < curve_count; //
+ curve_index++, point_index += 2 //
+ ) {
+ builder.QuadraticCurveTo(ToDlPoint(points[point_index + 1]),
+ ToDlPoint(points[point_index + 2]));
+ }
+ } break;
+ case SkPath::kCubic_Verb:
+ builder.CubicCurveTo(ToDlPoint(data.points[1]),
+ ToDlPoint(data.points[2]),
+ ToDlPoint(data.points[3]));
+ break;
+ case SkPath::kClose_Verb:
+ builder.Close();
+ break;
+ case SkPath::kDone_Verb:
+ break;
+ }
+ } while (verb != SkPath::Verb::kDone_Verb);
+
+ FillType fill_type;
+ switch (path.getFillType()) {
+ case SkPathFillType::kWinding:
+ fill_type = FillType::kNonZero;
+ break;
+ case SkPathFillType::kEvenOdd:
+ fill_type = FillType::kOdd;
+ break;
+ case SkPathFillType::kInverseWinding:
+ case SkPathFillType::kInverseEvenOdd:
+ // Flutter doesn't expose these path fill types. These are only visible
+ // via the receiver interface. We should never get here.
+ fill_type = FillType::kNonZero;
+ break;
+ }
+ builder.SetConvexity(path.isConvex() ? Convexity::kConvex
+ : Convexity::kUnknown);
+ builder.Shift(shift);
+ auto sk_bounds = path.getBounds().makeOutset(shift.x, shift.y);
+ builder.SetBounds(ToDlRect(sk_bounds));
+ return builder.TakePath(fill_type);
+}
+
+} // namespace flutter
diff --git a/display_list/geometry/dl_path.h b/display_list/geometry/dl_path.h
new file mode 100644
index 0000000..21f6006
--- /dev/null
+++ b/display_list/geometry/dl_path.h
@@ -0,0 +1,51 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef FLUTTER_DISPLAY_LIST_GEOMETRY_DL_PATH_H_
+#define FLUTTER_DISPLAY_LIST_GEOMETRY_DL_PATH_H_
+
+#include "flutter/display_list/geometry/dl_geometry_types.h"
+#include "flutter/impeller/geometry/path.h"
+#include "flutter/third_party/skia/include/core/SkPath.h"
+
+namespace flutter {
+
+class DlPath {
+ public:
+ DlPath() = default;
+ explicit DlPath(const SkPath& path) : sk_path_(path) {}
+
+ DlPath(const DlPath& path) = default;
+ DlPath(DlPath&& path) = default;
+
+ const SkPath& GetSkPath() const;
+ impeller::Path GetPath() const;
+
+ bool IsInverseFillType() const;
+
+ bool IsRect(DlRect* rect, bool* is_closed = nullptr) const;
+ bool IsOval(DlRect* bounds) const;
+
+ bool IsSkRect(SkRect* rect, bool* is_closed = nullptr) const;
+ bool IsSkOval(SkRect* bounds) const;
+ bool IsSkRRect(SkRRect* rrect) const;
+
+ SkRect GetSkBounds() const;
+ DlRect GetBounds() const;
+
+ bool operator==(const DlPath& other) const;
+
+ bool IsConverted() const;
+
+ private:
+ const SkPath sk_path_;
+ mutable impeller::Path path_;
+
+ static impeller::Path ConvertToImpellerPath(const SkPath& path,
+ const DlPoint& shift = DlPoint());
+};
+
+} // namespace flutter
+
+#endif // FLUTTER_DISPLAY_LIST_GEOMETRY_DL_PATH_H_
diff --git a/display_list/geometry/dl_path_unittests.cc b/display_list/geometry/dl_path_unittests.cc
new file mode 100644
index 0000000..f0d42be
--- /dev/null
+++ b/display_list/geometry/dl_path_unittests.cc
@@ -0,0 +1,308 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "flutter/display_list/geometry/dl_path.h"
+#include "gtest/gtest.h"
+
+#include "flutter/third_party/skia/include/core/SkRRect.h"
+
+namespace flutter {
+namespace testing {
+
+TEST(DisplayListPath, DefaultConstruction) {
+ DlPath path;
+
+ EXPECT_EQ(path, DlPath());
+ EXPECT_EQ(path.GetSkPath(), SkPath());
+
+ EXPECT_FALSE(path.IsInverseFillType());
+ // Empty/default paths are always "pre-converted" by default.
+ EXPECT_TRUE(path.IsConverted());
+
+ bool is_closed = false;
+ EXPECT_FALSE(path.IsRect(nullptr));
+ EXPECT_FALSE(path.IsRect(nullptr, &is_closed));
+ EXPECT_FALSE(is_closed);
+ EXPECT_FALSE(path.IsOval(nullptr));
+
+ is_closed = false;
+ EXPECT_FALSE(path.IsSkRect(nullptr));
+ EXPECT_FALSE(path.IsSkRect(nullptr, &is_closed));
+ EXPECT_FALSE(is_closed);
+ EXPECT_FALSE(path.IsSkOval(nullptr));
+ EXPECT_FALSE(path.IsSkRRect(nullptr));
+
+ EXPECT_EQ(path.GetBounds(), DlRect());
+ EXPECT_EQ(path.GetSkBounds(), SkRect());
+}
+
+TEST(DisplayListPath, ConstructFromEmpty) {
+ SkPath sk_path;
+ DlPath path(sk_path);
+
+ EXPECT_EQ(path, DlPath());
+ EXPECT_EQ(path.GetSkPath(), SkPath());
+
+ EXPECT_FALSE(path.IsInverseFillType());
+ // Empty/default paths are always "pre-converted" by default.
+ EXPECT_TRUE(path.IsConverted());
+
+ bool is_closed = false;
+ EXPECT_FALSE(path.IsRect(nullptr));
+ EXPECT_FALSE(path.IsRect(nullptr, &is_closed));
+ EXPECT_FALSE(is_closed);
+ EXPECT_FALSE(path.IsOval(nullptr));
+
+ is_closed = false;
+ EXPECT_FALSE(path.IsSkRect(nullptr));
+ EXPECT_FALSE(path.IsSkRect(nullptr, &is_closed));
+ EXPECT_FALSE(is_closed);
+ EXPECT_FALSE(path.IsSkOval(nullptr));
+ EXPECT_FALSE(path.IsSkRRect(nullptr));
+
+ EXPECT_EQ(path.GetBounds(), DlRect());
+ EXPECT_EQ(path.GetSkBounds(), SkRect());
+}
+
+TEST(DisplayListPath, CopyConstruct) {
+ SkPath sk_path = SkPath::Oval(SkRect::MakeLTRB(10, 10, 20, 20));
+ DlPath path1(sk_path);
+ DlPath path2 = DlPath(path1);
+
+ EXPECT_EQ(path2, path1);
+ EXPECT_EQ(path2, DlPath(SkPath::Oval(SkRect::MakeLTRB(10, 10, 20, 20))));
+ EXPECT_EQ(path2.GetSkPath(), SkPath::Oval(SkRect::MakeLTRB(10, 10, 20, 20)));
+
+ EXPECT_FALSE(path2.IsInverseFillType());
+ EXPECT_FALSE(path2.IsConverted());
+
+ bool is_closed = false;
+ EXPECT_FALSE(path2.IsRect(nullptr));
+ EXPECT_FALSE(path2.IsRect(nullptr, &is_closed));
+ EXPECT_FALSE(is_closed);
+ EXPECT_TRUE(path2.IsOval(nullptr));
+
+ is_closed = false;
+ EXPECT_FALSE(path2.IsSkRect(nullptr));
+ EXPECT_FALSE(path2.IsSkRect(nullptr, &is_closed));
+ EXPECT_FALSE(is_closed);
+ EXPECT_TRUE(path2.IsSkOval(nullptr));
+ EXPECT_FALSE(path2.IsSkRRect(nullptr));
+
+ EXPECT_EQ(path2.GetBounds(), DlRect::MakeLTRB(10, 10, 20, 20));
+ EXPECT_EQ(path2.GetSkBounds(), SkRect::MakeLTRB(10, 10, 20, 20));
+}
+
+TEST(DisplayListPath, EmbeddingSharedReference) {
+ SkPath sk_path = SkPath::Oval(SkRect::MakeLTRB(10, 10, 20, 20));
+ DlPath path(sk_path);
+
+ class ConversionSharingTester {
+ public:
+ explicit ConversionSharingTester(const DlPath& path) : path_(path) {}
+
+ bool ConvertAndTestEmpty() { return path_.GetPath().IsEmpty(); }
+
+ bool Test(const DlPath& reference_path, const std::string& label) {
+ EXPECT_EQ(path_, reference_path) << label;
+ EXPECT_EQ(path_, DlPath(SkPath::Oval(SkRect::MakeLTRB(10, 10, 20, 20))))
+ << label;
+ EXPECT_EQ(path_.GetSkPath(),
+ SkPath::Oval(SkRect::MakeLTRB(10, 10, 20, 20)))
+ << label;
+
+ EXPECT_FALSE(path_.IsInverseFillType()) << label;
+
+ bool is_closed = false;
+ EXPECT_FALSE(path_.IsRect(nullptr)) << label;
+ EXPECT_FALSE(path_.IsRect(nullptr, &is_closed)) << label;
+ EXPECT_FALSE(is_closed) << label;
+ EXPECT_TRUE(path_.IsOval(nullptr)) << label;
+
+ is_closed = false;
+ EXPECT_FALSE(path_.IsSkRect(nullptr)) << label;
+ EXPECT_FALSE(path_.IsSkRect(nullptr, &is_closed)) << label;
+ EXPECT_FALSE(is_closed) << label;
+ EXPECT_TRUE(path_.IsSkOval(nullptr)) << label;
+ EXPECT_FALSE(path_.IsSkRRect(nullptr)) << label;
+
+ EXPECT_EQ(path_.GetBounds(), DlRect::MakeLTRB(10, 10, 20, 20)) << label;
+ EXPECT_EQ(path_.GetSkBounds(), SkRect::MakeLTRB(10, 10, 20, 20)) << label;
+ return path_.IsConverted();
+ };
+
+ private:
+ const DlPath path_;
+ };
+
+ EXPECT_FALSE(path.IsConverted());
+ ConversionSharingTester before_tester(path);
+ EXPECT_FALSE(before_tester.Test(path, "Before triggering conversion"));
+ EXPECT_FALSE(path.GetPath().IsEmpty());
+ EXPECT_FALSE(before_tester.Test(path, "After conversion of source object"));
+ EXPECT_FALSE(before_tester.ConvertAndTestEmpty());
+ EXPECT_TRUE(before_tester.Test(path, "After conversion of captured object"));
+
+ EXPECT_TRUE(path.IsConverted());
+ ConversionSharingTester after_tester(path);
+ EXPECT_TRUE(after_tester.Test(path, "Constructed after conversion"));
+}
+
+TEST(DisplayListPath, ConstructFromRect) {
+ SkPath sk_path = SkPath::Rect(SkRect::MakeLTRB(10, 10, 20, 20));
+ DlPath path(sk_path);
+
+ EXPECT_EQ(path, DlPath(SkPath::Rect(SkRect::MakeLTRB(10, 10, 20, 20))));
+ EXPECT_EQ(path.GetSkPath(), SkPath::Rect(SkRect::MakeLTRB(10, 10, 20, 20)));
+
+ EXPECT_FALSE(path.IsInverseFillType());
+ EXPECT_FALSE(path.IsConverted());
+ EXPECT_FALSE(path.GetPath().IsEmpty());
+ EXPECT_TRUE(path.IsConverted());
+
+ bool is_closed = false;
+ EXPECT_TRUE(path.IsRect(nullptr));
+ DlRect dl_rect;
+ EXPECT_TRUE(path.IsRect(&dl_rect, &is_closed));
+ EXPECT_EQ(dl_rect, DlRect::MakeLTRB(10, 10, 20, 20));
+ EXPECT_TRUE(is_closed);
+ EXPECT_FALSE(path.IsOval(nullptr));
+
+ is_closed = false;
+ EXPECT_TRUE(path.IsSkRect(nullptr));
+ SkRect sk_rect;
+ EXPECT_TRUE(path.IsSkRect(&sk_rect, &is_closed));
+ EXPECT_EQ(sk_rect, SkRect::MakeLTRB(10, 10, 20, 20));
+ EXPECT_TRUE(is_closed);
+ EXPECT_FALSE(path.IsSkOval(nullptr));
+ EXPECT_FALSE(path.IsSkRRect(nullptr));
+
+ EXPECT_EQ(path.GetBounds(), DlRect::MakeLTRB(10, 10, 20, 20));
+ EXPECT_EQ(path.GetSkBounds(), SkRect::MakeLTRB(10, 10, 20, 20));
+}
+
+TEST(DisplayListPath, ConstructFromOval) {
+ SkPath sk_path = SkPath::Oval(SkRect::MakeLTRB(10, 10, 20, 20));
+ DlPath path(sk_path);
+
+ EXPECT_EQ(path, DlPath(SkPath::Oval(SkRect::MakeLTRB(10, 10, 20, 20))));
+ EXPECT_EQ(path.GetSkPath(), SkPath::Oval(SkRect::MakeLTRB(10, 10, 20, 20)));
+
+ EXPECT_FALSE(path.IsInverseFillType());
+ EXPECT_FALSE(path.IsConverted());
+ EXPECT_FALSE(path.GetPath().IsEmpty());
+ EXPECT_TRUE(path.IsConverted());
+
+ EXPECT_FALSE(path.IsRect(nullptr));
+ EXPECT_TRUE(path.IsOval(nullptr));
+ DlRect dl_bounds;
+ EXPECT_TRUE(path.IsOval(&dl_bounds));
+ EXPECT_EQ(dl_bounds, DlRect::MakeLTRB(10, 10, 20, 20));
+
+ EXPECT_FALSE(path.IsSkRect(nullptr));
+ EXPECT_TRUE(path.IsSkOval(nullptr));
+ SkRect sk_bounds;
+ EXPECT_TRUE(path.IsSkOval(&sk_bounds));
+ EXPECT_EQ(sk_bounds, SkRect::MakeLTRB(10, 10, 20, 20));
+ EXPECT_FALSE(path.IsSkRRect(nullptr));
+
+ EXPECT_EQ(path.GetBounds(), DlRect::MakeLTRB(10, 10, 20, 20));
+ EXPECT_EQ(path.GetSkBounds(), SkRect::MakeLTRB(10, 10, 20, 20));
+}
+
+TEST(DisplayListPath, ConstructFromRRect) {
+ SkPath sk_path = SkPath::RRect(SkRect::MakeLTRB(10, 10, 20, 20), 1, 2);
+ DlPath path(sk_path);
+
+ EXPECT_EQ(path,
+ DlPath(SkPath::RRect(SkRect::MakeLTRB(10, 10, 20, 20), 1, 2)));
+ EXPECT_EQ(path.GetSkPath(),
+ SkPath::RRect(SkRect::MakeLTRB(10, 10, 20, 20), 1, 2));
+
+ EXPECT_FALSE(path.IsInverseFillType());
+ EXPECT_FALSE(path.IsConverted());
+ EXPECT_FALSE(path.GetPath().IsEmpty());
+ EXPECT_TRUE(path.IsConverted());
+
+ EXPECT_FALSE(path.IsRect(nullptr));
+ EXPECT_FALSE(path.IsOval(nullptr));
+
+ EXPECT_FALSE(path.IsSkRect(nullptr));
+ EXPECT_FALSE(path.IsSkOval(nullptr));
+ EXPECT_TRUE(path.IsSkRRect(nullptr));
+ SkRRect rrect2;
+ EXPECT_TRUE(path.IsSkRRect(&rrect2));
+ EXPECT_EQ(rrect2,
+ SkRRect::MakeRectXY(SkRect::MakeLTRB(10, 10, 20, 20), 1, 2));
+
+ EXPECT_EQ(path.GetBounds(), DlRect::MakeLTRB(10, 10, 20, 20));
+ EXPECT_EQ(path.GetSkBounds(), SkRect::MakeLTRB(10, 10, 20, 20));
+}
+
+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);
+ DlPath path(sk_path1);
+
+ ASSERT_EQ(sk_path1, sk_path2);
+
+ EXPECT_EQ(path, DlPath(sk_path2));
+ EXPECT_EQ(path.GetSkPath(), sk_path2);
+
+ EXPECT_FALSE(path.IsInverseFillType());
+ EXPECT_FALSE(path.IsConverted());
+ EXPECT_FALSE(path.GetPath().IsEmpty());
+ EXPECT_TRUE(path.IsConverted());
+
+ EXPECT_FALSE(path.IsRect(nullptr));
+ EXPECT_FALSE(path.IsOval(nullptr));
+ EXPECT_FALSE(path.IsSkRect(nullptr));
+ EXPECT_FALSE(path.IsSkOval(nullptr));
+ EXPECT_FALSE(path.IsSkRRect(nullptr));
+
+ EXPECT_EQ(path.GetBounds(), DlRect::MakeLTRB(10, 10, 20, 20));
+ EXPECT_EQ(path.GetSkBounds(), SkRect::MakeLTRB(10, 10, 20, 20));
+}
+
+TEST(DisplayListPath, ConstructFromInversePath) {
+ SkPath sk_path1;
+ sk_path1.moveTo(10, 10);
+ sk_path1.lineTo(20, 20);
+ sk_path1.lineTo(20, 10);
+ sk_path1.setFillType(SkPathFillType::kInverseWinding);
+ SkPath sk_path2;
+ sk_path2.moveTo(10, 10);
+ sk_path2.lineTo(20, 20);
+ sk_path2.lineTo(20, 10);
+ sk_path2.setFillType(SkPathFillType::kInverseWinding);
+ DlPath path(sk_path1);
+
+ ASSERT_EQ(sk_path1, sk_path2);
+
+ EXPECT_EQ(path, DlPath(sk_path2));
+ EXPECT_EQ(path.GetSkPath(), sk_path2);
+
+ EXPECT_TRUE(path.IsInverseFillType());
+ EXPECT_FALSE(path.IsConverted());
+ EXPECT_FALSE(path.GetPath().IsEmpty());
+ EXPECT_TRUE(path.IsConverted());
+
+ EXPECT_FALSE(path.IsRect(nullptr));
+ EXPECT_FALSE(path.IsOval(nullptr));
+ EXPECT_FALSE(path.IsSkRect(nullptr));
+ EXPECT_FALSE(path.IsSkOval(nullptr));
+ EXPECT_FALSE(path.IsSkRRect(nullptr));
+
+ EXPECT_EQ(path.GetBounds(), DlRect::MakeLTRB(10, 10, 20, 20));
+ EXPECT_EQ(path.GetSkBounds(), SkRect::MakeLTRB(10, 10, 20, 20));
+}
+
+} // namespace testing
+} // namespace flutter
diff --git a/display_list/skia/dl_sk_dispatcher.cc b/display_list/skia/dl_sk_dispatcher.cc
index c4edaad..8a47d88 100644
--- a/display_list/skia/dl_sk_dispatcher.cc
+++ b/display_list/skia/dl_sk_dispatcher.cc
@@ -133,10 +133,10 @@
bool is_aa) {
canvas_->clipRRect(rrect, ToSk(clip_op), is_aa);
}
-void DlSkCanvasDispatcher::clipPath(const SkPath& path,
+void DlSkCanvasDispatcher::clipPath(const DlPath& path,
ClipOp clip_op,
bool is_aa) {
- canvas_->clipPath(path, ToSk(clip_op), is_aa);
+ canvas_->clipPath(path.GetSkPath(), ToSk(clip_op), is_aa);
}
void DlSkCanvasDispatcher::drawPaint() {
@@ -184,8 +184,8 @@
const SkRRect& inner) {
canvas_->drawDRRect(outer, inner, paint());
}
-void DlSkCanvasDispatcher::drawPath(const SkPath& path) {
- canvas_->drawPath(path, paint());
+void DlSkCanvasDispatcher::drawPath(const DlPath& path) {
+ canvas_->drawPath(path.GetSkPath(), paint());
}
void DlSkCanvasDispatcher::drawArc(const DlRect& bounds,
DlScalar start,
@@ -328,12 +328,13 @@
ambient_color, spot_color, flags);
}
-void DlSkCanvasDispatcher::drawShadow(const SkPath& path,
+void DlSkCanvasDispatcher::drawShadow(const DlPath& path,
const DlColor color,
const DlScalar elevation,
bool transparent_occluder,
DlScalar dpr) {
- DrawShadow(canvas_, path, color, elevation, transparent_occluder, dpr);
+ DrawShadow(canvas_, path.GetSkPath(), color, elevation, transparent_occluder,
+ dpr);
}
} // namespace flutter
diff --git a/display_list/skia/dl_sk_dispatcher.h b/display_list/skia/dl_sk_dispatcher.h
index 918bfb4..fa5fbdd 100644
--- a/display_list/skia/dl_sk_dispatcher.h
+++ b/display_list/skia/dl_sk_dispatcher.h
@@ -53,7 +53,7 @@
void clipRect(const DlRect& rect, ClipOp clip_op, bool is_aa) override;
void clipOval(const DlRect& bounds, ClipOp clip_op, bool is_aa) override;
void clipRRect(const SkRRect& rrect, ClipOp clip_op, bool is_aa) override;
- void clipPath(const SkPath& path, ClipOp clip_op, bool is_aa) override;
+ void clipPath(const DlPath& path, ClipOp clip_op, bool is_aa) override;
void drawPaint() override;
void drawColor(DlColor color, DlBlendMode mode) override;
@@ -67,7 +67,7 @@
void drawCircle(const DlPoint& center, DlScalar radius) override;
void drawRRect(const SkRRect& rrect) override;
void drawDRRect(const SkRRect& outer, const SkRRect& inner) override;
- void drawPath(const SkPath& path) override;
+ void drawPath(const DlPath& path) override;
void drawArc(const DlRect& bounds,
DlScalar start,
DlScalar sweep,
@@ -107,7 +107,7 @@
void drawTextFrame(const std::shared_ptr<impeller::TextFrame>& text_frame,
DlScalar x,
DlScalar y) override;
- void drawShadow(const SkPath& path,
+ void drawShadow(const DlPath& path,
const DlColor color,
const DlScalar elevation,
bool transparent_occluder,
diff --git a/display_list/testing/dl_test_snippets.h b/display_list/testing/dl_test_snippets.h
index 2647a6b..1057990 100644
--- a/display_list/testing/dl_test_snippets.h
+++ b/display_list/testing/dl_test_snippets.h
@@ -182,15 +182,15 @@
static const SkRRect kTestRRectRect = SkRRect::MakeRect(kTestSkBounds);
static const SkRRect kTestInnerRRect =
SkRRect::MakeRectXY(kTestSkBounds.makeInset(5, 5), 2, 2);
-static const SkPath kTestPathRect = SkPath::Rect(kTestSkBounds);
-static const SkPath kTestPathOval = SkPath::Oval(kTestSkBounds);
-static const SkPath kTestPathRRect = SkPath::RRect(kTestRRect);
-static const SkPath kTestPath1 =
- SkPath::Polygon({{0, 0}, {10, 10}, {10, 0}, {0, 10}}, true);
-static const SkPath kTestPath2 =
- SkPath::Polygon({{0, 0}, {10, 10}, {0, 10}, {10, 0}}, true);
-static const SkPath kTestPath3 =
- SkPath::Polygon({{0, 0}, {10, 10}, {10, 0}, {0, 10}}, false);
+static const DlPath kTestPathRect = DlPath(SkPath::Rect(kTestSkBounds));
+static const DlPath kTestPathOval = DlPath(SkPath::Oval(kTestSkBounds));
+static const DlPath kTestPathRRect = DlPath(SkPath::RRect(kTestRRect));
+static const DlPath kTestPath1 =
+ DlPath(SkPath::Polygon({{0, 0}, {10, 10}, {10, 0}, {0, 10}}, true));
+static const DlPath kTestPath2 =
+ DlPath(SkPath::Polygon({{0, 0}, {10, 10}, {0, 10}, {10, 0}}, true));
+static const DlPath kTestPath3 =
+ DlPath(SkPath::Polygon({{0, 0}, {10, 10}, {10, 0}, {0, 10}}, false));
static const SkMatrix kTestMatrix1 = SkMatrix::Scale(2, 2);
static const SkMatrix kTestMatrix2 = SkMatrix::RotateDeg(45);
diff --git a/display_list/utils/dl_receiver_utils.h b/display_list/utils/dl_receiver_utils.h
index 397e401..257d276 100644
--- a/display_list/utils/dl_receiver_utils.h
+++ b/display_list/utils/dl_receiver_utils.h
@@ -50,7 +50,7 @@
void clipRRect(const SkRRect& rrect,
DlCanvas::ClipOp clip_op,
bool is_aa) override {}
- void clipPath(const SkPath& path,
+ void clipPath(const DlPath& path,
DlCanvas::ClipOp clip_op,
bool is_aa) override {}
};
@@ -96,7 +96,7 @@
void drawCircle(const DlPoint& center, DlScalar radius) override {}
void drawRRect(const SkRRect& rrect) override {}
void drawDRRect(const SkRRect& outer, const SkRRect& inner) override {}
- void drawPath(const SkPath& path) override {}
+ void drawPath(const DlPath& path) override {}
void drawArc(const DlRect& oval_bounds,
DlScalar start_degrees,
DlScalar sweep_degrees,
@@ -138,7 +138,7 @@
void drawTextFrame(const std::shared_ptr<impeller::TextFrame>& text_frame,
DlScalar x,
DlScalar y) override {}
- void drawShadow(const SkPath& path,
+ void drawShadow(const DlPath& path,
const DlColor color,
const DlScalar elevation,
bool transparent_occluder,
diff --git a/impeller/display_list/dl_dispatcher.cc b/impeller/display_list/dl_dispatcher.cc
index 37c3daf..75a6c11 100644
--- a/impeller/display_list/dl_dispatcher.cc
+++ b/impeller/display_list/dl_dispatcher.cc
@@ -880,38 +880,24 @@
}
// |flutter::DlOpReceiver|
-void DlDispatcherBase::clipPath(const SkPath& path, ClipOp sk_op, bool is_aa) {
- UNIMPLEMENTED;
-}
-
-const Path& DlDispatcherBase::GetOrCachePath(const CacheablePath& cache) {
- if (cache.cached_impeller_path.IsEmpty() && !cache.sk_path.isEmpty()) {
- cache.cached_impeller_path = skia_conversions::ToPath(cache.sk_path);
- }
- return cache.cached_impeller_path;
-}
-
-// |flutter::DlOpReceiver|
-void DlDispatcherBase::clipPath(const CacheablePath& cache,
- ClipOp sk_op,
- bool is_aa) {
+void DlDispatcherBase::clipPath(const DlPath& path, ClipOp sk_op, bool is_aa) {
AUTO_DEPTH_WATCHER(0u);
auto clip_op = ToClipOperation(sk_op);
- SkRect rect;
- if (cache.sk_path.isRect(&rect)) {
- GetCanvas().ClipRect(skia_conversions::ToRect(rect), clip_op);
- } else if (cache.sk_path.isOval(&rect)) {
- GetCanvas().ClipOval(skia_conversions::ToRect(rect), clip_op);
+ DlRect rect;
+ if (path.IsRect(&rect)) {
+ GetCanvas().ClipRect(rect, clip_op);
+ } else if (path.IsOval(&rect)) {
+ GetCanvas().ClipOval(rect, clip_op);
} else {
SkRRect rrect;
- if (cache.sk_path.isRRect(&rrect) && rrect.isSimple()) {
+ if (path.IsSkRRect(&rrect) && rrect.isSimple()) {
GetCanvas().ClipRRect(skia_conversions::ToRect(rrect.rect()),
skia_conversions::ToSize(rrect.getSimpleRadii()),
clip_op);
} else {
- GetCanvas().ClipPath(GetOrCachePath(cache), clip_op);
+ GetCanvas().ClipPath(path.GetPath(), clip_op);
}
}
}
@@ -1027,43 +1013,37 @@
}
// |flutter::DlOpReceiver|
-void DlDispatcherBase::drawPath(const SkPath& path) {
- UNIMPLEMENTED;
-}
-
-// |flutter::DlOpReceiver|
-void DlDispatcherBase::drawPath(const CacheablePath& cache) {
+void DlDispatcherBase::drawPath(const DlPath& path) {
AUTO_DEPTH_WATCHER(1u);
- SimplifyOrDrawPath(GetCanvas(), cache, paint_);
+ SimplifyOrDrawPath(GetCanvas(), path, paint_);
}
void DlDispatcherBase::SimplifyOrDrawPath(Canvas& canvas,
- const CacheablePath& cache,
+ const DlPath& path,
const Paint& paint) {
- SkRect rect;
+ DlRect rect;
// We can't "optimize" a path into a rectangle if it's open.
bool closed;
- if (cache.sk_path.isRect(&rect, &closed) && closed) {
- canvas.DrawRect(skia_conversions::ToRect(rect), paint);
+ if (path.IsRect(&rect, &closed) && closed) {
+ canvas.DrawRect(rect, paint);
return;
}
SkRRect rrect;
- if (cache.sk_path.isRRect(&rrect) && rrect.isSimple()) {
+ if (path.IsSkRRect(&rrect) && rrect.isSimple()) {
canvas.DrawRRect(skia_conversions::ToRect(rrect.rect()),
skia_conversions::ToSize(rrect.getSimpleRadii()), paint);
return;
}
- SkRect oval;
- if (cache.sk_path.isOval(&oval)) {
- canvas.DrawOval(skia_conversions::ToRect(oval), paint);
+ if (path.IsOval(&rect)) {
+ canvas.DrawOval(rect, paint);
return;
}
- canvas.DrawPath(GetOrCachePath(cache), paint);
+ canvas.DrawPath(path.GetPath(), paint);
}
// |flutter::DlOpReceiver|
@@ -1299,16 +1279,7 @@
}
// |flutter::DlOpReceiver|
-void DlDispatcherBase::drawShadow(const SkPath& path,
- const flutter::DlColor color,
- const DlScalar elevation,
- bool transparent_occluder,
- DlScalar dpr) {
- UNIMPLEMENTED;
-}
-
-// |flutter::DlOpReceiver|
-void DlDispatcherBase::drawShadow(const CacheablePath& cache,
+void DlDispatcherBase::drawShadow(const DlPath& path,
const flutter::DlColor color,
const DlScalar elevation,
bool transparent_occluder,
@@ -1363,7 +1334,7 @@
GetCanvas().PreConcat(
Matrix::MakeTranslation(Vector2(0, -occluder_z * light_position.y)));
- SimplifyOrDrawPath(GetCanvas(), cache, paint);
+ SimplifyOrDrawPath(GetCanvas(), path, paint);
AUTO_DEPTH_CHECK();
GetCanvas().Restore();
diff --git a/impeller/display_list/dl_dispatcher.h b/impeller/display_list/dl_dispatcher.h
index d8e4bad..4bda272 100644
--- a/impeller/display_list/dl_dispatcher.h
+++ b/impeller/display_list/dl_dispatcher.h
@@ -7,6 +7,7 @@
#include "flutter/display_list/dl_op_receiver.h"
#include "flutter/display_list/geometry/dl_geometry_types.h"
+#include "flutter/display_list/geometry/dl_path.h"
#include "flutter/display_list/utils/dl_receiver_utils.h"
#include "fml/logging.h"
#include "impeller/aiks/canvas.h"
@@ -21,15 +22,13 @@
using DlPoint = flutter::DlPoint;
using DlRect = flutter::DlRect;
using DlIRect = flutter::DlIRect;
+using DlPath = flutter::DlPath;
class DlDispatcherBase : public flutter::DlOpReceiver {
public:
Picture EndRecordingAsPicture();
// |flutter::DlOpReceiver|
- bool PrefersImpellerPaths() const override { return true; }
-
- // |flutter::DlOpReceiver|
void setAntiAlias(bool aa) override;
// |flutter::DlOpReceiver|
@@ -132,12 +131,7 @@
void clipRRect(const SkRRect& rrect, ClipOp clip_op, bool is_aa) override;
// |flutter::DlOpReceiver|
- void clipPath(const SkPath& path, ClipOp clip_op, bool is_aa) override;
-
- // |flutter::DlOpReceiver|
- void clipPath(const CacheablePath& cache,
- ClipOp clip_op,
- bool is_aa) override;
+ void clipPath(const DlPath& path, ClipOp clip_op, bool is_aa) override;
// |flutter::DlOpReceiver|
void drawColor(flutter::DlColor color, flutter::DlBlendMode mode) override;
@@ -170,10 +164,7 @@
void drawDRRect(const SkRRect& outer, const SkRRect& inner) override;
// |flutter::DlOpReceiver|
- void drawPath(const SkPath& path) override;
-
- // |flutter::DlOpReceiver|
- void drawPath(const CacheablePath& cache) override;
+ void drawPath(const DlPath& path) override;
// |flutter::DlOpReceiver|
void drawArc(const DlRect& oval_bounds,
@@ -237,14 +228,7 @@
DlScalar y) override;
// |flutter::DlOpReceiver|
- void drawShadow(const SkPath& path,
- const flutter::DlColor color,
- const DlScalar elevation,
- bool transparent_occluder,
- DlScalar dpr) override;
-
- // |flutter::DlOpReceiver|
- void drawShadow(const CacheablePath& cache,
+ void drawShadow(const DlPath& path,
const flutter::DlColor color,
const DlScalar elevation,
bool transparent_occluder,
@@ -256,10 +240,8 @@
Paint paint_;
Matrix initial_matrix_;
- static const Path& GetOrCachePath(const CacheablePath& cache);
-
static void SimplifyOrDrawPath(Canvas& canvas,
- const CacheablePath& cache,
+ const DlPath& cache,
const Paint& paint);
};
diff --git a/impeller/display_list/skia_conversions.cc b/impeller/display_list/skia_conversions.cc
index 5457f67..911814f 100644
--- a/impeller/display_list/skia_conversions.cc
+++ b/impeller/display_list/skia_conversions.cc
@@ -87,89 +87,6 @@
return radii;
}
-Path ToPath(const SkPath& path, Point shift) {
- auto iterator = SkPath::Iter(path, false);
-
- struct PathData {
- union {
- SkPoint points[4];
- };
- };
-
- PathBuilder builder;
- PathData data;
- // Reserve a path size with some arbitrarily additional padding.
- builder.Reserve(path.countPoints() + 8, path.countVerbs() + 8);
- auto verb = SkPath::Verb::kDone_Verb;
- do {
- verb = iterator.next(data.points);
- switch (verb) {
- case SkPath::kMove_Verb:
- builder.MoveTo(ToPoint(data.points[0]));
- break;
- case SkPath::kLine_Verb:
- builder.LineTo(ToPoint(data.points[1]));
- break;
- case SkPath::kQuad_Verb:
- builder.QuadraticCurveTo(ToPoint(data.points[1]),
- ToPoint(data.points[2]));
- break;
- case SkPath::kConic_Verb: {
- constexpr auto kPow2 = 1; // Only works for sweeps up to 90 degrees.
- constexpr auto kQuadCount = 1 + (2 * (1 << kPow2));
- SkPoint points[kQuadCount];
- const auto curve_count =
- SkPath::ConvertConicToQuads(data.points[0], //
- data.points[1], //
- data.points[2], //
- iterator.conicWeight(), //
- points, //
- kPow2 //
- );
-
- for (int curve_index = 0, point_index = 0; //
- curve_index < curve_count; //
- curve_index++, point_index += 2 //
- ) {
- builder.QuadraticCurveTo(ToPoint(points[point_index + 1]),
- ToPoint(points[point_index + 2]));
- }
- } break;
- case SkPath::kCubic_Verb:
- builder.CubicCurveTo(ToPoint(data.points[1]), ToPoint(data.points[2]),
- ToPoint(data.points[3]));
- break;
- case SkPath::kClose_Verb:
- builder.Close();
- break;
- case SkPath::kDone_Verb:
- break;
- }
- } while (verb != SkPath::Verb::kDone_Verb);
-
- FillType fill_type;
- switch (path.getFillType()) {
- case SkPathFillType::kWinding:
- fill_type = FillType::kNonZero;
- break;
- case SkPathFillType::kEvenOdd:
- fill_type = FillType::kOdd;
- break;
- case SkPathFillType::kInverseWinding:
- case SkPathFillType::kInverseEvenOdd:
- // Flutter doesn't expose these path fill types. These are only visible
- // via the receiver interface. We should never get here.
- fill_type = FillType::kNonZero;
- break;
- }
- builder.SetConvexity(path.isConvex() ? Convexity::kConvex
- : Convexity::kUnknown);
- builder.Shift(shift);
- auto sk_bounds = path.getBounds().makeOutset(shift.x, shift.y);
- builder.SetBounds(ToRect(sk_bounds));
- return builder.TakePath(fill_type);
-}
-
Path ToPath(const SkRRect& rrect) {
return PathBuilder{}
.AddRoundedRect(ToRect(rrect.getBounds()), ToRoundingRadii(rrect))
@@ -214,14 +131,6 @@
return result;
}
-Path PathDataFromTextBlob(const sk_sp<SkTextBlob>& blob, Point shift) {
- if (!blob) {
- return {};
- }
-
- return ToPath(skia::textlayout::Paragraph::GetPath(blob.get()), shift);
-}
-
std::optional<impeller::PixelFormat> ToPixelFormat(SkColorType type) {
switch (type) {
case kRGBA_8888_SkColorType:
diff --git a/impeller/display_list/skia_conversions.h b/impeller/display_list/skia_conversions.h
index edc9aec..fa0c9f6 100644
--- a/impeller/display_list/skia_conversions.h
+++ b/impeller/display_list/skia_conversions.h
@@ -52,13 +52,8 @@
PathBuilder::RoundingRadii ToRoundingRadii(const SkRRect& rrect);
-Path ToPath(const SkPath& path, Point shift = Point(0, 0));
-
Path ToPath(const SkRRect& rrect);
-Path PathDataFromTextBlob(const sk_sp<SkTextBlob>& blob,
- Point shift = Point(0, 0));
-
std::optional<impeller::PixelFormat> ToPixelFormat(SkColorType type);
/// @brief Convert display list colors + stops into impeller colors and stops,
diff --git a/shell/common/dl_op_spy.cc b/shell/common/dl_op_spy.cc
index b386344..19f54d1 100644
--- a/shell/common/dl_op_spy.cc
+++ b/shell/common/dl_op_spy.cc
@@ -65,7 +65,7 @@
void DlOpSpy::drawDRRect(const SkRRect& outer, const SkRRect& inner) {
did_draw_ |= will_draw_;
}
-void DlOpSpy::drawPath(const SkPath& path) {
+void DlOpSpy::drawPath(const DlPath& path) {
did_draw_ |= will_draw_;
}
void DlOpSpy::drawArc(const DlRect& oval_bounds,
@@ -142,7 +142,7 @@
did_draw_ |= will_draw_;
}
-void DlOpSpy::drawShadow(const SkPath& path,
+void DlOpSpy::drawShadow(const DlPath& path,
const DlColor color,
const DlScalar elevation,
bool transparent_occluder,
diff --git a/shell/common/dl_op_spy.h b/shell/common/dl_op_spy.h
index f51297c..6d3d9c9 100644
--- a/shell/common/dl_op_spy.h
+++ b/shell/common/dl_op_spy.h
@@ -55,7 +55,7 @@
void drawCircle(const DlPoint& center, DlScalar radius) override;
void drawRRect(const SkRRect& rrect) override;
void drawDRRect(const SkRRect& outer, const SkRRect& inner) override;
- void drawPath(const SkPath& path) override;
+ void drawPath(const DlPath& path) override;
void drawArc(const DlRect& oval_bounds,
DlScalar start_degrees,
DlScalar sweep_degrees,
@@ -98,7 +98,7 @@
void drawTextFrame(const std::shared_ptr<impeller::TextFrame>& text_frame,
DlScalar x,
DlScalar y) override;
- void drawShadow(const SkPath& path,
+ void drawShadow(const DlPath& path,
const DlColor color,
const DlScalar elevation,
bool transparent_occluder,
diff --git a/testing/display_list_testing.cc b/testing/display_list_testing.cc
index dc0205b..5ef1601 100644
--- a/testing/display_list_testing.cc
+++ b/testing/display_list_testing.cc
@@ -57,6 +57,7 @@
using SaveLayerOptions = flutter::SaveLayerOptions;
using DisplayListOpType = flutter::DisplayListOpType;
using DisplayListOpCategory = flutter::DisplayListOpCategory;
+using DlPath = flutter::DlPath;
using DisplayListStreamDispatcher = flutter::testing::DisplayListStreamDispatcher;
@@ -218,9 +219,9 @@
<< ")";
}
-static std::ostream& operator<<(std::ostream& os, const SkPath& path) {
- return os << "SkPath("
- << "bounds: " << path.getBounds()
+extern std::ostream& operator<<(std::ostream& os, const DlPath& path) {
+ return os << "DlPath("
+ << "bounds: " << path.GetSkBounds()
// should iterate over verbs and coordinates...
<< ")";
}
@@ -813,7 +814,7 @@
<< "isaa: " << is_aa
<< ");" << std::endl;
}
-void DisplayListStreamDispatcher::clipPath(const SkPath& path, ClipOp clip_op,
+void DisplayListStreamDispatcher::clipPath(const DlPath& path, ClipOp clip_op,
bool is_aa) {
startl() << "clipPath("
<< path << ", "
@@ -864,7 +865,7 @@
startl() << "drawDRRect(outer: " << outer << ", " << std::endl;
startl() << " inner: " << inner << ");" << std::endl;
}
-void DisplayListStreamDispatcher::drawPath(const SkPath& path) {
+void DisplayListStreamDispatcher::drawPath(const DlPath& path) {
startl() << "drawPath(" << path << ");" << std::endl;
}
void DisplayListStreamDispatcher::drawArc(const DlRect& oval_bounds,
@@ -974,7 +975,7 @@
<< x << ", " << y << ");" << std::endl;
}
-void DisplayListStreamDispatcher::drawShadow(const SkPath& path,
+void DisplayListStreamDispatcher::drawShadow(const DlPath& path,
const DlColor color,
const DlScalar elevation,
bool transparent_occluder,
diff --git a/testing/display_list_testing.h b/testing/display_list_testing.h
index dbc1c67..3172203 100644
--- a/testing/display_list_testing.h
+++ b/testing/display_list_testing.h
@@ -79,6 +79,7 @@
const flutter::DisplayListOpType& type);
extern std::ostream& operator<<(std::ostream& os,
const flutter::DisplayListOpCategory& category);
+extern std::ostream& operator<<(std::ostream& os, const flutter::DlPath& path);
} // namespace std
@@ -130,7 +131,7 @@
void clipRect(const DlRect& rect, ClipOp clip_op, bool is_aa) override;
void clipOval(const DlRect& bounds, ClipOp clip_op, bool is_aa) override;
void clipRRect(const SkRRect& rrect, ClipOp clip_op, bool is_aa) override;
- void clipPath(const SkPath& path, ClipOp clip_op, bool is_aa) override;
+ void clipPath(const DlPath& path, ClipOp clip_op, bool is_aa) override;
void drawColor(DlColor color, DlBlendMode mode) override;
void drawPaint() override;
@@ -144,7 +145,7 @@
void drawCircle(const DlPoint& center, DlScalar radius) override;
void drawRRect(const SkRRect& rrect) override;
void drawDRRect(const SkRRect& outer, const SkRRect& inner) override;
- void drawPath(const SkPath& path) override;
+ void drawPath(const DlPath& path) override;
void drawArc(const DlRect& oval_bounds,
DlScalar start_degrees,
DlScalar sweep_degrees,
@@ -186,7 +187,7 @@
void drawTextFrame(const std::shared_ptr<impeller::TextFrame>& text_frame,
DlScalar x,
DlScalar y) override;
- void drawShadow(const SkPath& path,
+ void drawShadow(const DlPath& path,
const DlColor color,
const DlScalar elevation,
bool transparent_occluder,
@@ -385,7 +386,7 @@
break;
}
}
- void clipPath(const SkPath& path,
+ void clipPath(const DlPath& path,
DlCanvas::ClipOp clip_op,
bool is_aa) override {
switch (clip_op) {
@@ -438,7 +439,7 @@
void drawDRRect(const SkRRect& outer, const SkRRect& inner) override {
RecordByType(DisplayListOpType::kDrawDRRect);
}
- void drawPath(const SkPath& path) override {
+ void drawPath(const DlPath& path) override {
RecordByType(DisplayListOpType::kDrawPath);
}
void drawArc(const DlRect& oval_bounds,
@@ -524,7 +525,7 @@
DlScalar y) override {
RecordByType(DisplayListOpType::kDrawTextFrame);
}
- void drawShadow(const SkPath& path,
+ void drawShadow(const DlPath& path,
const DlColor color,
const DlScalar elevation,
bool transparent_occluder,
diff --git a/third_party/txt/tests/paragraph_unittests.cc b/third_party/txt/tests/paragraph_unittests.cc
index a02899b..66ce7f2 100644
--- a/third_party/txt/tests/paragraph_unittests.cc
+++ b/third_party/txt/tests/paragraph_unittests.cc
@@ -75,14 +75,14 @@
void drawRect(const DlRect& rect) override { rects_.push_back(rect); }
- void drawPath(const SkPath& path) override { paths_.push_back(path); }
+ void drawPath(const DlPath& path) override { paths_.push_back(path); }
std::vector<std::shared_ptr<impeller::TextFrame>> text_frames_;
std::vector<sk_sp<SkTextBlob>> blobs_;
std::vector<std::pair<DlPoint, DlPoint>> lines_;
std::vector<std::tuple<DlPoint, DlPoint, DlPoint>> dashed_lines_;
std::vector<DlRect> rects_;
- std::vector<SkPath> paths_;
+ std::vector<DlPath> paths_;
};
template <typename T>