From a7c8b309cd31a8495ff2aa1d920374b502132ce5 Mon Sep 17 00:00:00 2001 From: JsouLiang Date: Tue, 22 Mar 2022 00:13:09 +0800 Subject: [PATCH 01/17] Define the DlPathEffect Object --- display_list/display_list_path_effect.cc | 23 ++++ display_list/display_list_path_effect.h | 145 +++++++++++++++++++++++ 2 files changed, 168 insertions(+) create mode 100644 display_list/display_list_path_effect.cc create mode 100644 display_list/display_list_path_effect.h diff --git a/display_list/display_list_path_effect.cc b/display_list/display_list_path_effect.cc new file mode 100644 index 0000000000000..d515c69a2e2db --- /dev/null +++ b/display_list/display_list_path_effect.cc @@ -0,0 +1,23 @@ +// 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/display_list_path_effect.h" +#include +#include "include/core/SkRefCnt.h" + +namespace flutter { + +std::shared_ptr DlPathEffect::MakeSum( + std::shared_ptr first, + std::shared_ptr second) { + return std::make_shared(first, second); +} + +std::shared_ptr DlPathEffect::MakeCompose( + std::shared_ptr outer, + std::shared_ptr inner) { + return std::make_shared(outer, inner); +} + +} // namespace flutter diff --git a/display_list/display_list_path_effect.h b/display_list/display_list_path_effect.h new file mode 100644 index 0000000000000..ff1d1d6c2fb0e --- /dev/null +++ b/display_list/display_list_path_effect.h @@ -0,0 +1,145 @@ +// 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_DISPLAY_LIST_PATH_EFFECT_H_ +#define FLUTTER_DISPLAY_LIST_DISPLAY_LIST_PATH_EFFECT_H_ + +#include +#include +#include +#include "flutter/display_list/display_list_attributes.h" +#include "flutter/display_list/types.h" +#include "flutter/fml/logging.h" +#include "include/core/SkRefCnt.h" + +namespace flutter { + +class DlComposePathEffect; +class DlSumPathEffect; + +enum class DlPathEffectType { kSumPathEffect, kComposePathEffect }; + +class DlPathEffect + : public DlAttribute { + public: + static std::shared_ptr From(SkPathEffect* sk_path_effect); + + static std::shared_ptr From( + sk_sp sk_path_effect) { + return From(sk_path_effect.get()); + } + + static std::shared_ptr MakeSum( + std::shared_ptr first, + std::shared_ptr second); + + static std::shared_ptr MakeCompose( + std::shared_ptr outer, + std::shared_ptr inner); + + virtual DlSumPathEffect* asSum() const { return nullptr; } + + virtual DlComposePathEffect* asCompose() const { return nullptr; } +}; + +class DlPairPathEffect : public DlPathEffect { + protected: + DlPairPathEffect(sk_sp pe0, sk_sp pe1) + : fPE0(std::move(pe0)), fPE1(std::move(pe1)) {} + + sk_sp fPE0; + sk_sp fPE1; +}; + +class DlComposePathEffect final : public DlPairPathEffect { + public: + DlComposePathEffect(sk_sp first, sk_sp second) + : DlPairPathEffect(first, second) {} + + DlComposePathEffect(const DlComposePathEffect& path_effect) + : DlComposePathEffect(path_effect.fPE0, path_effect.fPE1) {} + DlComposePathEffect(const DlComposePathEffect* path_effect) + : DlComposePathEffect(path_effect->fPE0, path_effect->fPE1) {} + + static std::shared_ptr Make(sk_sp outer, + sk_sp inner) { + if (!outer) { + return From(inner); + } + if (!inner) { + return From(outer); + } + return std::make_shared(outer, inner); + } + + DlPathEffectType type() const override { + return DlPathEffectType::kComposePathEffect; + } + size_t size() const override { return sizeof(*this); } + + std::shared_ptr shared() const override { + return std::make_shared(this); + } + + const DlComposePathEffect* asCompose() const override { return this; } + + sk_sp skia_object() const override { + return SkPathEffect::MakeCompose(fPE0, fPE1); + } + + protected: + bool equals_(DlPathEffect const& other) const override { + FML_DCHECK(other.type() == DlPathEffectType::kComposePathEffect); + auto that = static_cast(&other); + return fPE0 == that->fPE0 && fPE1 == that->fPE1; + } +}; + +class DlSumPathEffect final : public DlPairPathEffect { + public: + DlSumPathEffect(sk_sp first, sk_sp second) + : DlPairPathEffect(first, second) {} + + DlSumPathEffect(const DlSumPathEffect& path_effect) + : DlSumPathEffect(path_effect.fPE0, path_effect.fPE1) {} + DlSumPathEffect(const DlSumPathEffect* path_effect) + : DlSumPathEffect(path_effect->fPE0, path_effect->fPE1) {} + + static std::shared_ptr Make(sk_sp first, + sk_sp second) { + if (!first) { + return From(second); + } + if (!second) { + return From(first); + } + return std::make_shared(first, second); + } + + DlPathEffectType type() const override { + return DlPathEffectType::kSumPathEffect; + } + size_t size() const override { return sizeof(*this); } + + std::shared_ptr shared() const override { + return std::make_shared(this); + } + + sk_sp skia_object() const override { + return SkPathEffect::MakeSum(fPE0, fPE1); + } + + const DlSumPathEffect* asSum() const override { return this; } + + protected: + bool equals_(DlPathEffect const& other) const override { + FML_DCHECK(other.type() == DlPathEffectType::kSumPathEffect); + auto that = static_cast(&other); + return fPE0 == that->fPE0 && fPE1 == that->fPE1; + } +}; + +} // namespace flutter + +#endif // FLUTTER_DISPLAY_LIST_DISPLAY_LIST_PATH_EFFECT_H_ From 9ae187694b9cd2b2daf86f23aaaf675443820036 Mon Sep 17 00:00:00 2001 From: JsouLiang Date: Tue, 22 Mar 2022 11:47:19 +0800 Subject: [PATCH 02/17] Complete the DlPathEffect Object --- display_list/BUILD.gn | 2 + display_list/display_list_builder.cc | 50 ++++- display_list/display_list_builder.h | 13 +- display_list/display_list_canvas_unittests.cc | 44 +++-- display_list/display_list_complexity_helper.h | 2 +- display_list/display_list_dispatcher.h | 3 +- display_list/display_list_ops.h | 3 +- display_list/display_list_path_effect.cc | 16 +- display_list/display_list_path_effect.h | 183 +++++++++++++++++- display_list/display_list_unittests.cc | 17 +- display_list/display_list_utils.cc | 15 +- display_list/display_list_utils.h | 9 +- display_list/types.h | 4 +- 13 files changed, 305 insertions(+), 56 deletions(-) diff --git a/display_list/BUILD.gn b/display_list/BUILD.gn index 1f919a9ec4971..d08d69dcdd0a9 100644 --- a/display_list/BUILD.gn +++ b/display_list/BUILD.gn @@ -46,6 +46,8 @@ source_set("display_list") { "display_list_ops.h", "display_list_paint.cc", "display_list_paint.h", + "display_list_path_effect.cc", + "display_list_path_effect.h", "display_list_tile_mode.h", "display_list_utils.cc", "display_list_utils.h", diff --git a/display_list/display_list_builder.cc b/display_list/display_list_builder.cc index 10331d98f24bb..fd4cc53fcb937 100644 --- a/display_list/display_list_builder.cc +++ b/display_list/display_list_builder.cc @@ -275,10 +275,49 @@ void DisplayListBuilder::onSetColorFilter(const DlColorFilter* filter) { } UpdateCurrentOpacityCompatibility(); } -void DisplayListBuilder::onSetPathEffect(sk_sp effect) { - (current_path_effect_ = effect) // - ? Push(0, 0, std::move(effect)) - : Push(0, 0); +void DisplayListBuilder::onSetPathEffect(const DlPathEffect* effect) { + if (effect == nullptr) { + current_path_effect_ = nullptr; + Push(0, 0); + } else { + current_path_effect_ = effect->shared(); + switch (current_path_effect_->type()) { + case DlPathEffectType::kCorner: { + const DlCornerPathEffect* corner_effect = effect->asCorner(); + void* pod = Push(corner_effect->size(), 0); + new (pod) DlCornerPathEffect(corner_effect); + break; + } + case DlPathEffectType::kDash: { + const DlDashPathEffect* dash_effect = effect->asDash(); + void* pod = Push(dash_effect->size(), 0); + new (pod) DlDashPathEffect(dash_effect); + break; + } + case DlPathEffectType::kDiscrete: { + const DlDiscretePathEffect* discrete_effect = effect->asDiscrete(); + void* pod = Push(discrete_effect->size(), 0); + new (pod) DlDiscretePathEffect(discrete_effect); + break; + } + case DlPathEffectType::kSumPathEffect: { + const DlSumPathEffect* sum_effect = effect->asSum(); + void* pod = Push(sum_effect->size(), 0); + new (pod) DlSumPathEffect(sum_effect); + break; + } + case DlPathEffectType::kComposePathEffect: { + const DlComposePathEffect* compose_effect = effect->asCompose(); + void* pod = Push(compose_effect->size(), 0); + new (pod) DlComposePathEffect(compose_effect); + break; + } + case DlPathEffectType::kUnknown: { + Push(0, 0, effect->skia_object()); + break; + } + } + } } void DisplayListBuilder::onSetMaskFilter(const DlMaskFilter* filter) { if (filter == nullptr) { @@ -389,7 +428,8 @@ void DisplayListBuilder::setAttributesFromPaint( setImageFilter(DlImageFilter::From(paint.getImageFilter()).get()); } if (flags.applies_path_effect()) { - setPathEffect(sk_ref_sp(paint.getPathEffect())); + SkPathEffect* path_effect = paint.getPathEffect(); + setPathEffect(DlPathEffect::From(path_effect).get()); } if (flags.applies_mask_filter()) { SkMaskFilter* mask_filter = paint.getMaskFilter(); diff --git a/display_list/display_list_builder.h b/display_list/display_list_builder.h index 6bdc3dc913e66..34110c8ce93ed 100644 --- a/display_list/display_list_builder.h +++ b/display_list/display_list_builder.h @@ -5,6 +5,7 @@ #ifndef FLUTTER_DISPLAY_LIST_DISPLAY_LIST_BUILDER_H_ #define FLUTTER_DISPLAY_LIST_DISPLAY_LIST_BUILDER_H_ +#include #include "flutter/display_list/display_list.h" #include "flutter/display_list/display_list_blend_mode.h" #include "flutter/display_list/display_list_comparable.h" @@ -102,9 +103,9 @@ class DisplayListBuilder final : public virtual Dispatcher, onSetColorFilter(filter); } } - void setPathEffect(sk_sp effect) override { - if (current_path_effect_ != effect) { - onSetPathEffect(std::move(effect)); + void setPathEffect(const DlPathEffect* effect) override { + if (NotEquals(current_path_effect_, effect)) { + onSetPathEffect(effect); } } void setMaskFilter(const DlMaskFilter* filter) override { @@ -139,7 +140,9 @@ class DisplayListBuilder final : public virtual Dispatcher, return current_blender_ ? current_blender_ : SkBlender::Mode(ToSk(current_.getBlendMode())); } - sk_sp getPathEffect() const { return current_path_effect_; } + std::shared_ptr getPathEffect() const { + return current_path_effect_; + } std::shared_ptr getMaskFilter() const { return current_.getMaskFilter(); } @@ -453,7 +456,7 @@ class DisplayListBuilder final : public virtual Dispatcher, void onSetColorSource(const DlColorSource* source); void onSetImageFilter(const DlImageFilter* filter); void onSetColorFilter(const DlColorFilter* filter); - void onSetPathEffect(sk_sp effect); + void onSetPathEffect(const DlPathEffect* effect); void onSetMaskFilter(const DlMaskFilter* filter); void onSetMaskBlurFilter(SkBlurStyle style, SkScalar sigma); diff --git a/display_list/display_list_canvas_unittests.cc b/display_list/display_list_canvas_unittests.cc index 4ac2cb018c7d0..891beb77c6587 100644 --- a/display_list/display_list_canvas_unittests.cc +++ b/display_list/display_list_canvas_unittests.cc @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include #include "flutter/display_list/display_list.h" #include "flutter/display_list/display_list_canvas_dispatcher.h" #include "flutter/display_list/display_list_canvas_recorder.h" @@ -387,13 +388,13 @@ class TestParameters { NotEquals(ref_attr.getColorSource(), attr.getColorSource())) { return false; } + auto skia_path_effect = attr.getPathEffect()->skia_object(); DisplayListSpecialGeometryFlags geo_flags = - flags_.WithPathEffect(attr.getPathEffect()); + flags_.WithPathEffect(skia_path_effect); if (flags_.applies_path_effect() && // ref_attr.getPathEffect() != attr.getPathEffect()) { SkPathEffect::DashInfo info; - if (attr.getPathEffect()->asADash(&info) != - SkPathEffect::kDash_DashType) { + if (skia_path_effect->asADash(&info) != SkPathEffect::kDash_DashType) { return false; } if (!ignores_dashes()) { @@ -1230,7 +1231,9 @@ class CanvasCompareTester { } { - sk_sp effect = SkDiscretePathEffect::Make(3, 5); + std::shared_ptr effect = + DlDiscretePathEffect::Make(3, 5); + auto skia_effect = effect->skia_object(); { // Discrete path effects need a stroke width for drawPointsAsPoints // to do something realistic @@ -1249,17 +1252,18 @@ class CanvasCompareTester { [=](SkCanvas*, SkPaint& p) { p.setStrokeWidth(5.0); p.setStrokeMiter(3.0); - p.setPathEffect(effect); + p.setPathEffect(skia_effect); }, [=](DisplayListBuilder& b) { b.setStrokeWidth(5.0); b.setStrokeMiter(3.0); - b.setPathEffect(effect); + b.setPathEffect(effect.get()); })); } - EXPECT_TRUE(testP.is_draw_text_blob() || effect->unique()) + EXPECT_TRUE(testP.is_draw_text_blob() || skia_effect->unique()) << "PathEffect == Discrete-3-5 Cleanup"; - effect = SkDiscretePathEffect::Make(2, 3); + effect = DlDiscretePathEffect::Make(2, 3); + skia_effect = effect->skia_object(); { // Discrete path effects need a stroke width for drawPointsAsPoints // to do something realistic @@ -1278,15 +1282,15 @@ class CanvasCompareTester { [=](SkCanvas*, SkPaint& p) { p.setStrokeWidth(5.0); p.setStrokeMiter(2.5); - p.setPathEffect(effect); + p.setPathEffect(skia_effect); }, [=](DisplayListBuilder& b) { b.setStrokeWidth(5.0); b.setStrokeMiter(2.5); - b.setPathEffect(effect); + b.setPathEffect(effect.get()); })); } - EXPECT_TRUE(testP.is_draw_text_blob() || effect->unique()) + EXPECT_TRUE(testP.is_draw_text_blob() || skia_effect->unique()) << "PathEffect == Discrete-2-3 Cleanup"; } @@ -1503,7 +1507,8 @@ class CanvasCompareTester { { const SkScalar TestDashes1[] = {29.0, 2.0}; const SkScalar TestDashes2[] = {17.0, 1.5}; - sk_sp effect = SkDashPathEffect::Make(TestDashes1, 2, 0.0f); + auto effect = DlDashPathEffect::Make(TestDashes1, 2, 0.0f); + auto skia_effect = effect->skia_object(); { RenderWith(testP, stroke_base_env, tolerance, CaseParameters( @@ -1513,19 +1518,20 @@ class CanvasCompareTester { p.setStyle(SkPaint::kStroke_Style); // Provide some non-trivial stroke size to get dashed p.setStrokeWidth(5.0); - p.setPathEffect(effect); + p.setPathEffect(skia_effect); }, [=](DisplayListBuilder& b) { // Need stroke style to see dashing properly b.setStyle(DlDrawStyle::kStroke); // Provide some non-trivial stroke size to get dashed b.setStrokeWidth(5.0); - b.setPathEffect(effect); + b.setPathEffect(effect.get()); })); } - EXPECT_TRUE(testP.is_draw_text_blob() || effect->unique()) + EXPECT_TRUE(testP.is_draw_text_blob() || skia_effect->unique()) << "PathEffect == Dash-29-2 Cleanup"; - effect = SkDashPathEffect::Make(TestDashes2, 2, 0.0f); + effect = DlDashPathEffect::Make(TestDashes2, 2, 0.0f); + skia_effect = effect->skia_object(); { RenderWith(testP, stroke_base_env, tolerance, CaseParameters( @@ -1535,17 +1541,17 @@ class CanvasCompareTester { p.setStyle(SkPaint::kStroke_Style); // Provide some non-trivial stroke size to get dashed p.setStrokeWidth(5.0); - p.setPathEffect(effect); + p.setPathEffect(skia_effect); }, [=](DisplayListBuilder& b) { // Need stroke style to see dashing properly b.setStyle(DlDrawStyle::kStroke); // Provide some non-trivial stroke size to get dashed b.setStrokeWidth(5.0); - b.setPathEffect(effect); + b.setPathEffect(effect.get()); })); } - EXPECT_TRUE(testP.is_draw_text_blob() || effect->unique()) + EXPECT_TRUE(testP.is_draw_text_blob() || skia_effect->unique()) << "PathEffect == Dash-17-1.5 Cleanup"; } } diff --git a/display_list/display_list_complexity_helper.h b/display_list/display_list_complexity_helper.h index efaf0e97f83ac..e17c41638beb8 100644 --- a/display_list/display_list_complexity_helper.h +++ b/display_list/display_list_complexity_helper.h @@ -112,7 +112,7 @@ class ComplexityCalculatorHelper void setColorSource(const DlColorSource* source) override {} void setImageFilter(const DlImageFilter* filter) override {} void setColorFilter(const DlColorFilter* filter) override {} - void setPathEffect(sk_sp effect) override {} + void setPathEffect(const DlPathEffect* effect) override {} void setMaskFilter(const DlMaskFilter* filter) override {} void save() override {} diff --git a/display_list/display_list_dispatcher.h b/display_list/display_list_dispatcher.h index ce2236a0f25eb..bcd950eb266f8 100644 --- a/display_list/display_list_dispatcher.h +++ b/display_list/display_list_dispatcher.h @@ -14,6 +14,7 @@ #include "flutter/display_list/display_list_mask_filter.h" #include "flutter/display_list/display_list_paint.h" #include "flutter/display_list/display_list_vertices.h" +#include "flutter/display_list/display_list_path_effect.h" namespace flutter { @@ -52,7 +53,7 @@ class Dispatcher { virtual void setInvertColors(bool invert) = 0; virtual void setBlendMode(DlBlendMode mode) = 0; virtual void setBlender(sk_sp blender) = 0; - virtual void setPathEffect(sk_sp effect) = 0; + virtual void setPathEffect(const DlPathEffect* effect) = 0; virtual void setMaskFilter(const DlMaskFilter* filter) = 0; virtual void setImageFilter(const DlImageFilter* filter) = 0; diff --git a/display_list/display_list_ops.h b/display_list/display_list_ops.h index d451accd6556f..a16436d5ac1ba 100644 --- a/display_list/display_list_ops.h +++ b/display_list/display_list_ops.h @@ -176,7 +176,7 @@ struct SetBlendModeOp final : DLOp { } \ }; DEFINE_SET_CLEAR_SKREF_OP(Blender, blender) -DEFINE_SET_CLEAR_SKREF_OP(PathEffect, effect) +DEFINE_SET_CLEAR_SKREF_OP(ImageFilter, filter) #undef DEFINE_SET_CLEAR_SKREF_OP // Clear: 4 byte header + unused 4 byte payload uses 8 bytes @@ -224,6 +224,7 @@ DEFINE_SET_CLEAR_DLATTR_OP(ColorFilter, ColorFilter, filter) DEFINE_SET_CLEAR_DLATTR_OP(ImageFilter, ImageFilter, filter) DEFINE_SET_CLEAR_DLATTR_OP(MaskFilter, MaskFilter, filter) DEFINE_SET_CLEAR_DLATTR_OP(ColorSource, Shader, source) +DEFINE_SET_CLEAR_DLATTR_OP(PathEffect, PathEffect, effect) #undef DEFINE_SET_CLEAR_DLATTR_OP // 4 byte header + 80 bytes for the embedded DlImageColorSource diff --git a/display_list/display_list_path_effect.cc b/display_list/display_list_path_effect.cc index d515c69a2e2db..1e11c89e1b878 100644 --- a/display_list/display_list_path_effect.cc +++ b/display_list/display_list_path_effect.cc @@ -8,16 +8,28 @@ namespace flutter { +std::shared_ptr DlPathEffect::From(SkPathEffect* sk_path_effect) { + if (sk_path_effect == nullptr) { + return nullptr; + } + // There are no inspection methods for SkPathEffect so we cannot break + // the Skia filter down into a specific subclass (i.e. DlSumPathEffect or + // DlComposePathEffect). + return std::make_shared(sk_ref_sp(sk_path_effect)); +} + std::shared_ptr DlPathEffect::MakeSum( std::shared_ptr first, std::shared_ptr second) { - return std::make_shared(first, second); + return std::make_shared(first->skia_object(), + second->skia_object()); } std::shared_ptr DlPathEffect::MakeCompose( std::shared_ptr outer, std::shared_ptr inner) { - return std::make_shared(outer, inner); + return std::make_shared(outer->skia_object(), + inner->skia_object()); } } // namespace flutter diff --git a/display_list/display_list_path_effect.h b/display_list/display_list_path_effect.h index ff1d1d6c2fb0e..40774581debec 100644 --- a/display_list/display_list_path_effect.h +++ b/display_list/display_list_path_effect.h @@ -11,14 +11,23 @@ #include "flutter/display_list/display_list_attributes.h" #include "flutter/display_list/types.h" #include "flutter/fml/logging.h" -#include "include/core/SkRefCnt.h" namespace flutter { class DlComposePathEffect; class DlSumPathEffect; +class DlCornerPathEffect; +class DlDashPathEffect; +class DlDiscretePathEffect; -enum class DlPathEffectType { kSumPathEffect, kComposePathEffect }; +enum class DlPathEffectType { + kCorner, + kDash, + kDiscrete, + kSumPathEffect, + kComposePathEffect, + kUnknown +}; class DlPathEffect : public DlAttribute { @@ -38,9 +47,175 @@ class DlPathEffect std::shared_ptr outer, std::shared_ptr inner); - virtual DlSumPathEffect* asSum() const { return nullptr; } + virtual const DlCornerPathEffect* asCorner() const { return nullptr; } + + virtual const DlDashPathEffect* asDash() const { return nullptr; } + + virtual const DlDiscretePathEffect* asDiscrete() const { return nullptr; } + + virtual const DlSumPathEffect* asSum() const { return nullptr; } + virtual const DlComposePathEffect* asCompose() const { return nullptr; } +}; + +class DlCornerPathEffect : public DlPathEffect { + public: + DlCornerPathEffect(SkScalar radius) : radius_(radius) {} + + DlCornerPathEffect(const DlCornerPathEffect& corner_effect) + : DlCornerPathEffect(corner_effect.radius_) {} + DlCornerPathEffect(const DlCornerPathEffect* corner_effect) + : DlCornerPathEffect(corner_effect->radius_) {} + + static std::shared_ptr Make(SkScalar radius) { + return std::make_shared(radius); + } + + DlPathEffectType type() const override { return DlPathEffectType::kCorner; } + size_t size() const override { return sizeof(*this); } + + std::shared_ptr shared() const override { + return std::make_shared(this); + } + + const DlCornerPathEffect* asCorner() const override { return this; } + + sk_sp skia_object() const override { + return SkCornerPathEffect::Make(radius_); + } + + protected: + bool equals_(DlPathEffect const& other) const override { + FML_DCHECK(other.type() == DlPathEffectType::kCorner); + auto that = static_cast(&other); + return radius_ == that->radius_; + } + + SkScalar radius_; +}; + +class DlDashPathEffect : public DlPathEffect { + public: + DlDashPathEffect(const SkScalar intervals[], int count, SkScalar phase) + : intervals_(intervals), count_(count), phase_(phase) {} + + DlDashPathEffect(const DlDashPathEffect& dash_effect) + : DlDashPathEffect(dash_effect.intervals_, + dash_effect.count_, + dash_effect.phase_) {} + DlDashPathEffect(const DlDashPathEffect* dash_effect) + : DlDashPathEffect(dash_effect->intervals_, + dash_effect->count_, + dash_effect->phase_) {} + + static std::shared_ptr Make(const SkScalar intervals[], + int count, + SkScalar phase) { + return std::make_shared(intervals, count, phase); + } + + DlPathEffectType type() const override { return DlPathEffectType::kDash; } + size_t size() const override { return sizeof(*this); } + + std::shared_ptr shared() const override { + return std::make_shared(this); + } + + const DlDashPathEffect* asDash() const override { return this; } + + sk_sp skia_object() const override { + return SkDashPathEffect::Make(intervals_, count_, phase_); + } + + protected: + bool equals_(DlPathEffect const& other) const override { + FML_DCHECK(other.type() == DlPathEffectType::kCorner); + auto that = static_cast(&other); + return intervals_ == that->intervals_ && count_ == that->count_ && + phase_ == that->phase_; + } + + const SkScalar* intervals_; + int count_; + SkScalar phase_; +}; + +class DlUnknownPathEffect final : public DlPathEffect { + public: + DlUnknownPathEffect(sk_sp effect) + : sk_path_effect_(std::move(effect)) {} + DlUnknownPathEffect(const DlUnknownPathEffect& effect) + : DlUnknownPathEffect(effect.sk_path_effect_) {} + DlUnknownPathEffect(const DlUnknownPathEffect* effect) + : DlUnknownPathEffect(effect->sk_path_effect_) {} + + DlPathEffectType type() const override { return DlPathEffectType::kUnknown; } + size_t size() const override { return sizeof(*this); } + + std::shared_ptr shared() const override { + return std::make_shared(this); + } + + sk_sp skia_object() const override { return sk_path_effect_; } + + virtual ~DlUnknownPathEffect() = default; + + protected: + bool equals_(const DlPathEffect& other) const override { + FML_DCHECK(other.type() == DlPathEffectType::kUnknown); + auto that = static_cast(&other); + return sk_path_effect_ == that->sk_path_effect_; + } + + private: + sk_sp sk_path_effect_; +}; + +class DlDiscretePathEffect : public DlPathEffect { + public: + DlDiscretePathEffect(SkScalar segLength, + SkScalar dev, + uint32_t seedAssist = 0) + : segLength_(segLength), dev_(dev), seedAssist_(seedAssist) {} + + DlDiscretePathEffect(const DlDiscretePathEffect& discrete_effect) + : DlDiscretePathEffect(discrete_effect.segLength_, + discrete_effect.dev_, + discrete_effect.seedAssist_) {} + DlDiscretePathEffect(const DlDiscretePathEffect* discrete_effect) + : DlDiscretePathEffect(discrete_effect->segLength_, + discrete_effect->dev_, + discrete_effect->seedAssist_) {} + + DlPathEffectType type() const override { return DlPathEffectType::kDiscrete; } + size_t size() const override { return sizeof(*this); } + + static std::shared_ptr Make(SkScalar segLength, + SkScalar dev, + uint32_t seedAssist = 0) { + return std::make_shared(segLength, dev, seedAssist); + } + + std::shared_ptr shared() const override { + return std::make_shared(this); + } + + const DlDiscretePathEffect* asDiscrete() const override { return this; } + + sk_sp skia_object() const override { + return SkDiscretePathEffect::Make(segLength_, dev_, seedAssist_); + } + + protected: + bool equals_(DlPathEffect const& other) const override { + FML_DCHECK(other.type() == DlPathEffectType::kDiscrete); + auto that = static_cast(&other); + return segLength_ == that->segLength_ && dev_ == that->dev_ && + seedAssist_ == that->seedAssist_; + } - virtual DlComposePathEffect* asCompose() const { return nullptr; } + SkScalar segLength_; + SkScalar dev_; + uint32_t seedAssist_ = 0; }; class DlPairPathEffect : public DlPathEffect { diff --git a/display_list/display_list_unittests.cc b/display_list/display_list_unittests.cc index 23f4156594f01..e6550ecdd67b6 100644 --- a/display_list/display_list_unittests.cc +++ b/display_list/display_list_unittests.cc @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include #include "flutter/display_list/display_list.h" #include "flutter/display_list/display_list_builder.h" #include "flutter/display_list/display_list_canvas_recorder.h" @@ -427,8 +428,8 @@ std::vector allGroups = { } }, { "SetPathEffect", { - {0, 16, 0, 0, [](DisplayListBuilder& b) {b.setPathEffect(TestPathEffect1);}}, - {0, 16, 0, 0, [](DisplayListBuilder& b) {b.setPathEffect(TestPathEffect2);}}, + {0, 16, 0, 0, [](DisplayListBuilder& b) {b.setPathEffect(TestPathEffect1.get());}}, + {0, 16, 0, 0, [](DisplayListBuilder& b) {b.setPathEffect(TestPathEffect2.get());}}, {0, 0, 0, 0, [](DisplayListBuilder& b) {b.setPathEffect(nullptr);}}, } }, @@ -1337,16 +1338,18 @@ TEST(DisplayList, DisplayListPathEffectRefHandling) { class PathEffectRefTester : public virtual AttributeRefTester { public: void setRefToPaint(SkPaint& paint) const override { - paint.setPathEffect(path_effect); + paint.setPathEffect(path_effect->skia_object()); } void setRefToDisplayList(DisplayListBuilder& builder) const override { - builder.setPathEffect(path_effect); + builder.setPathEffect(path_effect.get()); + } + bool ref_is_unique() const override { + return path_effect->skia_object()->unique(); } - bool ref_is_unique() const override { return path_effect->unique(); } private: - sk_sp path_effect = - SkDashPathEffect::Make(TestDashes1, 2, 0.0); + std::shared_ptr path_effect = + DlDashPathEffect::Make(TestDashes1, 2, 0.0); }; PathEffectRefTester tester; diff --git a/display_list/display_list_utils.cc b/display_list/display_list_utils.cc index 123465df8c6ad..769538fed9d05 100644 --- a/display_list/display_list_utils.cc +++ b/display_list/display_list_utils.cc @@ -5,12 +5,14 @@ #include "flutter/display_list/display_list_utils.h" #include +#include #include #include #include "flutter/display_list/display_list_blend_mode.h" #include "flutter/display_list/display_list_canvas_dispatcher.h" #include "flutter/fml/logging.h" +#include "include/core/SkRefCnt.h" #include "third_party/skia/include/core/SkMaskFilter.h" #include "third_party/skia/include/core/SkPath.h" #include "third_party/skia/include/core/SkRSXform.h" @@ -85,8 +87,8 @@ void SkPaintDispatchHelper::setColorFilter(const DlColorFilter* filter) { color_filter_ = filter ? filter->shared() : nullptr; paint_.setColorFilter(makeColorFilter()); } -void SkPaintDispatchHelper::setPathEffect(sk_sp effect) { - paint_.setPathEffect(effect); +void SkPaintDispatchHelper::setPathEffect(const DlPathEffect* effect) { + paint_.setPathEffect(effect ? effect->skia_object() : nullptr); } void SkPaintDispatchHelper::setMaskFilter(const DlMaskFilter* filter) { paint_.setMaskFilter(filter ? filter->skia_object() : nullptr); @@ -277,8 +279,8 @@ void DisplayListBoundsCalculator::setImageFilter(const DlImageFilter* filter) { void DisplayListBoundsCalculator::setColorFilter(const DlColorFilter* filter) { color_filter_ = filter ? filter->shared() : nullptr; } -void DisplayListBoundsCalculator::setPathEffect(sk_sp effect) { - path_effect_ = std::move(effect); +void DisplayListBoundsCalculator::setPathEffect(const DlPathEffect* effect) { + path_effect_ = effect ? effect->shared() : nullptr; } void DisplayListBoundsCalculator::setMaskFilter(const DlMaskFilter* filter) { mask_filter_ = filter ? filter->shared() : nullptr; @@ -578,12 +580,13 @@ bool DisplayListBoundsCalculator::AdjustBoundsForPaint( } if (flags.is_geometric()) { + auto sk_path_effect = path_effect_->skia_object(); // Path effect occurs before stroking... DisplayListSpecialGeometryFlags special_flags = - flags.WithPathEffect(path_effect_); + flags.WithPathEffect(sk_path_effect); if (path_effect_) { SkPaint p; - p.setPathEffect(path_effect_); + p.setPathEffect(sk_path_effect); if (!p.canComputeFastBounds()) { return false; } diff --git a/display_list/display_list_utils.h b/display_list/display_list_utils.h index 648dff9ad42fa..6e13edb3f547f 100644 --- a/display_list/display_list_utils.h +++ b/display_list/display_list_utils.h @@ -5,6 +5,7 @@ #ifndef FLUTTER_DISPLAY_LIST_DISPLAY_LIST_UTILS_H_ #define FLUTTER_DISPLAY_LIST_DISPLAY_LIST_UTILS_H_ +#include #include #include "flutter/display_list/display_list.h" @@ -58,7 +59,7 @@ class IgnoreAttributeDispatchHelper : public virtual Dispatcher { void setColorSource(const DlColorSource* source) override {} void setImageFilter(const DlImageFilter* filter) override {} void setColorFilter(const DlColorFilter* filter) override {} - void setPathEffect(sk_sp effect) override {} + void setPathEffect(const DlPathEffect* effect) override {} void setMaskFilter(const DlMaskFilter* filter) override {} }; @@ -185,7 +186,7 @@ class SkPaintDispatchHelper : public virtual Dispatcher { void setInvertColors(bool invert) override; void setBlendMode(DlBlendMode mode) override; void setBlender(sk_sp blender) override; - void setPathEffect(sk_sp effect) override; + void setPathEffect(const DlPathEffect* effect) override; void setMaskFilter(const DlMaskFilter* filter) override; void setImageFilter(const DlImageFilter* filter) override; @@ -404,7 +405,7 @@ class DisplayListBoundsCalculator final void setBlender(sk_sp blender) override; void setImageFilter(const DlImageFilter* filter) override; void setColorFilter(const DlColorFilter* filter) override; - void setPathEffect(sk_sp effect) override; + void setPathEffect(const DlPathEffect* effect) override; void setMaskFilter(const DlMaskFilter* filter) override; void save() override; @@ -582,7 +583,7 @@ class DisplayListBoundsCalculator final bool join_is_miter_ = true; bool cap_is_square_ = false; std::shared_ptr image_filter_; - sk_sp path_effect_; + std::shared_ptr path_effect_; std::shared_ptr mask_filter_; bool paint_nops_on_transparency(); diff --git a/display_list/types.h b/display_list/types.h index e00bc96056363..6d1e06971552b 100644 --- a/display_list/types.h +++ b/display_list/types.h @@ -25,7 +25,9 @@ #include "third_party/skia/include/core/SkShader.h" #include "third_party/skia/include/core/SkTextBlob.h" #include "third_party/skia/include/core/SkVertices.h" +#include "third_party/skia/include/effects/SkCornerPathEffect.h" +#include "third_party/skia/include/effects/SkDashPathEffect.h" +#include "third_party/skia/include/effects/SkDiscretePathEffect.h" #include "third_party/skia/include/gpu/GrTypes.h" #include "third_party/skia/include/utils/SkShadowUtils.h" - #endif // FLUTTER_DISPLAY_LIST_TYPES_H_ From 360ef9bf93dfef8b14c4825a878434b0fb8480bf Mon Sep 17 00:00:00 2001 From: JsouLiang Date: Tue, 22 Mar 2022 15:28:20 +0800 Subject: [PATCH 03/17] Add DlPathEffect Unittests --- display_list/BUILD.gn | 1 + display_list/display_list.h | 3 +- display_list/display_list_builder.h | 1 - display_list/display_list_canvas_unittests.cc | 4 +- display_list/display_list_ops.h | 1 - display_list/display_list_path_effect.h | 63 +++--- .../display_list_path_effect_unittests.cc | 210 ++++++++++++++++++ display_list/display_list_unittests.cc | 34 +-- display_list/display_list_utils.cc | 4 +- display_list/display_list_utils.h | 1 - impeller/LICENSE | 25 +++ .../entity/contents/filters/filter_input.cc | 158 +++++++++++++ .../entity/contents/filters/filter_input.h | 153 +++++++++++++ 13 files changed, 587 insertions(+), 71 deletions(-) create mode 100644 display_list/display_list_path_effect_unittests.cc create mode 100644 impeller/LICENSE create mode 100644 impeller/entity/contents/filters/filter_input.cc create mode 100644 impeller/entity/contents/filters/filter_input.h diff --git a/display_list/BUILD.gn b/display_list/BUILD.gn index d08d69dcdd0a9..ea809d6d87073 100644 --- a/display_list/BUILD.gn +++ b/display_list/BUILD.gn @@ -93,6 +93,7 @@ if (enable_unittests) { "display_list_color_unittests.cc", "display_list_complexity_unittests.cc", "display_list_enum_unittests.cc", + "display_list_path_effect_unittests.cc", "display_list_image_filter_unittests.cc", "display_list_mask_filter_unittests.cc", "display_list_paint_unittests.cc", diff --git a/display_list/display_list.h b/display_list/display_list.h index 651332a375380..b61c1434edeb5 100644 --- a/display_list/display_list.h +++ b/display_list/display_list.h @@ -74,7 +74,8 @@ namespace flutter { \ V(SetBlender) \ V(ClearBlender) \ - V(SetPathEffect) \ + V(SetSkPathEffect) \ + V(SetPodPathEffect) \ V(ClearPathEffect) \ \ V(ClearColorFilter) \ diff --git a/display_list/display_list_builder.h b/display_list/display_list_builder.h index 34110c8ce93ed..0e4778b3fd6b3 100644 --- a/display_list/display_list_builder.h +++ b/display_list/display_list_builder.h @@ -5,7 +5,6 @@ #ifndef FLUTTER_DISPLAY_LIST_DISPLAY_LIST_BUILDER_H_ #define FLUTTER_DISPLAY_LIST_DISPLAY_LIST_BUILDER_H_ -#include #include "flutter/display_list/display_list.h" #include "flutter/display_list/display_list_blend_mode.h" #include "flutter/display_list/display_list_comparable.h" diff --git a/display_list/display_list_canvas_unittests.cc b/display_list/display_list_canvas_unittests.cc index 891beb77c6587..20b22c8974849 100644 --- a/display_list/display_list_canvas_unittests.cc +++ b/display_list/display_list_canvas_unittests.cc @@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include #include "flutter/display_list/display_list.h" #include "flutter/display_list/display_list_canvas_dispatcher.h" #include "flutter/display_list/display_list_canvas_recorder.h" @@ -388,7 +387,8 @@ class TestParameters { NotEquals(ref_attr.getColorSource(), attr.getColorSource())) { return false; } - auto skia_path_effect = attr.getPathEffect()->skia_object(); + auto skia_path_effect = + attr.getPathEffect() ? attr.getPathEffect()->skia_object() : nullptr; DisplayListSpecialGeometryFlags geo_flags = flags_.WithPathEffect(skia_path_effect); if (flags_.applies_path_effect() && // diff --git a/display_list/display_list_ops.h b/display_list/display_list_ops.h index a16436d5ac1ba..91893813628f5 100644 --- a/display_list/display_list_ops.h +++ b/display_list/display_list_ops.h @@ -176,7 +176,6 @@ struct SetBlendModeOp final : DLOp { } \ }; DEFINE_SET_CLEAR_SKREF_OP(Blender, blender) -DEFINE_SET_CLEAR_SKREF_OP(ImageFilter, filter) #undef DEFINE_SET_CLEAR_SKREF_OP // Clear: 4 byte header + unused 4 byte payload uses 8 bytes diff --git a/display_list/display_list_path_effect.h b/display_list/display_list_path_effect.h index 40774581debec..22748254f89ba 100644 --- a/display_list/display_list_path_effect.h +++ b/display_list/display_list_path_effect.h @@ -128,7 +128,7 @@ class DlDashPathEffect : public DlPathEffect { protected: bool equals_(DlPathEffect const& other) const override { - FML_DCHECK(other.type() == DlPathEffectType::kCorner); + FML_DCHECK(other.type() == DlPathEffectType::kDash); auto that = static_cast(&other); return intervals_ == that->intervals_ && count_ == that->count_ && phase_ == that->phase_; @@ -139,37 +139,6 @@ class DlDashPathEffect : public DlPathEffect { SkScalar phase_; }; -class DlUnknownPathEffect final : public DlPathEffect { - public: - DlUnknownPathEffect(sk_sp effect) - : sk_path_effect_(std::move(effect)) {} - DlUnknownPathEffect(const DlUnknownPathEffect& effect) - : DlUnknownPathEffect(effect.sk_path_effect_) {} - DlUnknownPathEffect(const DlUnknownPathEffect* effect) - : DlUnknownPathEffect(effect->sk_path_effect_) {} - - DlPathEffectType type() const override { return DlPathEffectType::kUnknown; } - size_t size() const override { return sizeof(*this); } - - std::shared_ptr shared() const override { - return std::make_shared(this); - } - - sk_sp skia_object() const override { return sk_path_effect_; } - - virtual ~DlUnknownPathEffect() = default; - - protected: - bool equals_(const DlPathEffect& other) const override { - FML_DCHECK(other.type() == DlPathEffectType::kUnknown); - auto that = static_cast(&other); - return sk_path_effect_ == that->sk_path_effect_; - } - - private: - sk_sp sk_path_effect_; -}; - class DlDiscretePathEffect : public DlPathEffect { public: DlDiscretePathEffect(SkScalar segLength, @@ -218,6 +187,36 @@ class DlDiscretePathEffect : public DlPathEffect { uint32_t seedAssist_ = 0; }; +class DlUnknownPathEffect final : public DlPathEffect { + public: + DlUnknownPathEffect(sk_sp effect) + : sk_path_effect_(std::move(effect)) {} + DlUnknownPathEffect(const DlUnknownPathEffect& effect) + : DlUnknownPathEffect(effect.sk_path_effect_) {} + DlUnknownPathEffect(const DlUnknownPathEffect* effect) + : DlUnknownPathEffect(effect->sk_path_effect_) {} + + DlPathEffectType type() const override { return DlPathEffectType::kUnknown; } + size_t size() const override { return sizeof(*this); } + + std::shared_ptr shared() const override { + return std::make_shared(this); + } + + sk_sp skia_object() const override { return sk_path_effect_; } + + virtual ~DlUnknownPathEffect() = default; + + protected: + bool equals_(const DlPathEffect& other) const override { + FML_DCHECK(other.type() == DlPathEffectType::kUnknown); + auto that = static_cast(&other); + return sk_path_effect_ == that->sk_path_effect_; + } + + private: + sk_sp sk_path_effect_; +}; class DlPairPathEffect : public DlPathEffect { protected: DlPairPathEffect(sk_sp pe0, sk_sp pe1) diff --git a/display_list/display_list_path_effect_unittests.cc b/display_list/display_list_path_effect_unittests.cc new file mode 100644 index 0000000000000..70c42150ad158 --- /dev/null +++ b/display_list/display_list_path_effect_unittests.cc @@ -0,0 +1,210 @@ +// 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/display_list_attributes_testing.h" +#include "flutter/display_list/display_list_builder.h" +#include "flutter/display_list/display_list_comparable.h" +#include "flutter/display_list/types.h" +#include "gtest/gtest.h" +#include "include/core/SkPath.h" + +namespace flutter { +namespace testing { + +const SkScalar TestDashes1[] = {4.0, 2.0}; +const SkScalar TestDashes2[] = {1.0, 1.5}; + +TEST(DisplayListPathEffect, BuilderSetGet) { + DlDashPathEffect dash_path_effect(TestDashes1, 2, 0.0); + DisplayListBuilder builder; + ASSERT_EQ(builder.getPathEffect(), nullptr); + builder.setPathEffect(&dash_path_effect); + ASSERT_NE(builder.getPathEffect(), nullptr); + ASSERT_TRUE(Equals(builder.getPathEffect(), + static_cast(&dash_path_effect))); + builder.setPathEffect(nullptr); + ASSERT_EQ(builder.getPathEffect(), nullptr); +} + +TEST(DisplayListPathEffect, FromSkiaNullPathEffect) { + std::shared_ptr path_effect = DlPathEffect::From(nullptr); + ASSERT_EQ(path_effect, nullptr); + ASSERT_EQ(path_effect.get(), nullptr); +} + +TEST(DisplayListPathEffect, FromSkiaPathEffect) { + sk_sp sk_path_effect = + SkDashPathEffect::Make(TestDashes2, 2, 0.0); + std::shared_ptr dl_path_effect = + DlPathEffect::From(sk_path_effect); + + ASSERT_EQ(dl_path_effect->type(), DlPathEffectType::kUnknown); + // We cannot recapture the dash parameters from an SkDashPathEffect + ASSERT_EQ(dl_path_effect->asDash(), nullptr); + ASSERT_EQ(dl_path_effect->skia_object(), sk_path_effect); +} + +TEST(DisplayListPathEffect, EffectShared) { + DlDashPathEffect effect(TestDashes2, 2, 0.0); + ASSERT_NE(effect.shared().get(), &effect); + ASSERT_EQ(*effect.shared(), effect); +} + +TEST(DisplayListPathEffect, DashEffectAsDash) { + DlDashPathEffect effect(TestDashes2, 2, 0.0); + ASSERT_NE(effect.asDash(), nullptr); + ASSERT_EQ(effect.asDash(), &effect); +} + +TEST(DisplayListPathEffect, DashEffectEquals) { + DlDashPathEffect effect1(TestDashes2, 2, 0.0); + DlDashPathEffect effect2(TestDashes2, 2, 0.0); + TestEquals(effect1, effect2); +} + +TEST(DisplayListPathEffect, BlurNotEquals) { + DlDashPathEffect effect1(TestDashes1, 2, 0.0); + DlDashPathEffect effect2(TestDashes2, 2, 0.0); + DlDashPathEffect effect3(TestDashes2, 3, 0.0); + TestNotEquals(effect1, effect2, "intervals differs"); + TestNotEquals(effect2, effect3, "phase differs"); +} + +TEST(DisplayListPathEffect, UnknownConstructor) { + DlUnknownPathEffect path_effect(SkDashPathEffect::Make(TestDashes1, 2, 0.0)); +} + +TEST(DisplayListPathEffect, UnknownShared) { + DlUnknownPathEffect path_effect(SkDashPathEffect::Make(TestDashes1, 2, 0.0)); + ASSERT_NE(path_effect.shared().get(), &path_effect); + ASSERT_EQ(*path_effect.shared(), path_effect); +} + +TEST(DisplayListPathEffect, UnknownContents) { + sk_sp sk_effect = SkDashPathEffect::Make(TestDashes1, 2, 0.0); + DlUnknownPathEffect effect(sk_effect); + ASSERT_EQ(effect.skia_object(), sk_effect); + ASSERT_EQ(effect.skia_object().get(), sk_effect.get()); +} + +TEST(DisplayListPathEffect, UnknownEquals) { + sk_sp sk_effect = SkDashPathEffect::Make(TestDashes1, 2, 0.0); + DlUnknownPathEffect effect1(sk_effect); + DlUnknownPathEffect effect2(sk_effect); + TestEquals(effect1, effect1); +} + +TEST(DisplayListPathEffect, UnknownNotEquals) { + // Even though the effect is the same, it is a different instance + // and we cannot currently tell them apart because the Skia + // DashEffect::Make objects do not implement == + DlUnknownPathEffect path_effect1(SkDashPathEffect::Make(TestDashes1, 2, 0.0)); + DlUnknownPathEffect path_effect2(SkDashPathEffect::Make(TestDashes1, 2, 0.0)); + TestNotEquals(path_effect1, path_effect2, + "SkDashPathEffect instance differs"); +} + +void testEquals(DlPathEffect* a, DlPathEffect* b) { + // a and b have the same nullness or values + ASSERT_TRUE(Equals(a, b)); + ASSERT_FALSE(NotEquals(a, b)); + ASSERT_TRUE(Equals(b, a)); + ASSERT_FALSE(NotEquals(b, a)); +} + +void testNotEquals(DlPathEffect* a, DlPathEffect* b) { + // a and b do not have the same nullness or values + ASSERT_FALSE(Equals(a, b)); + ASSERT_TRUE(NotEquals(a, b)); + ASSERT_FALSE(Equals(b, a)); + ASSERT_TRUE(NotEquals(b, a)); +} + +void testEquals(std::shared_ptr a, DlPathEffect* b) { + // a and b have the same nullness or values + ASSERT_TRUE(Equals(a, b)); + ASSERT_FALSE(NotEquals(a, b)); + ASSERT_TRUE(Equals(b, a)); + ASSERT_FALSE(NotEquals(b, a)); +} + +void testNotEquals(std::shared_ptr a, DlPathEffect* b) { + // a and b do not have the same nullness or values + ASSERT_FALSE(Equals(a, b)); + ASSERT_TRUE(NotEquals(a, b)); + ASSERT_FALSE(Equals(b, a)); + ASSERT_TRUE(NotEquals(b, a)); +} + +void testEquals(std::shared_ptr a, + std::shared_ptr b) { + // a and b have the same nullness or values + ASSERT_TRUE(Equals(a, b)); + ASSERT_FALSE(NotEquals(a, b)); + ASSERT_TRUE(Equals(b, a)); + ASSERT_FALSE(NotEquals(b, a)); +} + +void testNotEquals(std::shared_ptr a, + std::shared_ptr b) { + // a and b do not have the same nullness or values + ASSERT_FALSE(Equals(a, b)); + ASSERT_TRUE(NotEquals(a, b)); + ASSERT_FALSE(Equals(b, a)); + ASSERT_TRUE(NotEquals(b, a)); +} + +TEST(DisplayListPathEffect, ComparableTemplates) { + DlDashPathEffect effect1(TestDashes1, 2, 0.0); + DlDashPathEffect effect2(TestDashes1, 2, 0.0); + DlDashPathEffect effect3(TestDashes2, 3, 0.0); + std::shared_ptr shared_null; + + // null to null + testEquals(nullptr, nullptr); + testEquals(shared_null, nullptr); + testEquals(shared_null, shared_null); + + // ptr to null + testNotEquals(&effect1, nullptr); + testNotEquals(&effect2, nullptr); + testNotEquals(&effect3, nullptr); + + // shared_ptr to null and shared_null to ptr + testNotEquals(effect1.shared(), nullptr); + testNotEquals(effect2.shared(), nullptr); + testNotEquals(effect3.shared(), nullptr); + testNotEquals(shared_null, &effect1); + testNotEquals(shared_null, &effect2); + testNotEquals(shared_null, &effect3); + + // ptr to ptr + testEquals(&effect1, &effect1); + testEquals(&effect1, &effect2); + testEquals(&effect3, &effect3); + testEquals(&effect2, &effect2); + + // shared_ptr to ptr + testEquals(effect1.shared(), &effect1); + testEquals(effect1.shared(), &effect2); + testEquals(effect2.shared(), &effect2); + testEquals(effect3.shared(), &effect3); + testNotEquals(effect1.shared(), &effect3); + testNotEquals(effect2.shared(), &effect3); + testNotEquals(effect3.shared(), &effect1); + testNotEquals(effect3.shared(), &effect2); + + // shared_ptr to shared_ptr + testEquals(effect1.shared(), effect1.shared()); + testEquals(effect1.shared(), effect2.shared()); + testEquals(effect2.shared(), effect2.shared()); + testEquals(effect3.shared(), effect3.shared()); + testNotEquals(effect1.shared(), effect3.shared()); + testNotEquals(effect2.shared(), effect3.shared()); + testNotEquals(effect3.shared(), effect1.shared()); + testNotEquals(effect3.shared(), effect2.shared()); +} + +} // namespace testing +} // namespace flutter diff --git a/display_list/display_list_unittests.cc b/display_list/display_list_unittests.cc index e6550ecdd67b6..fcb5b98db7f92 100644 --- a/display_list/display_list_unittests.cc +++ b/display_list/display_list_unittests.cc @@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include #include "flutter/display_list/display_list.h" #include "flutter/display_list/display_list_builder.h" #include "flutter/display_list/display_list_canvas_recorder.h" @@ -174,10 +173,8 @@ static const DlComposeImageFilter TestComposeImageFilter3( TestMatrixImageFilter2); static const DlColorFilterImageFilter TestCFImageFilter1(TestBlendColorFilter1); static const DlColorFilterImageFilter TestCFImageFilter2(TestBlendColorFilter2); -static const sk_sp TestPathEffect1 = - SkDashPathEffect::Make(TestDashes1, 2, 0.0f); -static const sk_sp TestPathEffect2 = - SkDashPathEffect::Make(TestDashes2, 2, 0.0f); +static const DlDashPathEffect TestPathEffect1(TestDashes1, 2, 0.0f); +static const DlDashPathEffect TestPathEffect2(TestDashes2, 2, 0.0f); static const DlBlurMaskFilter TestMaskFilter1(kNormal_SkBlurStyle, 3.0); static const DlBlurMaskFilter TestMaskFilter2(kNormal_SkBlurStyle, 5.0); static const DlBlurMaskFilter TestMaskFilter3(kSolid_SkBlurStyle, 3.0); @@ -428,8 +425,8 @@ std::vector allGroups = { } }, { "SetPathEffect", { - {0, 16, 0, 0, [](DisplayListBuilder& b) {b.setPathEffect(TestPathEffect1.get());}}, - {0, 16, 0, 0, [](DisplayListBuilder& b) {b.setPathEffect(TestPathEffect2.get());}}, + {0, 32, 0, 0, [](DisplayListBuilder& b) {b.setPathEffect(&TestPathEffect1);}}, + {0, 32, 0, 0, [](DisplayListBuilder& b) {b.setPathEffect(&TestPathEffect2);}}, {0, 0, 0, 0, [](DisplayListBuilder& b) {b.setPathEffect(nullptr);}}, } }, @@ -1334,29 +1331,6 @@ TEST(DisplayList, DisplayListBlenderRefHandling) { ASSERT_TRUE(tester.ref_is_unique()); } -TEST(DisplayList, DisplayListPathEffectRefHandling) { - class PathEffectRefTester : public virtual AttributeRefTester { - public: - void setRefToPaint(SkPaint& paint) const override { - paint.setPathEffect(path_effect->skia_object()); - } - void setRefToDisplayList(DisplayListBuilder& builder) const override { - builder.setPathEffect(path_effect.get()); - } - bool ref_is_unique() const override { - return path_effect->skia_object()->unique(); - } - - private: - std::shared_ptr path_effect = - DlDashPathEffect::Make(TestDashes1, 2, 0.0); - }; - - PathEffectRefTester tester; - tester.test(); - ASSERT_TRUE(tester.ref_is_unique()); -} - TEST(DisplayList, DisplayListFullPerspectiveTransformHandling) { // SkM44 constructor takes row-major order SkM44 sk_matrix = SkM44( diff --git a/display_list/display_list_utils.cc b/display_list/display_list_utils.cc index 769538fed9d05..dc5c3183445c0 100644 --- a/display_list/display_list_utils.cc +++ b/display_list/display_list_utils.cc @@ -5,14 +5,12 @@ #include "flutter/display_list/display_list_utils.h" #include -#include #include #include #include "flutter/display_list/display_list_blend_mode.h" #include "flutter/display_list/display_list_canvas_dispatcher.h" #include "flutter/fml/logging.h" -#include "include/core/SkRefCnt.h" #include "third_party/skia/include/core/SkMaskFilter.h" #include "third_party/skia/include/core/SkPath.h" #include "third_party/skia/include/core/SkRSXform.h" @@ -580,7 +578,7 @@ bool DisplayListBoundsCalculator::AdjustBoundsForPaint( } if (flags.is_geometric()) { - auto sk_path_effect = path_effect_->skia_object(); + auto sk_path_effect = path_effect_ ? path_effect_->skia_object() : nullptr; // Path effect occurs before stroking... DisplayListSpecialGeometryFlags special_flags = flags.WithPathEffect(sk_path_effect); diff --git a/display_list/display_list_utils.h b/display_list/display_list_utils.h index 6e13edb3f547f..8f3dd5486be3a 100644 --- a/display_list/display_list_utils.h +++ b/display_list/display_list_utils.h @@ -5,7 +5,6 @@ #ifndef FLUTTER_DISPLAY_LIST_DISPLAY_LIST_UTILS_H_ #define FLUTTER_DISPLAY_LIST_DISPLAY_LIST_UTILS_H_ -#include #include #include "flutter/display_list/display_list.h" diff --git a/impeller/LICENSE b/impeller/LICENSE new file mode 100644 index 0000000000000..c6823b81eb845 --- /dev/null +++ b/impeller/LICENSE @@ -0,0 +1,25 @@ +Copyright 2013 The Flutter Authors. All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/impeller/entity/contents/filters/filter_input.cc b/impeller/entity/contents/filters/filter_input.cc new file mode 100644 index 0000000000000..6719886467e0c --- /dev/null +++ b/impeller/entity/contents/filters/filter_input.cc @@ -0,0 +1,158 @@ +// 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 "impeller/entity/contents/filters/filter_input.h" + +#include +#include +#include +#include +#include + +#include "fml/logging.h" +#include "impeller/entity/contents/filters/filter_contents.h" +#include "impeller/entity/contents/snapshot.h" +#include "impeller/entity/entity.h" + +namespace impeller { + +/******************************************************************************* + ******* FilterInput + ******************************************************************************/ + +FilterInput::Ref FilterInput::Make(Variant input) { + if (auto filter = std::get_if>(&input)) { + return std::static_pointer_cast( + std::shared_ptr( + new FilterContentsFilterInput(*filter))); + } + + if (auto contents = std::get_if>(&input)) { + return std::static_pointer_cast( + std::shared_ptr( + new ContentsFilterInput(*contents))); + } + + if (auto texture = std::get_if>(&input)) { + return std::static_pointer_cast( + std::shared_ptr(new TextureFilterInput(*texture))); + } + + FML_UNREACHABLE(); +} + +FilterInput::Vector FilterInput::Make(std::initializer_list inputs) { + FilterInput::Vector result; + result.reserve(inputs.size()); + for (const auto& input : inputs) { + result.push_back(Make(input)); + } + return result; +} + +Matrix FilterInput::GetLocalTransform(const Entity& entity) const { + return Matrix(); +} + +Matrix FilterInput::GetTransform(const Entity& entity) const { + return entity.GetTransformation() * GetLocalTransform(entity); +} + +FilterInput::~FilterInput() = default; + +/******************************************************************************* + ******* FilterContentsFilterInput + ******************************************************************************/ + +FilterContentsFilterInput::FilterContentsFilterInput( + std::shared_ptr filter) + : filter_(filter) {} + +FilterContentsFilterInput::~FilterContentsFilterInput() = default; + +FilterInput::Variant FilterContentsFilterInput::GetInput() const { + return filter_; +} + +std::optional FilterContentsFilterInput::GetSnapshot( + const ContentContext& renderer, + const Entity& entity) const { + if (!snapshot_.has_value()) { + snapshot_ = filter_->RenderToSnapshot(renderer, entity); + } + return snapshot_; +} + +std::optional FilterContentsFilterInput::GetCoverage( + const Entity& entity) const { + return filter_->GetCoverage(entity); +} + +Matrix FilterContentsFilterInput::GetLocalTransform( + const Entity& entity) const { + return filter_->GetLocalTransform(); +} + +Matrix FilterContentsFilterInput::GetTransform(const Entity& entity) const { + return filter_->GetTransform(entity.GetTransformation()); +} + +/******************************************************************************* + ******* ContentsFilterInput + ******************************************************************************/ + +ContentsFilterInput::ContentsFilterInput(std::shared_ptr contents) + : contents_(contents) {} + +ContentsFilterInput::~ContentsFilterInput() = default; + +FilterInput::Variant ContentsFilterInput::GetInput() const { + return contents_; +} + +std::optional ContentsFilterInput::GetSnapshot( + const ContentContext& renderer, + const Entity& entity) const { + if (!snapshot_.has_value()) { + snapshot_ = contents_->RenderToSnapshot(renderer, entity); + } + return snapshot_; +} + +std::optional ContentsFilterInput::GetCoverage( + const Entity& entity) const { + return contents_->GetCoverage(entity); +} + +/******************************************************************************* + ******* TextureFilterInput + ******************************************************************************/ + +TextureFilterInput::TextureFilterInput(std::shared_ptr texture) + : texture_(texture) {} + +TextureFilterInput::~TextureFilterInput() = default; + +FilterInput::Variant TextureFilterInput::GetInput() const { + return texture_; +} + +std::optional TextureFilterInput::GetSnapshot( + const ContentContext& renderer, + const Entity& entity) const { + return Snapshot{.texture = texture_, .transform = GetTransform(entity)}; +} + +std::optional TextureFilterInput::GetCoverage( + const Entity& entity) const { + return Rect::MakeSize(Size(texture_->GetSize())) + .TransformBounds(GetTransform(entity)); +} + +Matrix TextureFilterInput::GetLocalTransform(const Entity& entity) const { + // Compute the local transform such that the texture is centered. + return Matrix::MakeTranslation(-Point(texture_->GetSize()) / 2); +} + +} // namespace impeller diff --git a/impeller/entity/contents/filters/filter_input.h b/impeller/entity/contents/filters/filter_input.h new file mode 100644 index 0000000000000..dd1f907a6df70 --- /dev/null +++ b/impeller/entity/contents/filters/filter_input.h @@ -0,0 +1,153 @@ +// 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. + +#pragma once + +#include +#include +#include +#include + +#include "impeller/entity/contents/contents.h" +#include "impeller/geometry/rect.h" +#include "impeller/renderer/formats.h" + +namespace impeller { + +class ContentContext; +class Entity; +class FilterContents; + +/******************************************************************************* + ******* FilterInput + ******************************************************************************/ + +/// `FilterInput` is a lazy/single eval `Snapshot` which may be shared across +/// filter parameters and used to evaluate input coverage. +/// +/// A `FilterInput` can be re-used for any filter inputs across an entity's +/// filter graph without repeating subpasses unnecessarily. +/// +/// Filters may decide to not evaluate inputs in situations where they won't +/// contribute to the filter's output texture. +class FilterInput { + public: + using Ref = std::shared_ptr; + using Vector = std::vector; + using Variant = std::variant, + std::shared_ptr, + std::shared_ptr>; + + virtual ~FilterInput(); + + static FilterInput::Ref Make(Variant input); + + static FilterInput::Vector Make(std::initializer_list inputs); + + virtual Variant GetInput() const = 0; + + virtual std::optional GetSnapshot(const ContentContext& renderer, + const Entity& entity) const = 0; + + virtual std::optional GetCoverage(const Entity& entity) const = 0; + + /// @brief Get the local transform of this filter input. This transform is + /// relative to the `Entity` transform space. + virtual Matrix GetLocalTransform(const Entity& entity) const; + + /// @brief Get the transform of this `FilterInput`. This is equivalent to + /// calling `entity.GetTransformation() * GetLocalTransform()`. + virtual Matrix GetTransform(const Entity& entity) const; +}; + +/******************************************************************************* + ******* FilterContentsFilterInput + ******************************************************************************/ + +class FilterContentsFilterInput final : public FilterInput { + public: + ~FilterContentsFilterInput() override; + + // |FilterInput| + Variant GetInput() const override; + + // |FilterInput| + std::optional GetSnapshot(const ContentContext& renderer, + const Entity& entity) const override; + + // |FilterInput| + std::optional GetCoverage(const Entity& entity) const override; + + // |FilterInput| + Matrix GetLocalTransform(const Entity& entity) const override; + + // |FilterInput| + Matrix GetTransform(const Entity& entity) const override; + + private: + FilterContentsFilterInput(std::shared_ptr filter); + + std::shared_ptr filter_; + mutable std::optional snapshot_; + + friend FilterInput; +}; + +/******************************************************************************* + ******* ContentsFilterInput + ******************************************************************************/ + +class ContentsFilterInput final : public FilterInput { + public: + ~ContentsFilterInput() override; + + // |FilterInput| + Variant GetInput() const override; + + // |FilterInput| + std::optional GetSnapshot(const ContentContext& renderer, + const Entity& entity) const override; + + // |FilterInput| + std::optional GetCoverage(const Entity& entity) const override; + + private: + ContentsFilterInput(std::shared_ptr contents); + + std::shared_ptr contents_; + mutable std::optional snapshot_; + + friend FilterInput; +}; + +/******************************************************************************* + ******* TextureFilterInput + ******************************************************************************/ + +class TextureFilterInput final : public FilterInput { + public: + ~TextureFilterInput() override; + + // |FilterInput| + Variant GetInput() const override; + + // |FilterInput| + std::optional GetSnapshot(const ContentContext& renderer, + const Entity& entity) const override; + + // |FilterInput| + std::optional GetCoverage(const Entity& entity) const override; + + // |FilterInput| + Matrix GetLocalTransform(const Entity& entity) const override; + + private: + TextureFilterInput(std::shared_ptr texture); + + std::shared_ptr texture_; + + friend FilterInput; +}; + +} // namespace impeller From c024ba9e6c39968662472905116326c0d9469e01 Mon Sep 17 00:00:00 2001 From: JsouLiang Date: Wed, 23 Mar 2022 15:14:47 +0800 Subject: [PATCH 04/17] Cut down only DLDashPathEffect --- display_list/display_list_builder.cc | 24 -- display_list/display_list_canvas_unittests.cc | 37 ++- display_list/display_list_path_effect.cc | 28 +- display_list/display_list_path_effect.h | 258 ++++-------------- 4 files changed, 74 insertions(+), 273 deletions(-) diff --git a/display_list/display_list_builder.cc b/display_list/display_list_builder.cc index fd4cc53fcb937..3c0d03f26e10e 100644 --- a/display_list/display_list_builder.cc +++ b/display_list/display_list_builder.cc @@ -282,36 +282,12 @@ void DisplayListBuilder::onSetPathEffect(const DlPathEffect* effect) { } else { current_path_effect_ = effect->shared(); switch (current_path_effect_->type()) { - case DlPathEffectType::kCorner: { - const DlCornerPathEffect* corner_effect = effect->asCorner(); - void* pod = Push(corner_effect->size(), 0); - new (pod) DlCornerPathEffect(corner_effect); - break; - } case DlPathEffectType::kDash: { const DlDashPathEffect* dash_effect = effect->asDash(); void* pod = Push(dash_effect->size(), 0); new (pod) DlDashPathEffect(dash_effect); break; } - case DlPathEffectType::kDiscrete: { - const DlDiscretePathEffect* discrete_effect = effect->asDiscrete(); - void* pod = Push(discrete_effect->size(), 0); - new (pod) DlDiscretePathEffect(discrete_effect); - break; - } - case DlPathEffectType::kSumPathEffect: { - const DlSumPathEffect* sum_effect = effect->asSum(); - void* pod = Push(sum_effect->size(), 0); - new (pod) DlSumPathEffect(sum_effect); - break; - } - case DlPathEffectType::kComposePathEffect: { - const DlComposePathEffect* compose_effect = effect->asCompose(); - void* pod = Push(compose_effect->size(), 0); - new (pod) DlComposePathEffect(compose_effect); - break; - } case DlPathEffectType::kUnknown: { Push(0, 0, effect->skia_object()); break; diff --git a/display_list/display_list_canvas_unittests.cc b/display_list/display_list_canvas_unittests.cc index 20b22c8974849..fdaa27119dbaa 100644 --- a/display_list/display_list_canvas_unittests.cc +++ b/display_list/display_list_canvas_unittests.cc @@ -1231,9 +1231,7 @@ class CanvasCompareTester { } { - std::shared_ptr effect = - DlDiscretePathEffect::Make(3, 5); - auto skia_effect = effect->skia_object(); + sk_sp effect = SkDiscretePathEffect::Make(3, 5); { // Discrete path effects need a stroke width for drawPointsAsPoints // to do something realistic @@ -1252,18 +1250,17 @@ class CanvasCompareTester { [=](SkCanvas*, SkPaint& p) { p.setStrokeWidth(5.0); p.setStrokeMiter(3.0); - p.setPathEffect(skia_effect); + p.setPathEffect(effect); }, [=](DisplayListBuilder& b) { b.setStrokeWidth(5.0); b.setStrokeMiter(3.0); - b.setPathEffect(effect.get()); + b.setPathEffect(DlPathEffect::From(effect).get()); })); } - EXPECT_TRUE(testP.is_draw_text_blob() || skia_effect->unique()) + EXPECT_TRUE(testP.is_draw_text_blob() || effect->unique()) << "PathEffect == Discrete-3-5 Cleanup"; - effect = DlDiscretePathEffect::Make(2, 3); - skia_effect = effect->skia_object(); + effect = SkDiscretePathEffect::Make(2, 3); { // Discrete path effects need a stroke width for drawPointsAsPoints // to do something realistic @@ -1282,15 +1279,15 @@ class CanvasCompareTester { [=](SkCanvas*, SkPaint& p) { p.setStrokeWidth(5.0); p.setStrokeMiter(2.5); - p.setPathEffect(skia_effect); + p.setPathEffect(effect); }, [=](DisplayListBuilder& b) { b.setStrokeWidth(5.0); b.setStrokeMiter(2.5); - b.setPathEffect(effect.get()); + b.setPathEffect(DlPathEffect::From(effect).get()); })); } - EXPECT_TRUE(testP.is_draw_text_blob() || skia_effect->unique()) + EXPECT_TRUE(testP.is_draw_text_blob() || effect->unique()) << "PathEffect == Discrete-2-3 Cleanup"; } @@ -1507,8 +1504,7 @@ class CanvasCompareTester { { const SkScalar TestDashes1[] = {29.0, 2.0}; const SkScalar TestDashes2[] = {17.0, 1.5}; - auto effect = DlDashPathEffect::Make(TestDashes1, 2, 0.0f); - auto skia_effect = effect->skia_object(); + auto effect = SkDashPathEffect::Make(TestDashes1, 2, 0.0f); { RenderWith(testP, stroke_base_env, tolerance, CaseParameters( @@ -1518,20 +1514,19 @@ class CanvasCompareTester { p.setStyle(SkPaint::kStroke_Style); // Provide some non-trivial stroke size to get dashed p.setStrokeWidth(5.0); - p.setPathEffect(skia_effect); + p.setPathEffect(effect); }, [=](DisplayListBuilder& b) { // Need stroke style to see dashing properly b.setStyle(DlDrawStyle::kStroke); // Provide some non-trivial stroke size to get dashed b.setStrokeWidth(5.0); - b.setPathEffect(effect.get()); + b.setPathEffect(DlPathEffect::From(effect).get()); })); } - EXPECT_TRUE(testP.is_draw_text_blob() || skia_effect->unique()) + EXPECT_TRUE(testP.is_draw_text_blob() || effect->unique()) << "PathEffect == Dash-29-2 Cleanup"; - effect = DlDashPathEffect::Make(TestDashes2, 2, 0.0f); - skia_effect = effect->skia_object(); + effect = SkDashPathEffect::Make(TestDashes2, 2, 0.0f); { RenderWith(testP, stroke_base_env, tolerance, CaseParameters( @@ -1541,17 +1536,17 @@ class CanvasCompareTester { p.setStyle(SkPaint::kStroke_Style); // Provide some non-trivial stroke size to get dashed p.setStrokeWidth(5.0); - p.setPathEffect(skia_effect); + p.setPathEffect(effect); }, [=](DisplayListBuilder& b) { // Need stroke style to see dashing properly b.setStyle(DlDrawStyle::kStroke); // Provide some non-trivial stroke size to get dashed b.setStrokeWidth(5.0); - b.setPathEffect(effect.get()); + b.setPathEffect(DlPathEffect::From(effect).get()); })); } - EXPECT_TRUE(testP.is_draw_text_blob() || skia_effect->unique()) + EXPECT_TRUE(testP.is_draw_text_blob() || effect->unique()) << "PathEffect == Dash-17-1.5 Cleanup"; } } diff --git a/display_list/display_list_path_effect.cc b/display_list/display_list_path_effect.cc index 1e11c89e1b878..bace4ba0682f8 100644 --- a/display_list/display_list_path_effect.cc +++ b/display_list/display_list_path_effect.cc @@ -12,24 +12,18 @@ std::shared_ptr DlPathEffect::From(SkPathEffect* sk_path_effect) { if (sk_path_effect == nullptr) { return nullptr; } - // There are no inspection methods for SkPathEffect so we cannot break - // the Skia filter down into a specific subclass (i.e. DlSumPathEffect or - // DlComposePathEffect). - return std::make_shared(sk_ref_sp(sk_path_effect)); -} - -std::shared_ptr DlPathEffect::MakeSum( - std::shared_ptr first, - std::shared_ptr second) { - return std::make_shared(first->skia_object(), - second->skia_object()); -} -std::shared_ptr DlPathEffect::MakeCompose( - std::shared_ptr outer, - std::shared_ptr inner) { - return std::make_shared(outer->skia_object(), - inner->skia_object()); + SkPathEffect::DashInfo info; + if (SkPathEffect::DashType::kDash_DashType == + sk_path_effect->asADash(&info)) { + auto dash_path_effect = std::make_shared( + info.fIntervals, info.fCount, info.fPhase); + info.fIntervals = dash_path_effect->interval(); + sk_path_effect->asADash(&info); + return dash_path_effect; + } + // If not dash path effect, we will use UnknownPathEffect to wrap it. + return std::make_shared(sk_ref_sp(sk_path_effect)); } } // namespace flutter diff --git a/display_list/display_list_path_effect.h b/display_list/display_list_path_effect.h index 22748254f89ba..1b5143e0f0ecc 100644 --- a/display_list/display_list_path_effect.h +++ b/display_list/display_list_path_effect.h @@ -5,28 +5,27 @@ #ifndef FLUTTER_DISPLAY_LIST_DISPLAY_LIST_PATH_EFFECT_H_ #define FLUTTER_DISPLAY_LIST_DISPLAY_LIST_PATH_EFFECT_H_ -#include -#include -#include #include "flutter/display_list/display_list_attributes.h" #include "flutter/display_list/types.h" #include "flutter/fml/logging.h" +#include "include/core/SkScalar.h" namespace flutter { -class DlComposePathEffect; -class DlSumPathEffect; -class DlCornerPathEffect; class DlDashPathEffect; -class DlDiscretePathEffect; +// The DisplayList PathEffect class. This class implements all of the +// facilities and adheres to the design goals of the |DlAttribute| base +// class. + +// An enumerated type for the recognized PathEffect operations. +// In current Flutter we only use the DashPathEffect. +// And another PathEffect outside of the recognized types is needed +// then a |kUnknown| type that simply defers to an SkPathEffect is +// provided as a fallback. enum class DlPathEffectType { - kCorner, kDash, - kDiscrete, - kSumPathEffect, - kComposePathEffect, - kUnknown + kUnknown, }; class DlPathEffect @@ -39,69 +38,45 @@ class DlPathEffect return From(sk_path_effect.get()); } - static std::shared_ptr MakeSum( - std::shared_ptr first, - std::shared_ptr second); - - static std::shared_ptr MakeCompose( - std::shared_ptr outer, - std::shared_ptr inner); - - virtual const DlCornerPathEffect* asCorner() const { return nullptr; } - virtual const DlDashPathEffect* asDash() const { return nullptr; } - - virtual const DlDiscretePathEffect* asDiscrete() const { return nullptr; } - - virtual const DlSumPathEffect* asSum() const { return nullptr; } - virtual const DlComposePathEffect* asCompose() const { return nullptr; } -}; - -class DlCornerPathEffect : public DlPathEffect { - public: - DlCornerPathEffect(SkScalar radius) : radius_(radius) {} - - DlCornerPathEffect(const DlCornerPathEffect& corner_effect) - : DlCornerPathEffect(corner_effect.radius_) {} - DlCornerPathEffect(const DlCornerPathEffect* corner_effect) - : DlCornerPathEffect(corner_effect->radius_) {} - - static std::shared_ptr Make(SkScalar radius) { - return std::make_shared(radius); - } - - DlPathEffectType type() const override { return DlPathEffectType::kCorner; } - size_t size() const override { return sizeof(*this); } - - std::shared_ptr shared() const override { - return std::make_shared(this); - } - - const DlCornerPathEffect* asCorner() const override { return this; } - - sk_sp skia_object() const override { - return SkCornerPathEffect::Make(radius_); - } - - protected: - bool equals_(DlPathEffect const& other) const override { - FML_DCHECK(other.type() == DlPathEffectType::kCorner); - auto that = static_cast(&other); - return radius_ == that->radius_; - } - - SkScalar radius_; }; +/// The DashPathEffect which specifies modifying the path effect, and it +/// only affects storked paths. +/// intervals: array containing an even number of entries (>=2), with +/// the even indices specifying the length of "on" intervals, and the odd +/// indices specifying the length of "off" intervals. This array will be +/// copied in Make, and can be disposed of freely after. +/// count: number of elements in the intervals array +/// phase: offset into the intervals array (mod the sum of all of the +/// intervals). +/// +/// For example: if intervals[] = {10, 20}, count = 2, and phase = 25, +/// this will set up a dashed path like so: +/// 5 pixels off +/// 10 pixels on +/// 20 pixels off +/// 10 pixels on +/// 20 pixels off +/// ... +/// A phase of -5, 25, 55, 85, etc. would all result in the same path, +/// because the sum of all the intervals is 30. +/// class DlDashPathEffect : public DlPathEffect { public: DlDashPathEffect(const SkScalar intervals[], int count, SkScalar phase) - : intervals_(intervals), count_(count), phase_(phase) {} + : count_(count), phase_(phase) { + intervals_ = new SkScalar[count]; + if (intervals != nullptr) { + memcpy(intervals_, intervals, sizeof(SkScalar) * count); + } + } DlDashPathEffect(const DlDashPathEffect& dash_effect) : DlDashPathEffect(dash_effect.intervals_, dash_effect.count_, dash_effect.phase_) {} + DlDashPathEffect(const DlDashPathEffect* dash_effect) : DlDashPathEffect(dash_effect->intervals_, dash_effect->count_, @@ -126,67 +101,24 @@ class DlDashPathEffect : public DlPathEffect { return SkDashPathEffect::Make(intervals_, count_, phase_); } + ~DlDashPathEffect() { delete[] intervals_; } + + SkScalar* interval() const { return intervals_; } + protected: bool equals_(DlPathEffect const& other) const override { FML_DCHECK(other.type() == DlPathEffectType::kDash); auto that = static_cast(&other); - return intervals_ == that->intervals_ && count_ == that->count_ && - phase_ == that->phase_; + return memcmp(intervals_, that->intervals_, sizeof(SkScalar) * count_) == + 0 && + count_ == that->count_ && phase_ == that->phase_; } - const SkScalar* intervals_; + SkScalar* intervals_; int count_; SkScalar phase_; }; -class DlDiscretePathEffect : public DlPathEffect { - public: - DlDiscretePathEffect(SkScalar segLength, - SkScalar dev, - uint32_t seedAssist = 0) - : segLength_(segLength), dev_(dev), seedAssist_(seedAssist) {} - - DlDiscretePathEffect(const DlDiscretePathEffect& discrete_effect) - : DlDiscretePathEffect(discrete_effect.segLength_, - discrete_effect.dev_, - discrete_effect.seedAssist_) {} - DlDiscretePathEffect(const DlDiscretePathEffect* discrete_effect) - : DlDiscretePathEffect(discrete_effect->segLength_, - discrete_effect->dev_, - discrete_effect->seedAssist_) {} - - DlPathEffectType type() const override { return DlPathEffectType::kDiscrete; } - size_t size() const override { return sizeof(*this); } - - static std::shared_ptr Make(SkScalar segLength, - SkScalar dev, - uint32_t seedAssist = 0) { - return std::make_shared(segLength, dev, seedAssist); - } - - std::shared_ptr shared() const override { - return std::make_shared(this); - } - - const DlDiscretePathEffect* asDiscrete() const override { return this; } - - sk_sp skia_object() const override { - return SkDiscretePathEffect::Make(segLength_, dev_, seedAssist_); - } - - protected: - bool equals_(DlPathEffect const& other) const override { - FML_DCHECK(other.type() == DlPathEffectType::kDiscrete); - auto that = static_cast(&other); - return segLength_ == that->segLength_ && dev_ == that->dev_ && - seedAssist_ == that->seedAssist_; - } - - SkScalar segLength_; - SkScalar dev_; - uint32_t seedAssist_ = 0; -}; - class DlUnknownPathEffect final : public DlPathEffect { public: DlUnknownPathEffect(sk_sp effect) @@ -217,102 +149,6 @@ class DlUnknownPathEffect final : public DlPathEffect { private: sk_sp sk_path_effect_; }; -class DlPairPathEffect : public DlPathEffect { - protected: - DlPairPathEffect(sk_sp pe0, sk_sp pe1) - : fPE0(std::move(pe0)), fPE1(std::move(pe1)) {} - - sk_sp fPE0; - sk_sp fPE1; -}; - -class DlComposePathEffect final : public DlPairPathEffect { - public: - DlComposePathEffect(sk_sp first, sk_sp second) - : DlPairPathEffect(first, second) {} - - DlComposePathEffect(const DlComposePathEffect& path_effect) - : DlComposePathEffect(path_effect.fPE0, path_effect.fPE1) {} - DlComposePathEffect(const DlComposePathEffect* path_effect) - : DlComposePathEffect(path_effect->fPE0, path_effect->fPE1) {} - - static std::shared_ptr Make(sk_sp outer, - sk_sp inner) { - if (!outer) { - return From(inner); - } - if (!inner) { - return From(outer); - } - return std::make_shared(outer, inner); - } - - DlPathEffectType type() const override { - return DlPathEffectType::kComposePathEffect; - } - size_t size() const override { return sizeof(*this); } - - std::shared_ptr shared() const override { - return std::make_shared(this); - } - - const DlComposePathEffect* asCompose() const override { return this; } - - sk_sp skia_object() const override { - return SkPathEffect::MakeCompose(fPE0, fPE1); - } - - protected: - bool equals_(DlPathEffect const& other) const override { - FML_DCHECK(other.type() == DlPathEffectType::kComposePathEffect); - auto that = static_cast(&other); - return fPE0 == that->fPE0 && fPE1 == that->fPE1; - } -}; - -class DlSumPathEffect final : public DlPairPathEffect { - public: - DlSumPathEffect(sk_sp first, sk_sp second) - : DlPairPathEffect(first, second) {} - - DlSumPathEffect(const DlSumPathEffect& path_effect) - : DlSumPathEffect(path_effect.fPE0, path_effect.fPE1) {} - DlSumPathEffect(const DlSumPathEffect* path_effect) - : DlSumPathEffect(path_effect->fPE0, path_effect->fPE1) {} - - static std::shared_ptr Make(sk_sp first, - sk_sp second) { - if (!first) { - return From(second); - } - if (!second) { - return From(first); - } - return std::make_shared(first, second); - } - - DlPathEffectType type() const override { - return DlPathEffectType::kSumPathEffect; - } - size_t size() const override { return sizeof(*this); } - - std::shared_ptr shared() const override { - return std::make_shared(this); - } - - sk_sp skia_object() const override { - return SkPathEffect::MakeSum(fPE0, fPE1); - } - - const DlSumPathEffect* asSum() const override { return this; } - - protected: - bool equals_(DlPathEffect const& other) const override { - FML_DCHECK(other.type() == DlPathEffectType::kSumPathEffect); - auto that = static_cast(&other); - return fPE0 == that->fPE0 && fPE1 == that->fPE1; - } -}; } // namespace flutter From 19bbde99b55fb5e505b067754a3ccfc2d4c258e1 Mon Sep 17 00:00:00 2001 From: JsouLiang Date: Thu, 24 Mar 2022 15:23:41 +0800 Subject: [PATCH 05/17] Create Intervals by other mode --- display_list/display_list_canvas_unittests.cc | 16 +-- display_list/display_list_path_effect.cc | 33 +++++- display_list/display_list_path_effect.h | 79 +++++++------ .../display_list_path_effect_unittests.cc | 107 +++++++++--------- display_list/display_list_unittests.cc | 11 +- 5 files changed, 147 insertions(+), 99 deletions(-) diff --git a/display_list/display_list_canvas_unittests.cc b/display_list/display_list_canvas_unittests.cc index fdaa27119dbaa..fc3e5f13c52b0 100644 --- a/display_list/display_list_canvas_unittests.cc +++ b/display_list/display_list_canvas_unittests.cc @@ -1504,7 +1504,7 @@ class CanvasCompareTester { { const SkScalar TestDashes1[] = {29.0, 2.0}; const SkScalar TestDashes2[] = {17.0, 1.5}; - auto effect = SkDashPathEffect::Make(TestDashes1, 2, 0.0f); + auto effect = DlDashPathEffect::Make(TestDashes1, 2, 0.0f); { RenderWith(testP, stroke_base_env, tolerance, CaseParameters( @@ -1514,19 +1514,19 @@ class CanvasCompareTester { p.setStyle(SkPaint::kStroke_Style); // Provide some non-trivial stroke size to get dashed p.setStrokeWidth(5.0); - p.setPathEffect(effect); + p.setPathEffect(effect->skia_object()); }, [=](DisplayListBuilder& b) { // Need stroke style to see dashing properly b.setStyle(DlDrawStyle::kStroke); // Provide some non-trivial stroke size to get dashed b.setStrokeWidth(5.0); - b.setPathEffect(DlPathEffect::From(effect).get()); + b.setPathEffect(effect.get()); })); } - EXPECT_TRUE(testP.is_draw_text_blob() || effect->unique()) + EXPECT_TRUE(testP.is_draw_text_blob() || effect->skia_object()->unique()) << "PathEffect == Dash-29-2 Cleanup"; - effect = SkDashPathEffect::Make(TestDashes2, 2, 0.0f); + effect = DlDashPathEffect::Make(TestDashes2, 2, 0.0f); { RenderWith(testP, stroke_base_env, tolerance, CaseParameters( @@ -1536,17 +1536,17 @@ class CanvasCompareTester { p.setStyle(SkPaint::kStroke_Style); // Provide some non-trivial stroke size to get dashed p.setStrokeWidth(5.0); - p.setPathEffect(effect); + p.setPathEffect(effect->skia_object()); }, [=](DisplayListBuilder& b) { // Need stroke style to see dashing properly b.setStyle(DlDrawStyle::kStroke); // Provide some non-trivial stroke size to get dashed b.setStrokeWidth(5.0); - b.setPathEffect(DlPathEffect::From(effect).get()); + b.setPathEffect(effect.get()); })); } - EXPECT_TRUE(testP.is_draw_text_blob() || effect->unique()) + EXPECT_TRUE(testP.is_draw_text_blob() || effect->skia_object()->unique()) << "PathEffect == Dash-17-1.5 Cleanup"; } } diff --git a/display_list/display_list_path_effect.cc b/display_list/display_list_path_effect.cc index bace4ba0682f8..358183f398cd6 100644 --- a/display_list/display_list_path_effect.cc +++ b/display_list/display_list_path_effect.cc @@ -3,11 +3,24 @@ // found in the LICENSE file. #include "flutter/display_list/display_list_path_effect.h" + #include +#include + #include "include/core/SkRefCnt.h" +#include "include/core/SkScalar.h" namespace flutter { +static void DlPathEffectDeleter(void* p) { + // Some of our target environments would prefer a sized delete, + // but other target environments do not have that operator. + // Use an unsized delete until we get better agreement in the + // environments. + // See https://github.com/flutter/flutter/issues/100327 + ::operator delete(p); +} + std::shared_ptr DlPathEffect::From(SkPathEffect* sk_path_effect) { if (sk_path_effect == nullptr) { return nullptr; @@ -16,9 +29,11 @@ std::shared_ptr DlPathEffect::From(SkPathEffect* sk_path_effect) { SkPathEffect::DashInfo info; if (SkPathEffect::DashType::kDash_DashType == sk_path_effect->asADash(&info)) { - auto dash_path_effect = std::make_shared( - info.fIntervals, info.fCount, info.fPhase); - info.fIntervals = dash_path_effect->interval(); + auto dash_path_effect = + DlDashPathEffect::Make(info.fIntervals, info.fCount, info.fPhase); + info.fIntervals = + reinterpret_cast(dash_path_effect.get()) + ->intervals(); sk_path_effect->asADash(&info); return dash_path_effect; } @@ -26,4 +41,16 @@ std::shared_ptr DlPathEffect::From(SkPathEffect* sk_path_effect) { return std::make_shared(sk_ref_sp(sk_path_effect)); } +std::shared_ptr DlDashPathEffect::Make(const SkScalar* intervals, + int count, + SkScalar phase) { + size_t needed = sizeof(DlDashPathEffect) + sizeof(SkScalar) * count; + void* storage = ::operator new(needed); + + std::shared_ptr ret; + ret.reset(new (storage) DlDashPathEffect(intervals, count, phase), + DlPathEffectDeleter); + return std::move(ret); +} + } // namespace flutter diff --git a/display_list/display_list_path_effect.h b/display_list/display_list_path_effect.h index 1b5143e0f0ecc..477bb83b9e959 100644 --- a/display_list/display_list_path_effect.h +++ b/display_list/display_list_path_effect.h @@ -39,6 +39,12 @@ class DlPathEffect } virtual const DlDashPathEffect* asDash() const { return nullptr; } + + protected: + DlPathEffect() = default; + + private: + FML_DISALLOW_COPY_ASSIGN_AND_MOVE(DlPathEffect); }; /// The DashPathEffect which specifies modifying the path effect, and it @@ -62,37 +68,19 @@ class DlPathEffect /// A phase of -5, 25, 55, 85, etc. would all result in the same path, /// because the sum of all the intervals is 30. /// -class DlDashPathEffect : public DlPathEffect { +class DlDashPathEffect final : public DlPathEffect { public: - DlDashPathEffect(const SkScalar intervals[], int count, SkScalar phase) - : count_(count), phase_(phase) { - intervals_ = new SkScalar[count]; - if (intervals != nullptr) { - memcpy(intervals_, intervals, sizeof(SkScalar) * count); - } - } - - DlDashPathEffect(const DlDashPathEffect& dash_effect) - : DlDashPathEffect(dash_effect.intervals_, - dash_effect.count_, - dash_effect.phase_) {} - - DlDashPathEffect(const DlDashPathEffect* dash_effect) - : DlDashPathEffect(dash_effect->intervals_, - dash_effect->count_, - dash_effect->phase_) {} - - static std::shared_ptr Make(const SkScalar intervals[], - int count, - SkScalar phase) { - return std::make_shared(intervals, count, phase); - } + static std::shared_ptr Make(const SkScalar intervals[], + int count, + SkScalar phase); DlPathEffectType type() const override { return DlPathEffectType::kDash; } - size_t size() const override { return sizeof(*this); } + size_t size() const override { + return sizeof(*this) + sizeof(SkScalar) * count_; + } std::shared_ptr shared() const override { - return std::make_shared(this); + return Make(intervals_, count_, phase_); } const DlDashPathEffect* asDash() const override { return this; } @@ -101,22 +89,49 @@ class DlDashPathEffect : public DlPathEffect { return SkDashPathEffect::Make(intervals_, count_, phase_); } - ~DlDashPathEffect() { delete[] intervals_; } - - SkScalar* interval() const { return intervals_; } + SkScalar* intervals() const { return intervals_; } protected: bool equals_(DlPathEffect const& other) const override { FML_DCHECK(other.type() == DlPathEffectType::kDash); auto that = static_cast(&other); - return memcmp(intervals_, that->intervals_, sizeof(SkScalar) * count_) == - 0 && - count_ == that->count_ && phase_ == that->phase_; + return count_ == that->count_ && base_equals_(that) && + phase_ == that->phase_; + } + + private: + bool base_equals_(DlDashPathEffect const* other) const { + // intervals not nullptr, that has value + if (intervals_ != nullptr && other != nullptr) { + for (int i = 0; i < count_; i++) { + if (intervals_[i] != other->intervals_[i]) { + return false; + } + } + } + return true; } + DlDashPathEffect(const SkScalar intervals[], int count, SkScalar phase) + : count_(count), phase_(phase) { + intervals_ = reinterpret_cast(this + 1); + if (intervals != nullptr) { + memcpy(intervals_, intervals, sizeof(SkScalar) * count); + } + } + + DlDashPathEffect(const DlDashPathEffect* dash_effect) + : DlDashPathEffect(dash_effect->intervals_, + dash_effect->count_, + dash_effect->phase_) {} + SkScalar* intervals_; int count_; SkScalar phase_; + + friend class DisplayListBuilder; + + FML_DISALLOW_COPY_ASSIGN_AND_MOVE(DlDashPathEffect); }; class DlUnknownPathEffect final : public DlPathEffect { diff --git a/display_list/display_list_path_effect_unittests.cc b/display_list/display_list_path_effect_unittests.cc index 70c42150ad158..683feb9645eec 100644 --- a/display_list/display_list_path_effect_unittests.cc +++ b/display_list/display_list_path_effect_unittests.cc @@ -16,13 +16,13 @@ const SkScalar TestDashes1[] = {4.0, 2.0}; const SkScalar TestDashes2[] = {1.0, 1.5}; TEST(DisplayListPathEffect, BuilderSetGet) { - DlDashPathEffect dash_path_effect(TestDashes1, 2, 0.0); + auto dash_path_effect = DlDashPathEffect::Make(TestDashes1, 2, 0.0); DisplayListBuilder builder; ASSERT_EQ(builder.getPathEffect(), nullptr); - builder.setPathEffect(&dash_path_effect); + builder.setPathEffect(dash_path_effect.get()); ASSERT_NE(builder.getPathEffect(), nullptr); ASSERT_TRUE(Equals(builder.getPathEffect(), - static_cast(&dash_path_effect))); + static_cast(dash_path_effect.get()))); builder.setPathEffect(nullptr); ASSERT_EQ(builder.getPathEffect(), nullptr); } @@ -39,36 +39,39 @@ TEST(DisplayListPathEffect, FromSkiaPathEffect) { std::shared_ptr dl_path_effect = DlPathEffect::From(sk_path_effect); - ASSERT_EQ(dl_path_effect->type(), DlPathEffectType::kUnknown); + ASSERT_EQ(dl_path_effect->type(), DlPathEffectType::kDash); // We cannot recapture the dash parameters from an SkDashPathEffect - ASSERT_EQ(dl_path_effect->asDash(), nullptr); - ASSERT_EQ(dl_path_effect->skia_object(), sk_path_effect); + ASSERT_EQ(dl_path_effect->asDash(), dl_path_effect.get()); + ASSERT_TRUE( + Equals(dl_path_effect, DlDashPathEffect::Make(TestDashes2, 2, 0.0))); } TEST(DisplayListPathEffect, EffectShared) { - DlDashPathEffect effect(TestDashes2, 2, 0.0); - ASSERT_NE(effect.shared().get(), &effect); - ASSERT_EQ(*effect.shared(), effect); + auto effect = DlDashPathEffect::Make(TestDashes2, 2, 0.0); + ASSERT_TRUE(Equals(effect->shared(), effect)); } TEST(DisplayListPathEffect, DashEffectAsDash) { - DlDashPathEffect effect(TestDashes2, 2, 0.0); - ASSERT_NE(effect.asDash(), nullptr); - ASSERT_EQ(effect.asDash(), &effect); + auto effect = DlDashPathEffect::Make(TestDashes2, 2, 0.0); + ASSERT_NE(effect->asDash(), nullptr); + ASSERT_EQ(effect->asDash(), effect.get()); } TEST(DisplayListPathEffect, DashEffectEquals) { - DlDashPathEffect effect1(TestDashes2, 2, 0.0); - DlDashPathEffect effect2(TestDashes2, 2, 0.0); - TestEquals(effect1, effect2); + auto effect1 = DlDashPathEffect::Make(TestDashes2, 2, 0.0); + auto effect2 = DlDashPathEffect::Make(TestDashes2, 2, 0.0); + ASSERT_TRUE(Equals(effect1, effect2)); + ASSERT_TRUE(Equals(effect1->shared(), effect2->shared())); } TEST(DisplayListPathEffect, BlurNotEquals) { - DlDashPathEffect effect1(TestDashes1, 2, 0.0); - DlDashPathEffect effect2(TestDashes2, 2, 0.0); - DlDashPathEffect effect3(TestDashes2, 3, 0.0); - TestNotEquals(effect1, effect2, "intervals differs"); - TestNotEquals(effect2, effect3, "phase differs"); + auto effect1 = DlDashPathEffect::Make(TestDashes1, 2, 0.0); + auto effect2 = DlDashPathEffect::Make(TestDashes2, 2, 0.0); + auto effect3 = DlDashPathEffect::Make(TestDashes2, 3, 0.0); + ASSERT_NE(effect1, effect2); + ASSERT_NE(effect2, effect3); + ASSERT_NE(effect1->shared(), effect2->shared()); + ASSERT_NE(effect2->shared(), effect3->shared()); } TEST(DisplayListPathEffect, UnknownConstructor) { @@ -156,9 +159,9 @@ void testNotEquals(std::shared_ptr a, } TEST(DisplayListPathEffect, ComparableTemplates) { - DlDashPathEffect effect1(TestDashes1, 2, 0.0); - DlDashPathEffect effect2(TestDashes1, 2, 0.0); - DlDashPathEffect effect3(TestDashes2, 3, 0.0); + auto effect1 = DlDashPathEffect::Make(TestDashes1, 2, 0.0); + auto effect2 = DlDashPathEffect::Make(TestDashes1, 2, 0.0); + auto effect3 = DlDashPathEffect::Make(TestDashes2, 3, 0.0); std::shared_ptr shared_null; // null to null @@ -167,43 +170,43 @@ TEST(DisplayListPathEffect, ComparableTemplates) { testEquals(shared_null, shared_null); // ptr to null - testNotEquals(&effect1, nullptr); - testNotEquals(&effect2, nullptr); - testNotEquals(&effect3, nullptr); + testNotEquals(effect1.get(), nullptr); + testNotEquals(effect2.get(), nullptr); + testNotEquals(effect3.get(), nullptr); // shared_ptr to null and shared_null to ptr - testNotEquals(effect1.shared(), nullptr); - testNotEquals(effect2.shared(), nullptr); - testNotEquals(effect3.shared(), nullptr); - testNotEquals(shared_null, &effect1); - testNotEquals(shared_null, &effect2); - testNotEquals(shared_null, &effect3); + testNotEquals(effect1->shared(), nullptr); + testNotEquals(effect2->shared(), nullptr); + testNotEquals(effect3->shared(), nullptr); + testNotEquals(shared_null, effect1.get()); + testNotEquals(shared_null, effect2.get()); + testNotEquals(shared_null, effect3.get()); // ptr to ptr - testEquals(&effect1, &effect1); - testEquals(&effect1, &effect2); - testEquals(&effect3, &effect3); - testEquals(&effect2, &effect2); + testEquals(effect1, effect1); + testEquals(effect1, effect2); + testEquals(effect3, effect3); + testEquals(effect2, effect2); // shared_ptr to ptr - testEquals(effect1.shared(), &effect1); - testEquals(effect1.shared(), &effect2); - testEquals(effect2.shared(), &effect2); - testEquals(effect3.shared(), &effect3); - testNotEquals(effect1.shared(), &effect3); - testNotEquals(effect2.shared(), &effect3); - testNotEquals(effect3.shared(), &effect1); - testNotEquals(effect3.shared(), &effect2); + testEquals(effect1->shared(), effect1); + testEquals(effect1->shared(), effect2); + testEquals(effect2->shared(), effect2); + testEquals(effect3->shared(), effect3); + testNotEquals(effect1->shared(), effect3); + testNotEquals(effect2->shared(), effect3); + testNotEquals(effect3->shared(), effect1); + testNotEquals(effect3->shared(), effect2); // shared_ptr to shared_ptr - testEquals(effect1.shared(), effect1.shared()); - testEquals(effect1.shared(), effect2.shared()); - testEquals(effect2.shared(), effect2.shared()); - testEquals(effect3.shared(), effect3.shared()); - testNotEquals(effect1.shared(), effect3.shared()); - testNotEquals(effect2.shared(), effect3.shared()); - testNotEquals(effect3.shared(), effect1.shared()); - testNotEquals(effect3.shared(), effect2.shared()); + testEquals(effect1->shared(), effect1->shared()); + testEquals(effect1->shared(), effect2->shared()); + testEquals(effect2->shared(), effect2->shared()); + testEquals(effect3->shared(), effect3->shared()); + testNotEquals(effect1->shared(), effect3->shared()); + testNotEquals(effect2->shared(), effect3->shared()); + testNotEquals(effect3->shared(), effect1->shared()); + testNotEquals(effect3->shared(), effect2->shared()); } } // namespace testing diff --git a/display_list/display_list_unittests.cc b/display_list/display_list_unittests.cc index fcb5b98db7f92..3d436c7cc8091 100644 --- a/display_list/display_list_unittests.cc +++ b/display_list/display_list_unittests.cc @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include #include "flutter/display_list/display_list.h" #include "flutter/display_list/display_list_builder.h" #include "flutter/display_list/display_list_canvas_recorder.h" @@ -173,8 +174,10 @@ static const DlComposeImageFilter TestComposeImageFilter3( TestMatrixImageFilter2); static const DlColorFilterImageFilter TestCFImageFilter1(TestBlendColorFilter1); static const DlColorFilterImageFilter TestCFImageFilter2(TestBlendColorFilter2); -static const DlDashPathEffect TestPathEffect1(TestDashes1, 2, 0.0f); -static const DlDashPathEffect TestPathEffect2(TestDashes2, 2, 0.0f); +static const std::shared_ptr TestPathEffect1 = + DlDashPathEffect::Make(TestDashes1, 2, 0.0f); +static const std::shared_ptr TestPathEffect2 = + DlDashPathEffect::Make(TestDashes2, 2, 0.0f); static const DlBlurMaskFilter TestMaskFilter1(kNormal_SkBlurStyle, 3.0); static const DlBlurMaskFilter TestMaskFilter2(kNormal_SkBlurStyle, 5.0); static const DlBlurMaskFilter TestMaskFilter3(kSolid_SkBlurStyle, 3.0); @@ -425,8 +428,8 @@ std::vector allGroups = { } }, { "SetPathEffect", { - {0, 32, 0, 0, [](DisplayListBuilder& b) {b.setPathEffect(&TestPathEffect1);}}, - {0, 32, 0, 0, [](DisplayListBuilder& b) {b.setPathEffect(&TestPathEffect2);}}, + {0, 40, 0, 0, [](DisplayListBuilder& b) {b.setPathEffect(TestPathEffect1.get());}}, + {0, 40, 0, 0, [](DisplayListBuilder& b) {b.setPathEffect(TestPathEffect2.get());}}, {0, 0, 0, 0, [](DisplayListBuilder& b) {b.setPathEffect(nullptr);}}, } }, From 731e605c4e90485e22302b967cbed69c56a96b51 Mon Sep 17 00:00:00 2001 From: JsouLiang Date: Fri, 25 Mar 2022 10:55:57 +0800 Subject: [PATCH 06/17] Fix unittest issues --- display_list/display_list_path_effect.h | 19 +++++++++++-------- .../display_list_path_effect_unittests.cc | 14 ++++++++++++++ display_list/display_list_unittests.cc | 6 ++++-- 3 files changed, 29 insertions(+), 10 deletions(-) diff --git a/display_list/display_list_path_effect.h b/display_list/display_list_path_effect.h index 477bb83b9e959..073e40aabe719 100644 --- a/display_list/display_list_path_effect.h +++ b/display_list/display_list_path_effect.h @@ -80,16 +80,16 @@ class DlDashPathEffect final : public DlPathEffect { } std::shared_ptr shared() const override { - return Make(intervals_, count_, phase_); + return Make(pods(), count_, phase_); } const DlDashPathEffect* asDash() const override { return this; } sk_sp skia_object() const override { - return SkDashPathEffect::Make(intervals_, count_, phase_); + return SkDashPathEffect::Make(pods(), count_, phase_); } - SkScalar* intervals() const { return intervals_; } + SkScalar* intervals() { return reinterpret_cast(this + 1); } protected: bool equals_(DlPathEffect const& other) const override { @@ -100,11 +100,15 @@ class DlDashPathEffect final : public DlPathEffect { } private: + const SkScalar* pods() const { + return reinterpret_cast(this + 1); + } + bool base_equals_(DlDashPathEffect const* other) const { // intervals not nullptr, that has value - if (intervals_ != nullptr && other != nullptr) { + if (other != nullptr) { for (int i = 0; i < count_; i++) { - if (intervals_[i] != other->intervals_[i]) { + if (pods()[i] != other->pods()[i]) { return false; } } @@ -114,18 +118,17 @@ class DlDashPathEffect final : public DlPathEffect { DlDashPathEffect(const SkScalar intervals[], int count, SkScalar phase) : count_(count), phase_(phase) { - intervals_ = reinterpret_cast(this + 1); if (intervals != nullptr) { + SkScalar* intervals_ = reinterpret_cast(this + 1); memcpy(intervals_, intervals, sizeof(SkScalar) * count); } } DlDashPathEffect(const DlDashPathEffect* dash_effect) - : DlDashPathEffect(dash_effect->intervals_, + : DlDashPathEffect(dash_effect->pods(), dash_effect->count_, dash_effect->phase_) {} - SkScalar* intervals_; int count_; SkScalar phase_; diff --git a/display_list/display_list_path_effect_unittests.cc b/display_list/display_list_path_effect_unittests.cc index 683feb9645eec..a5dd151aaabfd 100644 --- a/display_list/display_list_path_effect_unittests.cc +++ b/display_list/display_list_path_effect_unittests.cc @@ -8,6 +8,7 @@ #include "flutter/display_list/types.h" #include "gtest/gtest.h" #include "include/core/SkPath.h" +#include "include/core/SkScalar.h" namespace flutter { namespace testing { @@ -44,6 +45,19 @@ TEST(DisplayListPathEffect, FromSkiaPathEffect) { ASSERT_EQ(dl_path_effect->asDash(), dl_path_effect.get()); ASSERT_TRUE( Equals(dl_path_effect, DlDashPathEffect::Make(TestDashes2, 2, 0.0))); + SkScalar s1[]{0.0, 0.0}; + SkPathEffect::DashInfo info1(s1, 2, 0); + sk_path_effect->asADash(&info1); + + SkScalar s2[]{0.0, 0.0}; + SkPathEffect::DashInfo info2(s2, 2, 0); + dl_path_effect->skia_object()->asADash(&info2); + // check interval values is equal + for (int i = 0; i < 2; i++) { + ASSERT_EQ(s1[i], s2[i]); + } + ASSERT_EQ(info1.fCount, info2.fCount); + ASSERT_EQ(info1.fPhase, info2.fPhase); } TEST(DisplayListPathEffect, EffectShared) { diff --git a/display_list/display_list_unittests.cc b/display_list/display_list_unittests.cc index 3d436c7cc8091..ca638e6193701 100644 --- a/display_list/display_list_unittests.cc +++ b/display_list/display_list_unittests.cc @@ -387,6 +387,7 @@ std::vector allGroups = { }, { "SetColorSource", { {0, 112, 0, 0, [](DisplayListBuilder& b) {b.setColorSource(&TestSource1);}}, + // stop_count * (sizeof(float) + sizeof(uint32_t)) = 80 {0, 80 + 6 * 4, 0, 0, [](DisplayListBuilder& b) {b.setColorSource(TestSource2.get());}}, {0, 80 + 6 * 4, 0, 0, [](DisplayListBuilder& b) {b.setColorSource(TestSource3.get());}}, {0, 88 + 6 * 4, 0, 0, [](DisplayListBuilder& b) {b.setColorSource(TestSource4.get());}}, @@ -428,8 +429,9 @@ std::vector allGroups = { } }, { "SetPathEffect", { - {0, 40, 0, 0, [](DisplayListBuilder& b) {b.setPathEffect(TestPathEffect1.get());}}, - {0, 40, 0, 0, [](DisplayListBuilder& b) {b.setPathEffect(TestPathEffect2.get());}}, + // 2 * sizeof(SkScalar) + {0, 32, 0, 0, [](DisplayListBuilder& b) {b.setPathEffect(TestPathEffect1.get());}}, + {0, 32, 0, 0, [](DisplayListBuilder& b) {b.setPathEffect(TestPathEffect2.get());}}, {0, 0, 0, 0, [](DisplayListBuilder& b) {b.setPathEffect(nullptr);}}, } }, From 42710b39abf1eab1d650dac5e8100f46dd15004f Mon Sep 17 00:00:00 2001 From: JsouLiang Date: Tue, 29 Mar 2022 10:33:45 +0800 Subject: [PATCH 07/17] Delete base_quals, check array equal first --- display_list/display_list_path_effect.h | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/display_list/display_list_path_effect.h b/display_list/display_list_path_effect.h index 073e40aabe719..04cac8250daf6 100644 --- a/display_list/display_list_path_effect.h +++ b/display_list/display_list_path_effect.h @@ -5,6 +5,7 @@ #ifndef FLUTTER_DISPLAY_LIST_DISPLAY_LIST_PATH_EFFECT_H_ #define FLUTTER_DISPLAY_LIST_DISPLAY_LIST_PATH_EFFECT_H_ +#include #include "flutter/display_list/display_list_attributes.h" #include "flutter/display_list/types.h" #include "flutter/fml/logging.h" @@ -95,8 +96,8 @@ class DlDashPathEffect final : public DlPathEffect { bool equals_(DlPathEffect const& other) const override { FML_DCHECK(other.type() == DlPathEffectType::kDash); auto that = static_cast(&other); - return count_ == that->count_ && base_equals_(that) && - phase_ == that->phase_; + return memcmp(pods(), that->pods(), count_) == 0 && + count_ == that->count_ && phase_ == that->phase_; } private: @@ -106,13 +107,7 @@ class DlDashPathEffect final : public DlPathEffect { bool base_equals_(DlDashPathEffect const* other) const { // intervals not nullptr, that has value - if (other != nullptr) { - for (int i = 0; i < count_; i++) { - if (pods()[i] != other->pods()[i]) { - return false; - } - } - } + return true; } From 40cbf6d8139da103bb705e32f5a0a845a3d162e5 Mon Sep 17 00:00:00 2001 From: JsouLiang Date: Thu, 31 Mar 2022 23:45:45 +0800 Subject: [PATCH 08/17] Change licenses file and deps --- ci/licenses_golden/licenses_flutter | 2 ++ display_list/display_list_dispatcher.h | 3 +- .../display_list_path_effect_unittests.cc | 36 +++++++++---------- 3 files changed, 19 insertions(+), 22 deletions(-) diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 4e896a581d904..39ecadb7ce65a 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -93,6 +93,8 @@ FILE: ../../../flutter/display_list/display_list_ops.h FILE: ../../../flutter/display_list/display_list_paint.cc FILE: ../../../flutter/display_list/display_list_paint.h FILE: ../../../flutter/display_list/display_list_paint_unittests.cc +FILE: ../../../flutter/display_list/display_list_path_effect.cc +FILE: ../../../flutter/display_list/display_list_path_effect.h FILE: ../../../flutter/display_list/display_list_test_utils.cc FILE: ../../../flutter/display_list/display_list_test_utils.h FILE: ../../../flutter/display_list/display_list_tile_mode.h diff --git a/display_list/display_list_dispatcher.h b/display_list/display_list_dispatcher.h index bcd950eb266f8..ce5ac2633ef4c 100644 --- a/display_list/display_list_dispatcher.h +++ b/display_list/display_list_dispatcher.h @@ -12,9 +12,8 @@ #include "flutter/display_list/display_list_image.h" #include "flutter/display_list/display_list_image_filter.h" #include "flutter/display_list/display_list_mask_filter.h" -#include "flutter/display_list/display_list_paint.h" -#include "flutter/display_list/display_list_vertices.h" #include "flutter/display_list/display_list_path_effect.h" +#include "flutter/display_list/display_list_vertices.h" namespace flutter { diff --git a/display_list/display_list_path_effect_unittests.cc b/display_list/display_list_path_effect_unittests.cc index a5dd151aaabfd..da12186a7e2e9 100644 --- a/display_list/display_list_path_effect_unittests.cc +++ b/display_list/display_list_path_effect_unittests.cc @@ -13,10 +13,8 @@ namespace flutter { namespace testing { -const SkScalar TestDashes1[] = {4.0, 2.0}; -const SkScalar TestDashes2[] = {1.0, 1.5}; - TEST(DisplayListPathEffect, BuilderSetGet) { + const SkScalar TestDashes1[] = {4.0, 2.0}; auto dash_path_effect = DlDashPathEffect::Make(TestDashes1, 2, 0.0); DisplayListBuilder builder; ASSERT_EQ(builder.getPathEffect(), nullptr); @@ -35,43 +33,32 @@ TEST(DisplayListPathEffect, FromSkiaNullPathEffect) { } TEST(DisplayListPathEffect, FromSkiaPathEffect) { + const SkScalar TestDashes2[] = {1.0, 1.5}; sk_sp sk_path_effect = SkDashPathEffect::Make(TestDashes2, 2, 0.0); std::shared_ptr dl_path_effect = DlPathEffect::From(sk_path_effect); ASSERT_EQ(dl_path_effect->type(), DlPathEffectType::kDash); - // We cannot recapture the dash parameters from an SkDashPathEffect - ASSERT_EQ(dl_path_effect->asDash(), dl_path_effect.get()); ASSERT_TRUE( Equals(dl_path_effect, DlDashPathEffect::Make(TestDashes2, 2, 0.0))); - SkScalar s1[]{0.0, 0.0}; - SkPathEffect::DashInfo info1(s1, 2, 0); - sk_path_effect->asADash(&info1); - - SkScalar s2[]{0.0, 0.0}; - SkPathEffect::DashInfo info2(s2, 2, 0); - dl_path_effect->skia_object()->asADash(&info2); - // check interval values is equal - for (int i = 0; i < 2; i++) { - ASSERT_EQ(s1[i], s2[i]); - } - ASSERT_EQ(info1.fCount, info2.fCount); - ASSERT_EQ(info1.fPhase, info2.fPhase); } TEST(DisplayListPathEffect, EffectShared) { + const SkScalar TestDashes2[] = {1.0, 1.5}; auto effect = DlDashPathEffect::Make(TestDashes2, 2, 0.0); ASSERT_TRUE(Equals(effect->shared(), effect)); } TEST(DisplayListPathEffect, DashEffectAsDash) { + const SkScalar TestDashes2[] = {1.0, 1.5}; auto effect = DlDashPathEffect::Make(TestDashes2, 2, 0.0); ASSERT_NE(effect->asDash(), nullptr); ASSERT_EQ(effect->asDash(), effect.get()); } TEST(DisplayListPathEffect, DashEffectEquals) { + const SkScalar TestDashes2[] = {1.0, 1.5}; auto effect1 = DlDashPathEffect::Make(TestDashes2, 2, 0.0); auto effect2 = DlDashPathEffect::Make(TestDashes2, 2, 0.0); ASSERT_TRUE(Equals(effect1, effect2)); @@ -79,9 +66,11 @@ TEST(DisplayListPathEffect, DashEffectEquals) { } TEST(DisplayListPathEffect, BlurNotEquals) { + const SkScalar TestDashes1[] = {4.0, 2.0}; + const SkScalar TestDashes2[] = {1.0, 1.5}; auto effect1 = DlDashPathEffect::Make(TestDashes1, 2, 0.0); auto effect2 = DlDashPathEffect::Make(TestDashes2, 2, 0.0); - auto effect3 = DlDashPathEffect::Make(TestDashes2, 3, 0.0); + auto effect3 = DlDashPathEffect::Make(TestDashes2, 2, 1.0); ASSERT_NE(effect1, effect2); ASSERT_NE(effect2, effect3); ASSERT_NE(effect1->shared(), effect2->shared()); @@ -89,16 +78,19 @@ TEST(DisplayListPathEffect, BlurNotEquals) { } TEST(DisplayListPathEffect, UnknownConstructor) { + const SkScalar TestDashes1[] = {4.0, 2.0}; DlUnknownPathEffect path_effect(SkDashPathEffect::Make(TestDashes1, 2, 0.0)); } TEST(DisplayListPathEffect, UnknownShared) { + const SkScalar TestDashes1[] = {4.0, 2.0}; DlUnknownPathEffect path_effect(SkDashPathEffect::Make(TestDashes1, 2, 0.0)); ASSERT_NE(path_effect.shared().get(), &path_effect); ASSERT_EQ(*path_effect.shared(), path_effect); } TEST(DisplayListPathEffect, UnknownContents) { + const SkScalar TestDashes1[] = {4.0, 2.0}; sk_sp sk_effect = SkDashPathEffect::Make(TestDashes1, 2, 0.0); DlUnknownPathEffect effect(sk_effect); ASSERT_EQ(effect.skia_object(), sk_effect); @@ -106,6 +98,7 @@ TEST(DisplayListPathEffect, UnknownContents) { } TEST(DisplayListPathEffect, UnknownEquals) { + const SkScalar TestDashes1[] = {4.0, 2.0}; sk_sp sk_effect = SkDashPathEffect::Make(TestDashes1, 2, 0.0); DlUnknownPathEffect effect1(sk_effect); DlUnknownPathEffect effect2(sk_effect); @@ -113,6 +106,7 @@ TEST(DisplayListPathEffect, UnknownEquals) { } TEST(DisplayListPathEffect, UnknownNotEquals) { + const SkScalar TestDashes1[] = {4.0, 2.0}; // Even though the effect is the same, it is a different instance // and we cannot currently tell them apart because the Skia // DashEffect::Make objects do not implement == @@ -173,9 +167,11 @@ void testNotEquals(std::shared_ptr a, } TEST(DisplayListPathEffect, ComparableTemplates) { + const SkScalar TestDashes1[] = {4.0, 2.0}; + const SkScalar TestDashes2[] = {1.0, 1.5}; auto effect1 = DlDashPathEffect::Make(TestDashes1, 2, 0.0); auto effect2 = DlDashPathEffect::Make(TestDashes1, 2, 0.0); - auto effect3 = DlDashPathEffect::Make(TestDashes2, 3, 0.0); + auto effect3 = DlDashPathEffect::Make(TestDashes2, 2, 1.0); std::shared_ptr shared_null; // null to null From 4e99e8140e6c5c4a46eeb249eb8602ff0bba43df Mon Sep 17 00:00:00 2001 From: JsouLiang Date: Fri, 1 Apr 2022 14:43:49 +0800 Subject: [PATCH 09/17] Add effect_bounds for DlPathEffect; Delete invalid test cases; --- display_list/display_list.h | 1 + display_list/display_list_canvas_unittests.cc | 16 +-- display_list/display_list_flags.cc | 23 +++- display_list/display_list_flags.h | 22 +--- display_list/display_list_path_effect.cc | 21 +++- display_list/display_list_path_effect.h | 38 +++--- .../display_list_path_effect_unittests.cc | 113 ++---------------- display_list/display_list_unittests.cc | 10 +- display_list/display_list_utils.cc | 10 +- 9 files changed, 92 insertions(+), 162 deletions(-) diff --git a/display_list/display_list.h b/display_list/display_list.h index b61c1434edeb5..204a4d895364b 100644 --- a/display_list/display_list.h +++ b/display_list/display_list.h @@ -74,6 +74,7 @@ namespace flutter { \ V(SetBlender) \ V(ClearBlender) \ + \ V(SetSkPathEffect) \ V(SetPodPathEffect) \ V(ClearPathEffect) \ diff --git a/display_list/display_list_canvas_unittests.cc b/display_list/display_list_canvas_unittests.cc index fc3e5f13c52b0..99966bb2d0522 100644 --- a/display_list/display_list_canvas_unittests.cc +++ b/display_list/display_list_canvas_unittests.cc @@ -387,14 +387,12 @@ class TestParameters { NotEquals(ref_attr.getColorSource(), attr.getColorSource())) { return false; } - auto skia_path_effect = - attr.getPathEffect() ? attr.getPathEffect()->skia_object() : nullptr; + DisplayListSpecialGeometryFlags geo_flags = - flags_.WithPathEffect(skia_path_effect); + flags_.WithPathEffect(attr.getPathEffect().get()); if (flags_.applies_path_effect() && // ref_attr.getPathEffect() != attr.getPathEffect()) { - SkPathEffect::DashInfo info; - if (skia_path_effect->asADash(&info) != SkPathEffect::kDash_DashType) { + if (attr.getPathEffect()->asDash() == nullptr) { return false; } if (!ignores_dashes()) { @@ -485,8 +483,10 @@ class TestParameters { adjust = half_width * paint.getStrokeMiter() + tolerance.discrete_offset(); } + auto paint_effect = paint.refPathEffect(); + DisplayListSpecialGeometryFlags geo_flags = - flags_.WithPathEffect(paint.refPathEffect()); + flags_.WithPathEffect(DlPathEffect::From(paint.refPathEffect()).get()); if (paint.getStrokeCap() == SkPaint::kButt_Cap && !geo_flags.butt_cap_becomes_square()) { adjust = std::max(adjust, half_width); @@ -1524,8 +1524,6 @@ class CanvasCompareTester { b.setPathEffect(effect.get()); })); } - EXPECT_TRUE(testP.is_draw_text_blob() || effect->skia_object()->unique()) - << "PathEffect == Dash-29-2 Cleanup"; effect = DlDashPathEffect::Make(TestDashes2, 2, 0.0f); { RenderWith(testP, stroke_base_env, tolerance, @@ -1546,8 +1544,6 @@ class CanvasCompareTester { b.setPathEffect(effect.get()); })); } - EXPECT_TRUE(testP.is_draw_text_blob() || effect->skia_object()->unique()) - << "PathEffect == Dash-17-1.5 Cleanup"; } } diff --git a/display_list/display_list_flags.cc b/display_list/display_list_flags.cc index 36ed9ea48d871..2b0a9d9043c2d 100644 --- a/display_list/display_list_flags.cc +++ b/display_list/display_list_flags.cc @@ -3,9 +3,28 @@ // found in the LICENSE file. #include "flutter/display_list/display_list_flags.h" - +#include "flutter/display_list/display_list_path_effect.h" namespace flutter { -// Just exists to ensure that the header can be cleanly imported. +const DisplayListSpecialGeometryFlags DisplayListAttributeFlags::WithPathEffect( + const DlPathEffect* effect) const { + if (is_geometric() && effect) { + if (effect->asDash()) { + // A dash effect has a very simple impact. It cannot introduce any + // miter joins that weren't already present in the original path + // and it does not grow the bounds of the path, but it can add + // end caps to areas that might not have had them before so all + // we need to do is to indicate the potential for diagonal + // end caps and move on. + return special_flags_.with(kMayHaveCaps_ | kMayHaveDiagonalCaps_); + } else { + // An arbitrary path effect can introduce joins at an arbitrary + // angle and may change the geometry of the end caps + return special_flags_.with(kMayHaveCaps_ | kMayHaveDiagonalCaps_ | + kMayHaveJoins_ | kMayHaveAcuteJoins_); + } + } + return special_flags_; +} } // namespace flutter diff --git a/display_list/display_list_flags.h b/display_list/display_list_flags.h index 568be0aa47ce3..f5362599c3b93 100644 --- a/display_list/display_list_flags.h +++ b/display_list/display_list_flags.h @@ -11,6 +11,7 @@ namespace flutter { +class DlPathEffect; /// The base class for the classes that maintain a list of /// attributes that might be important for a number of operations /// including which rendering attributes need to be set before @@ -159,26 +160,7 @@ class DisplayListSpecialGeometryFlags : DisplayListFlagsBase { class DisplayListAttributeFlags : DisplayListFlagsBase { public: const DisplayListSpecialGeometryFlags WithPathEffect( - sk_sp effect) const { - if (is_geometric() && effect) { - SkPathEffect::DashInfo info; - if (effect->asADash(&info) == SkPathEffect::kDash_DashType) { - // A dash effect has a very simple impact. It cannot introduce any - // miter joins that weren't already present in the original path - // and it does not grow the bounds of the path, but it can add - // end caps to areas that might not have had them before so all - // we need to do is to indicate the potential for diagonal - // end caps and move on. - return special_flags_.with(kMayHaveCaps_ | kMayHaveDiagonalCaps_); - } else { - // An arbitrary path effect can introduce joins at an arbitrary - // angle and may change the geometry of the end caps - return special_flags_.with(kMayHaveCaps_ | kMayHaveDiagonalCaps_ | - kMayHaveJoins_ | kMayHaveAcuteJoins_); - } - } - return special_flags_; - } + const DlPathEffect* effect) const; bool ignores_paint() const { return has_any(kIgnoresPaint_); } diff --git a/display_list/display_list_path_effect.cc b/display_list/display_list_path_effect.cc index 358183f398cd6..d087fd5c8aca3 100644 --- a/display_list/display_list_path_effect.cc +++ b/display_list/display_list_path_effect.cc @@ -5,6 +5,7 @@ #include "flutter/display_list/display_list_path_effect.h" #include +#include #include #include "include/core/SkRefCnt.h" @@ -30,7 +31,7 @@ std::shared_ptr DlPathEffect::From(SkPathEffect* sk_path_effect) { if (SkPathEffect::DashType::kDash_DashType == sk_path_effect->asADash(&info)) { auto dash_path_effect = - DlDashPathEffect::Make(info.fIntervals, info.fCount, info.fPhase); + DlDashPathEffect::Make(nullptr, info.fCount, info.fPhase); info.fIntervals = reinterpret_cast(dash_path_effect.get()) ->intervals(); @@ -53,4 +54,22 @@ std::shared_ptr DlDashPathEffect::Make(const SkScalar* intervals, return std::move(ret); } +std::optional DlDashPathEffect::effect_bounds(SkRect& rect) const { + // SkDashPathEffect's computeFastBounds is return true which mean it bounds is + // the input value; + return rect; +} + +std::optional DlUnknownPathEffect::effect_bounds(SkRect& rect) const { + if (rect.isSorted()) { + return std::nullopt; + } + SkPaint p; + p.setPathEffect(sk_path_effect_); + if (!p.canComputeFastBounds()) { + return std::nullopt; + } + return p.computeFastBounds(rect, &rect); +} + } // namespace flutter diff --git a/display_list/display_list_path_effect.h b/display_list/display_list_path_effect.h index 04cac8250daf6..df92981738390 100644 --- a/display_list/display_list_path_effect.h +++ b/display_list/display_list_path_effect.h @@ -6,6 +6,7 @@ #define FLUTTER_DISPLAY_LIST_DISPLAY_LIST_PATH_EFFECT_H_ #include +#include #include "flutter/display_list/display_list_attributes.h" #include "flutter/display_list/types.h" #include "flutter/fml/logging.h" @@ -41,6 +42,8 @@ class DlPathEffect virtual const DlDashPathEffect* asDash() const { return nullptr; } + virtual std::optional effect_bounds(SkRect&) const = 0; + protected: DlPathEffect() = default; @@ -81,36 +84,36 @@ class DlDashPathEffect final : public DlPathEffect { } std::shared_ptr shared() const override { - return Make(pods(), count_, phase_); + return Make(intervals(), count_, phase_); } const DlDashPathEffect* asDash() const override { return this; } sk_sp skia_object() const override { - return SkDashPathEffect::Make(pods(), count_, phase_); + return SkDashPathEffect::Make(intervals(), count_, phase_); } - SkScalar* intervals() { return reinterpret_cast(this + 1); } + const SkScalar* intervals() const { + return reinterpret_cast(this + 1); + } + + std::optional effect_bounds(SkRect& rect) const override; protected: bool equals_(DlPathEffect const& other) const override { FML_DCHECK(other.type() == DlPathEffectType::kDash); auto that = static_cast(&other); - return memcmp(pods(), that->pods(), count_) == 0 && - count_ == that->count_ && phase_ == that->phase_; + return count_ == that->count_ && + memcmp(intervals(), that->intervals(), sizeof(SkScalar) * count_) == + 0 && + phase_ == that->phase_; } private: - const SkScalar* pods() const { - return reinterpret_cast(this + 1); - } - - bool base_equals_(DlDashPathEffect const* other) const { - // intervals not nullptr, that has value - - return true; - } - + SkScalar* intervals() { return reinterpret_cast(this + 1); } + // DlDashPathEffect constructor assumes the caller has prealloced storage for + // the intervals. If the intervals is nullptr the intervals will + // uninitialized. DlDashPathEffect(const SkScalar intervals[], int count, SkScalar phase) : count_(count), phase_(phase) { if (intervals != nullptr) { @@ -120,7 +123,7 @@ class DlDashPathEffect final : public DlPathEffect { } DlDashPathEffect(const DlDashPathEffect* dash_effect) - : DlDashPathEffect(dash_effect->pods(), + : DlDashPathEffect(dash_effect->intervals(), dash_effect->count_, dash_effect->phase_) {} @@ -128,6 +131,7 @@ class DlDashPathEffect final : public DlPathEffect { SkScalar phase_; friend class DisplayListBuilder; + friend class DlPathEffect; FML_DISALLOW_COPY_ASSIGN_AND_MOVE(DlDashPathEffect); }; @@ -152,6 +156,8 @@ class DlUnknownPathEffect final : public DlPathEffect { virtual ~DlUnknownPathEffect() = default; + std::optional effect_bounds(SkRect& rect) const override; + protected: bool equals_(const DlPathEffect& other) const override { FML_DCHECK(other.type() == DlPathEffectType::kUnknown); diff --git a/display_list/display_list_path_effect_unittests.cc b/display_list/display_list_path_effect_unittests.cc index da12186a7e2e9..1ed408a414ac4 100644 --- a/display_list/display_list_path_effect_unittests.cc +++ b/display_list/display_list_path_effect_unittests.cc @@ -68,12 +68,18 @@ TEST(DisplayListPathEffect, DashEffectEquals) { TEST(DisplayListPathEffect, BlurNotEquals) { const SkScalar TestDashes1[] = {4.0, 2.0}; const SkScalar TestDashes2[] = {1.0, 1.5}; + const SkScalar TestDashes3[] = {4.0, 2.5, 2.0}; auto effect1 = DlDashPathEffect::Make(TestDashes1, 2, 0.0); auto effect2 = DlDashPathEffect::Make(TestDashes2, 2, 0.0); - auto effect3 = DlDashPathEffect::Make(TestDashes2, 2, 1.0); + auto effect3 = DlDashPathEffect::Make(TestDashes3, 3, 1.0); + ASSERT_NE(effect1, effect2); - ASSERT_NE(effect2, effect3); ASSERT_NE(effect1->shared(), effect2->shared()); + + ASSERT_NE(effect1, effect3); + ASSERT_NE(effect1->shared(), effect3->shared()); + + ASSERT_NE(effect2, effect3); ASSERT_NE(effect2->shared(), effect3->shared()); } @@ -116,108 +122,5 @@ TEST(DisplayListPathEffect, UnknownNotEquals) { "SkDashPathEffect instance differs"); } -void testEquals(DlPathEffect* a, DlPathEffect* b) { - // a and b have the same nullness or values - ASSERT_TRUE(Equals(a, b)); - ASSERT_FALSE(NotEquals(a, b)); - ASSERT_TRUE(Equals(b, a)); - ASSERT_FALSE(NotEquals(b, a)); -} - -void testNotEquals(DlPathEffect* a, DlPathEffect* b) { - // a and b do not have the same nullness or values - ASSERT_FALSE(Equals(a, b)); - ASSERT_TRUE(NotEquals(a, b)); - ASSERT_FALSE(Equals(b, a)); - ASSERT_TRUE(NotEquals(b, a)); -} - -void testEquals(std::shared_ptr a, DlPathEffect* b) { - // a and b have the same nullness or values - ASSERT_TRUE(Equals(a, b)); - ASSERT_FALSE(NotEquals(a, b)); - ASSERT_TRUE(Equals(b, a)); - ASSERT_FALSE(NotEquals(b, a)); -} - -void testNotEquals(std::shared_ptr a, DlPathEffect* b) { - // a and b do not have the same nullness or values - ASSERT_FALSE(Equals(a, b)); - ASSERT_TRUE(NotEquals(a, b)); - ASSERT_FALSE(Equals(b, a)); - ASSERT_TRUE(NotEquals(b, a)); -} - -void testEquals(std::shared_ptr a, - std::shared_ptr b) { - // a and b have the same nullness or values - ASSERT_TRUE(Equals(a, b)); - ASSERT_FALSE(NotEquals(a, b)); - ASSERT_TRUE(Equals(b, a)); - ASSERT_FALSE(NotEquals(b, a)); -} - -void testNotEquals(std::shared_ptr a, - std::shared_ptr b) { - // a and b do not have the same nullness or values - ASSERT_FALSE(Equals(a, b)); - ASSERT_TRUE(NotEquals(a, b)); - ASSERT_FALSE(Equals(b, a)); - ASSERT_TRUE(NotEquals(b, a)); -} - -TEST(DisplayListPathEffect, ComparableTemplates) { - const SkScalar TestDashes1[] = {4.0, 2.0}; - const SkScalar TestDashes2[] = {1.0, 1.5}; - auto effect1 = DlDashPathEffect::Make(TestDashes1, 2, 0.0); - auto effect2 = DlDashPathEffect::Make(TestDashes1, 2, 0.0); - auto effect3 = DlDashPathEffect::Make(TestDashes2, 2, 1.0); - std::shared_ptr shared_null; - - // null to null - testEquals(nullptr, nullptr); - testEquals(shared_null, nullptr); - testEquals(shared_null, shared_null); - - // ptr to null - testNotEquals(effect1.get(), nullptr); - testNotEquals(effect2.get(), nullptr); - testNotEquals(effect3.get(), nullptr); - - // shared_ptr to null and shared_null to ptr - testNotEquals(effect1->shared(), nullptr); - testNotEquals(effect2->shared(), nullptr); - testNotEquals(effect3->shared(), nullptr); - testNotEquals(shared_null, effect1.get()); - testNotEquals(shared_null, effect2.get()); - testNotEquals(shared_null, effect3.get()); - - // ptr to ptr - testEquals(effect1, effect1); - testEquals(effect1, effect2); - testEquals(effect3, effect3); - testEquals(effect2, effect2); - - // shared_ptr to ptr - testEquals(effect1->shared(), effect1); - testEquals(effect1->shared(), effect2); - testEquals(effect2->shared(), effect2); - testEquals(effect3->shared(), effect3); - testNotEquals(effect1->shared(), effect3); - testNotEquals(effect2->shared(), effect3); - testNotEquals(effect3->shared(), effect1); - testNotEquals(effect3->shared(), effect2); - - // shared_ptr to shared_ptr - testEquals(effect1->shared(), effect1->shared()); - testEquals(effect1->shared(), effect2->shared()); - testEquals(effect2->shared(), effect2->shared()); - testEquals(effect3->shared(), effect3->shared()); - testNotEquals(effect1->shared(), effect3->shared()); - testNotEquals(effect2->shared(), effect3->shared()); - testNotEquals(effect3->shared(), effect1->shared()); - testNotEquals(effect3->shared(), effect2->shared()); -} - } // namespace testing } // namespace flutter diff --git a/display_list/display_list_unittests.cc b/display_list/display_list_unittests.cc index ca638e6193701..e1d2624f43b02 100644 --- a/display_list/display_list_unittests.cc +++ b/display_list/display_list_unittests.cc @@ -429,8 +429,14 @@ std::vector allGroups = { } }, { "SetPathEffect", { - // 2 * sizeof(SkScalar) - {0, 32, 0, 0, [](DisplayListBuilder& b) {b.setPathEffect(TestPathEffect1.get());}}, + // sizeof(DlDashPathEffect) + 2 * sizeof(SkScalar) + {0, 32, 0, 0, [](DisplayListBuilder& b) { + auto size = TestPathEffect2->size(); + if (size > 0) { + + } + b.setPathEffect(TestPathEffect1.get()); + }}, {0, 32, 0, 0, [](DisplayListBuilder& b) {b.setPathEffect(TestPathEffect2.get());}}, {0, 0, 0, 0, [](DisplayListBuilder& b) {b.setPathEffect(nullptr);}}, } diff --git a/display_list/display_list_utils.cc b/display_list/display_list_utils.cc index dc5c3183445c0..3d74a87873a52 100644 --- a/display_list/display_list_utils.cc +++ b/display_list/display_list_utils.cc @@ -578,17 +578,15 @@ bool DisplayListBoundsCalculator::AdjustBoundsForPaint( } if (flags.is_geometric()) { - auto sk_path_effect = path_effect_ ? path_effect_->skia_object() : nullptr; // Path effect occurs before stroking... DisplayListSpecialGeometryFlags special_flags = - flags.WithPathEffect(sk_path_effect); + flags.WithPathEffect(path_effect_.get()); if (path_effect_) { - SkPaint p; - p.setPathEffect(sk_path_effect); - if (!p.canComputeFastBounds()) { + auto effect_bounds = path_effect_->effect_bounds(bounds); + if (!effect_bounds.has_value()) { return false; } - bounds = p.computeFastBounds(bounds, &bounds); + bounds = effect_bounds.value(); } if (flags.is_stroked(style_)) { From 48c36d25dce850240ecff95c512f47deee878841 Mon Sep 17 00:00:00 2001 From: JsouLiang Date: Thu, 7 Apr 2022 23:20:57 +0800 Subject: [PATCH 10/17] Change the intervals API; fix the DlUnknownPathEffect::effect_bounds bug; update test cases --- display_list/display_list_path_effect.cc | 4 +-- display_list/display_list_path_effect.h | 8 +++--- .../display_list_path_effect_unittests.cc | 28 +++++++++---------- 3 files changed, 19 insertions(+), 21 deletions(-) diff --git a/display_list/display_list_path_effect.cc b/display_list/display_list_path_effect.cc index d087fd5c8aca3..713a3eb98be6d 100644 --- a/display_list/display_list_path_effect.cc +++ b/display_list/display_list_path_effect.cc @@ -34,7 +34,7 @@ std::shared_ptr DlPathEffect::From(SkPathEffect* sk_path_effect) { DlDashPathEffect::Make(nullptr, info.fCount, info.fPhase); info.fIntervals = reinterpret_cast(dash_path_effect.get()) - ->intervals(); + ->intervals_unsafe(); sk_path_effect->asADash(&info); return dash_path_effect; } @@ -61,7 +61,7 @@ std::optional DlDashPathEffect::effect_bounds(SkRect& rect) const { } std::optional DlUnknownPathEffect::effect_bounds(SkRect& rect) const { - if (rect.isSorted()) { + if (!rect.isSorted()) { return std::nullopt; } SkPaint p; diff --git a/display_list/display_list_path_effect.h b/display_list/display_list_path_effect.h index df92981738390..447ac0f0413fb 100644 --- a/display_list/display_list_path_effect.h +++ b/display_list/display_list_path_effect.h @@ -103,14 +103,12 @@ class DlDashPathEffect final : public DlPathEffect { bool equals_(DlPathEffect const& other) const override { FML_DCHECK(other.type() == DlPathEffectType::kDash); auto that = static_cast(&other); - return count_ == that->count_ && + return count_ == that->count_ && phase_ == that->phase_ && memcmp(intervals(), that->intervals(), sizeof(SkScalar) * count_) == - 0 && - phase_ == that->phase_; + 0; } private: - SkScalar* intervals() { return reinterpret_cast(this + 1); } // DlDashPathEffect constructor assumes the caller has prealloced storage for // the intervals. If the intervals is nullptr the intervals will // uninitialized. @@ -127,6 +125,8 @@ class DlDashPathEffect final : public DlPathEffect { dash_effect->count_, dash_effect->phase_) {} + SkScalar* intervals_unsafe() { return reinterpret_cast(this + 1); } + int count_; SkScalar phase_; diff --git a/display_list/display_list_path_effect_unittests.cc b/display_list/display_list_path_effect_unittests.cc index 1ed408a414ac4..91501ecf873e3 100644 --- a/display_list/display_list_path_effect_unittests.cc +++ b/display_list/display_list_path_effect_unittests.cc @@ -61,26 +61,24 @@ TEST(DisplayListPathEffect, DashEffectEquals) { const SkScalar TestDashes2[] = {1.0, 1.5}; auto effect1 = DlDashPathEffect::Make(TestDashes2, 2, 0.0); auto effect2 = DlDashPathEffect::Make(TestDashes2, 2, 0.0); - ASSERT_TRUE(Equals(effect1, effect2)); - ASSERT_TRUE(Equals(effect1->shared(), effect2->shared())); + TestEquals(*effect1, *effect1); } -TEST(DisplayListPathEffect, BlurNotEquals) { +TEST(DisplayListPathEffect, CheckEffectProperties) { const SkScalar TestDashes1[] = {4.0, 2.0}; - const SkScalar TestDashes2[] = {1.0, 1.5}; - const SkScalar TestDashes3[] = {4.0, 2.5, 2.0}; + const SkScalar TestDashes2[] = {5.0, 2.0}; + const SkScalar TestDashes3[] = {4.0, 3.0}; + const SkScalar TestDashes4[] = {4.0, 2.0, 6.0}; auto effect1 = DlDashPathEffect::Make(TestDashes1, 2, 0.0); auto effect2 = DlDashPathEffect::Make(TestDashes2, 2, 0.0); - auto effect3 = DlDashPathEffect::Make(TestDashes3, 3, 1.0); - - ASSERT_NE(effect1, effect2); - ASSERT_NE(effect1->shared(), effect2->shared()); - - ASSERT_NE(effect1, effect3); - ASSERT_NE(effect1->shared(), effect3->shared()); - - ASSERT_NE(effect2, effect3); - ASSERT_NE(effect2->shared(), effect3->shared()); + auto effect3 = DlDashPathEffect::Make(TestDashes3, 2, 0.0); + auto effect4 = DlDashPathEffect::Make(TestDashes4, 3, 0.0); + auto effect5 = DlDashPathEffect::Make(TestDashes1, 2, 1.0); + + TestNotEquals(*effect1, *effect2, "Interval 1 differs"); + TestNotEquals(*effect1, *effect3, "Interval 2 differs"); + TestNotEquals(*effect1, *effect4, "Dash count differs"); + TestNotEquals(*effect1, *effect5, "Dash phase differs"); } TEST(DisplayListPathEffect, UnknownConstructor) { From d62c7442ef99c475b1d57d9d3551a430df49983f Mon Sep 17 00:00:00 2001 From: JsouLiang Date: Fri, 15 Apr 2022 10:24:36 +0800 Subject: [PATCH 11/17] fix some suggests of comments --- display_list/display_list_path_effect.cc | 4 ++-- display_list/display_list_path_effect.h | 10 +++++----- display_list/display_list_unittests.cc | 4 ---- 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/display_list/display_list_path_effect.cc b/display_list/display_list_path_effect.cc index 713a3eb98be6d..72297464e4f15 100644 --- a/display_list/display_list_path_effect.cc +++ b/display_list/display_list_path_effect.cc @@ -55,8 +55,8 @@ std::shared_ptr DlDashPathEffect::Make(const SkScalar* intervals, } std::optional DlDashPathEffect::effect_bounds(SkRect& rect) const { - // SkDashPathEffect's computeFastBounds is return true which mean it bounds is - // the input value; + // SkDashPathEffect returns the original bounds as the bounds of the effect + // since the dashed path will always be a subset of the original. return rect; } diff --git a/display_list/display_list_path_effect.h b/display_list/display_list_path_effect.h index 447ac0f0413fb..a6d2f02361df3 100644 --- a/display_list/display_list_path_effect.h +++ b/display_list/display_list_path_effect.h @@ -51,15 +51,15 @@ class DlPathEffect FML_DISALLOW_COPY_ASSIGN_AND_MOVE(DlPathEffect); }; -/// The DashPathEffect which specifies modifying the path effect, and it -/// only affects storked paths. +/// The DashPathEffect which breaks a path up into dash segments, and it +/// only affects stroked paths. /// intervals: array containing an even number of entries (>=2), with /// the even indices specifying the length of "on" intervals, and the odd /// indices specifying the length of "off" intervals. This array will be /// copied in Make, and can be disposed of freely after. -/// count: number of elements in the intervals array -/// phase: offset into the intervals array (mod the sum of all of the -/// intervals). +/// count: number of elements in the intervals array. +/// phase: initial distance into the intervals at which to start the dashing +/// effect for the path. /// /// For example: if intervals[] = {10, 20}, count = 2, and phase = 25, /// this will set up a dashed path like so: diff --git a/display_list/display_list_unittests.cc b/display_list/display_list_unittests.cc index e1d2624f43b02..64bf63c5d1590 100644 --- a/display_list/display_list_unittests.cc +++ b/display_list/display_list_unittests.cc @@ -431,10 +431,6 @@ std::vector allGroups = { { "SetPathEffect", { // sizeof(DlDashPathEffect) + 2 * sizeof(SkScalar) {0, 32, 0, 0, [](DisplayListBuilder& b) { - auto size = TestPathEffect2->size(); - if (size > 0) { - - } b.setPathEffect(TestPathEffect1.get()); }}, {0, 32, 0, 0, [](DisplayListBuilder& b) {b.setPathEffect(TestPathEffect2.get());}}, From 254893de7c387c9252590ff6c4c5e65287d90cd1 Mon Sep 17 00:00:00 2001 From: JsouLiang <1129584401@qq.com> Date: Sat, 16 Apr 2022 10:34:42 +0800 Subject: [PATCH 12/17] Change SetPathEffect one line like the others --- display_list/display_list_unittests.cc | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/display_list/display_list_unittests.cc b/display_list/display_list_unittests.cc index 64bf63c5d1590..320a40ee528f6 100644 --- a/display_list/display_list_unittests.cc +++ b/display_list/display_list_unittests.cc @@ -430,9 +430,7 @@ std::vector allGroups = { }, { "SetPathEffect", { // sizeof(DlDashPathEffect) + 2 * sizeof(SkScalar) - {0, 32, 0, 0, [](DisplayListBuilder& b) { - b.setPathEffect(TestPathEffect1.get()); - }}, + {0, 32, 0, 0, [](DisplayListBuilder& b) {b.setPathEffect(TestPathEffect1.get());}}, {0, 32, 0, 0, [](DisplayListBuilder& b) {b.setPathEffect(TestPathEffect2.get());}}, {0, 0, 0, 0, [](DisplayListBuilder& b) {b.setPathEffect(nullptr);}}, } From 81c2dcba6c4e96528b602657a52ac5463771e27c Mon Sep 17 00:00:00 2001 From: JsouLiang Date: Fri, 22 Apr 2022 13:49:26 +0800 Subject: [PATCH 13/17] Change the DisplayListStreamDispatcher::setBlendMode api --- testing/display_list_testing.cc | 2 +- testing/display_list_testing.h | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/testing/display_list_testing.cc b/testing/display_list_testing.cc index b9ca0b1e05ae5..ed8b19b014deb 100644 --- a/testing/display_list_testing.cc +++ b/testing/display_list_testing.cc @@ -479,7 +479,7 @@ void DisplayListStreamDispatcher::setBlendMode(DlBlendMode mode) { void DisplayListStreamDispatcher::setBlender(sk_sp blender) { startl() << "setBlender(" << blender << ");" << std::endl; } -void DisplayListStreamDispatcher::setPathEffect(sk_sp effect) { +void DisplayListStreamDispatcher::setPathEffect(const DlPathEffect* effect) { startl() << "setPathEffect(" << effect << ");" << std::endl; } void DisplayListStreamDispatcher::setMaskFilter(const DlMaskFilter* filter) { diff --git a/testing/display_list_testing.h b/testing/display_list_testing.h index 34a0ce1189e15..cadc7c6e8fc66 100644 --- a/testing/display_list_testing.h +++ b/testing/display_list_testing.h @@ -9,6 +9,7 @@ #include "flutter/display_list/display_list.h" #include "flutter/display_list/display_list_dispatcher.h" +#include "flutter/display_list/display_list_path_effect.h" namespace flutter { namespace testing { @@ -53,7 +54,7 @@ class DisplayListStreamDispatcher final : public Dispatcher { void setInvertColors(bool invert) override; void setBlendMode(DlBlendMode mode) override; void setBlender(sk_sp blender) override; - void setPathEffect(sk_sp effect) override; + void setPathEffect(const DlPathEffect* effect) override; void setMaskFilter(const DlMaskFilter* filter) override; void setImageFilter(const DlImageFilter* filter) override; From 8da47576612547bbcf575160ac38f2322fea5628 Mon Sep 17 00:00:00 2001 From: JsouLiang Date: Sat, 23 Apr 2022 12:31:23 +0800 Subject: [PATCH 14/17] Delete licenses --- ci/licenses_golden/licenses_flutter | 1 + 1 file changed, 1 insertion(+) diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 39ecadb7ce65a..de7c844209f76 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -95,6 +95,7 @@ FILE: ../../../flutter/display_list/display_list_paint.h FILE: ../../../flutter/display_list/display_list_paint_unittests.cc FILE: ../../../flutter/display_list/display_list_path_effect.cc FILE: ../../../flutter/display_list/display_list_path_effect.h +FILE: ../../../flutter/display_list/display_list_path_effect_unittests.cc FILE: ../../../flutter/display_list/display_list_test_utils.cc FILE: ../../../flutter/display_list/display_list_test_utils.h FILE: ../../../flutter/display_list/display_list_tile_mode.h From 0d2a0216d0c99432c6a24f2c769f55e28de1fdcd Mon Sep 17 00:00:00 2001 From: JsouLiang Date: Thu, 28 Apr 2022 14:04:40 +0800 Subject: [PATCH 15/17] change the display_list_dispatcher setPathEffect api --- display_list/BUILD.gn | 2 +- impeller/display_list/display_list_dispatcher.cc | 3 ++- impeller/display_list/display_list_dispatcher.h | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/display_list/BUILD.gn b/display_list/BUILD.gn index ea809d6d87073..eb2692869df83 100644 --- a/display_list/BUILD.gn +++ b/display_list/BUILD.gn @@ -93,10 +93,10 @@ if (enable_unittests) { "display_list_color_unittests.cc", "display_list_complexity_unittests.cc", "display_list_enum_unittests.cc", - "display_list_path_effect_unittests.cc", "display_list_image_filter_unittests.cc", "display_list_mask_filter_unittests.cc", "display_list_paint_unittests.cc", + "display_list_path_effect_unittests.cc", "display_list_unittests.cc", "display_list_vertices_unittests.cc", ] diff --git a/impeller/display_list/display_list_dispatcher.cc b/impeller/display_list/display_list_dispatcher.cc index b29ba0f850eca..017359b1fb211 100644 --- a/impeller/display_list/display_list_dispatcher.cc +++ b/impeller/display_list/display_list_dispatcher.cc @@ -6,6 +6,7 @@ #include +#include "display_list/display_list_path_effect.h" #include "flutter/fml/trace_event.h" #include "impeller/entity/contents/filters/filter_contents.h" #include "impeller/entity/contents/linear_gradient_contents.h" @@ -249,7 +250,7 @@ void DisplayListDispatcher::setBlender(sk_sp blender) { } // |flutter::Dispatcher| -void DisplayListDispatcher::setPathEffect(sk_sp effect) { +void DisplayListDispatcher::setPathEffect(const flutter::DlPathEffect* effect) { // Needs https://github.com/flutter/flutter/issues/95434 UNIMPLEMENTED; } diff --git a/impeller/display_list/display_list_dispatcher.h b/impeller/display_list/display_list_dispatcher.h index fd51545aadbe5..cf5864671d431 100644 --- a/impeller/display_list/display_list_dispatcher.h +++ b/impeller/display_list/display_list_dispatcher.h @@ -4,6 +4,7 @@ #pragma once +#include "display_list/display_list_path_effect.h" #include "flutter/display_list/display_list.h" #include "flutter/display_list/display_list_blend_mode.h" #include "flutter/display_list/display_list_dispatcher.h" @@ -61,7 +62,7 @@ class DisplayListDispatcher final : public flutter::Dispatcher { void setBlender(sk_sp blender) override; // |flutter::Dispatcher| - void setPathEffect(sk_sp effect) override; + void setPathEffect(const flutter::DlPathEffect* effect) override; // |flutter::Dispatcher| void setMaskFilter(const flutter::DlMaskFilter* filter) override; From 938ca8217dd1314f831fa85d70f6137289594c97 Mon Sep 17 00:00:00 2001 From: JsouLiang Date: Fri, 29 Apr 2022 11:46:41 +0800 Subject: [PATCH 16/17] Update Licenses --- ci/licenses_golden/licenses_flutter | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index de7c844209f76..96cdbaaa8b0ae 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -496,6 +496,8 @@ FILE: ../../../flutter/impeller/entity/contents/filters/border_mask_blur_filter_ FILE: ../../../flutter/impeller/entity/contents/filters/border_mask_blur_filter_contents.h FILE: ../../../flutter/impeller/entity/contents/filters/filter_contents.cc FILE: ../../../flutter/impeller/entity/contents/filters/filter_contents.h +FILE: ../../../flutter/impeller/entity/contents/filters/filter_input.cc +FILE: ../../../flutter/impeller/entity/contents/filters/filter_input.h FILE: ../../../flutter/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc FILE: ../../../flutter/impeller/entity/contents/filters/gaussian_blur_filter_contents.h FILE: ../../../flutter/impeller/entity/contents/filters/inputs/contents_filter_input.cc From 563d368949b22de4c7fd31512bead22588803961 Mon Sep 17 00:00:00 2001 From: JsouLiang Date: Mon, 9 May 2022 20:35:46 +0800 Subject: [PATCH 17/17] fix conflict --- ci/licenses_golden/licenses_flutter | 2 - display_list/display_list_builder.cc | 6 +- display_list/display_list_builder.h | 6 +- display_list/display_list_dispatcher.h | 1 + display_list/display_list_paint.h | 13 +- impeller/LICENSE | 25 --- .../entity/contents/filters/filter_input.cc | 158 ------------------ .../entity/contents/filters/filter_input.h | 153 ----------------- 8 files changed, 19 insertions(+), 345 deletions(-) delete mode 100644 impeller/LICENSE delete mode 100644 impeller/entity/contents/filters/filter_input.cc delete mode 100644 impeller/entity/contents/filters/filter_input.h diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 96cdbaaa8b0ae..de7c844209f76 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -496,8 +496,6 @@ FILE: ../../../flutter/impeller/entity/contents/filters/border_mask_blur_filter_ FILE: ../../../flutter/impeller/entity/contents/filters/border_mask_blur_filter_contents.h FILE: ../../../flutter/impeller/entity/contents/filters/filter_contents.cc FILE: ../../../flutter/impeller/entity/contents/filters/filter_contents.h -FILE: ../../../flutter/impeller/entity/contents/filters/filter_input.cc -FILE: ../../../flutter/impeller/entity/contents/filters/filter_input.h FILE: ../../../flutter/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc FILE: ../../../flutter/impeller/entity/contents/filters/gaussian_blur_filter_contents.h FILE: ../../../flutter/impeller/entity/contents/filters/inputs/contents_filter_input.cc diff --git a/display_list/display_list_builder.cc b/display_list/display_list_builder.cc index 3c0d03f26e10e..96aacead6684b 100644 --- a/display_list/display_list_builder.cc +++ b/display_list/display_list_builder.cc @@ -277,11 +277,11 @@ void DisplayListBuilder::onSetColorFilter(const DlColorFilter* filter) { } void DisplayListBuilder::onSetPathEffect(const DlPathEffect* effect) { if (effect == nullptr) { - current_path_effect_ = nullptr; + current_.setPathEffect(nullptr); Push(0, 0); } else { - current_path_effect_ = effect->shared(); - switch (current_path_effect_->type()) { + current_.setPathEffect(effect->shared()); + switch (effect->type()) { case DlPathEffectType::kDash: { const DlDashPathEffect* dash_effect = effect->asDash(); void* pod = Push(dash_effect->size(), 0); diff --git a/display_list/display_list_builder.h b/display_list/display_list_builder.h index 0e4778b3fd6b3..49b085d648f10 100644 --- a/display_list/display_list_builder.h +++ b/display_list/display_list_builder.h @@ -12,6 +12,7 @@ #include "flutter/display_list/display_list_flags.h" #include "flutter/display_list/display_list_image.h" #include "flutter/display_list/display_list_paint.h" +#include "flutter/display_list/display_list_path_effect.h" #include "flutter/display_list/types.h" #include "flutter/fml/macros.h" @@ -103,7 +104,7 @@ class DisplayListBuilder final : public virtual Dispatcher, } } void setPathEffect(const DlPathEffect* effect) override { - if (NotEquals(current_path_effect_, effect)) { + if (NotEquals(current_.getPathEffect(), effect)) { onSetPathEffect(effect); } } @@ -140,7 +141,7 @@ class DisplayListBuilder final : public virtual Dispatcher, : SkBlender::Mode(ToSk(current_.getBlendMode())); } std::shared_ptr getPathEffect() const { - return current_path_effect_; + return current_.getPathEffect(); } std::shared_ptr getMaskFilter() const { return current_.getMaskFilter(); @@ -462,7 +463,6 @@ class DisplayListBuilder final : public virtual Dispatcher, DlPaint current_; // If |current_blender_| is set then ignore |current_.getBlendMode()| sk_sp current_blender_; - sk_sp current_path_effect_; }; } // namespace flutter diff --git a/display_list/display_list_dispatcher.h b/display_list/display_list_dispatcher.h index ce5ac2633ef4c..c12fd90467f04 100644 --- a/display_list/display_list_dispatcher.h +++ b/display_list/display_list_dispatcher.h @@ -12,6 +12,7 @@ #include "flutter/display_list/display_list_image.h" #include "flutter/display_list/display_list_image_filter.h" #include "flutter/display_list/display_list_mask_filter.h" +#include "flutter/display_list/display_list_paint.h" #include "flutter/display_list/display_list_path_effect.h" #include "flutter/display_list/display_list_vertices.h" diff --git a/display_list/display_list_paint.h b/display_list/display_list_paint.h index 47a5b5fee23db..2892d13685633 100644 --- a/display_list/display_list_paint.h +++ b/display_list/display_list_paint.h @@ -5,12 +5,14 @@ #ifndef FLUTTER_DISPLAY_LIST_DISPLAY_LIST_PAINT_H_ #define FLUTTER_DISPLAY_LIST_DISPLAY_LIST_PAINT_H_ +#include #include "flutter/display_list/display_list_blend_mode.h" #include "flutter/display_list/display_list_color.h" #include "flutter/display_list/display_list_color_filter.h" #include "flutter/display_list/display_list_color_source.h" #include "flutter/display_list/display_list_image_filter.h" #include "flutter/display_list/display_list_mask_filter.h" +#include "flutter/display_list/display_list_path_effect.h" namespace flutter { @@ -199,6 +201,15 @@ class DlPaint { return *this; } + std::shared_ptr getPathEffect() const { + return pathEffect_; + } + const DlPathEffect* getPathEffectPtr() const { return pathEffect_.get(); } + DlPaint& setPathEffect(std::shared_ptr pathEffect) { + pathEffect_ = pathEffect; + return *this; + } + bool operator==(DlPaint const& other) const; bool operator!=(DlPaint const& other) const { return !(*this == other); } @@ -236,8 +247,8 @@ class DlPaint { std::shared_ptr colorFilter_; std::shared_ptr imageFilter_; std::shared_ptr maskFilter_; + std::shared_ptr pathEffect_; // missing (as compared to SkPaint): - // DlPathEffect - waiting for https://github.com/flutter/engine/pull/32159 // DlBlender - not planning on using that object in a pure DisplayList world }; diff --git a/impeller/LICENSE b/impeller/LICENSE deleted file mode 100644 index c6823b81eb845..0000000000000 --- a/impeller/LICENSE +++ /dev/null @@ -1,25 +0,0 @@ -Copyright 2013 The Flutter Authors. All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - * Neither the name of Google Inc. nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/impeller/entity/contents/filters/filter_input.cc b/impeller/entity/contents/filters/filter_input.cc deleted file mode 100644 index 6719886467e0c..0000000000000 --- a/impeller/entity/contents/filters/filter_input.cc +++ /dev/null @@ -1,158 +0,0 @@ -// 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 "impeller/entity/contents/filters/filter_input.h" - -#include -#include -#include -#include -#include - -#include "fml/logging.h" -#include "impeller/entity/contents/filters/filter_contents.h" -#include "impeller/entity/contents/snapshot.h" -#include "impeller/entity/entity.h" - -namespace impeller { - -/******************************************************************************* - ******* FilterInput - ******************************************************************************/ - -FilterInput::Ref FilterInput::Make(Variant input) { - if (auto filter = std::get_if>(&input)) { - return std::static_pointer_cast( - std::shared_ptr( - new FilterContentsFilterInput(*filter))); - } - - if (auto contents = std::get_if>(&input)) { - return std::static_pointer_cast( - std::shared_ptr( - new ContentsFilterInput(*contents))); - } - - if (auto texture = std::get_if>(&input)) { - return std::static_pointer_cast( - std::shared_ptr(new TextureFilterInput(*texture))); - } - - FML_UNREACHABLE(); -} - -FilterInput::Vector FilterInput::Make(std::initializer_list inputs) { - FilterInput::Vector result; - result.reserve(inputs.size()); - for (const auto& input : inputs) { - result.push_back(Make(input)); - } - return result; -} - -Matrix FilterInput::GetLocalTransform(const Entity& entity) const { - return Matrix(); -} - -Matrix FilterInput::GetTransform(const Entity& entity) const { - return entity.GetTransformation() * GetLocalTransform(entity); -} - -FilterInput::~FilterInput() = default; - -/******************************************************************************* - ******* FilterContentsFilterInput - ******************************************************************************/ - -FilterContentsFilterInput::FilterContentsFilterInput( - std::shared_ptr filter) - : filter_(filter) {} - -FilterContentsFilterInput::~FilterContentsFilterInput() = default; - -FilterInput::Variant FilterContentsFilterInput::GetInput() const { - return filter_; -} - -std::optional FilterContentsFilterInput::GetSnapshot( - const ContentContext& renderer, - const Entity& entity) const { - if (!snapshot_.has_value()) { - snapshot_ = filter_->RenderToSnapshot(renderer, entity); - } - return snapshot_; -} - -std::optional FilterContentsFilterInput::GetCoverage( - const Entity& entity) const { - return filter_->GetCoverage(entity); -} - -Matrix FilterContentsFilterInput::GetLocalTransform( - const Entity& entity) const { - return filter_->GetLocalTransform(); -} - -Matrix FilterContentsFilterInput::GetTransform(const Entity& entity) const { - return filter_->GetTransform(entity.GetTransformation()); -} - -/******************************************************************************* - ******* ContentsFilterInput - ******************************************************************************/ - -ContentsFilterInput::ContentsFilterInput(std::shared_ptr contents) - : contents_(contents) {} - -ContentsFilterInput::~ContentsFilterInput() = default; - -FilterInput::Variant ContentsFilterInput::GetInput() const { - return contents_; -} - -std::optional ContentsFilterInput::GetSnapshot( - const ContentContext& renderer, - const Entity& entity) const { - if (!snapshot_.has_value()) { - snapshot_ = contents_->RenderToSnapshot(renderer, entity); - } - return snapshot_; -} - -std::optional ContentsFilterInput::GetCoverage( - const Entity& entity) const { - return contents_->GetCoverage(entity); -} - -/******************************************************************************* - ******* TextureFilterInput - ******************************************************************************/ - -TextureFilterInput::TextureFilterInput(std::shared_ptr texture) - : texture_(texture) {} - -TextureFilterInput::~TextureFilterInput() = default; - -FilterInput::Variant TextureFilterInput::GetInput() const { - return texture_; -} - -std::optional TextureFilterInput::GetSnapshot( - const ContentContext& renderer, - const Entity& entity) const { - return Snapshot{.texture = texture_, .transform = GetTransform(entity)}; -} - -std::optional TextureFilterInput::GetCoverage( - const Entity& entity) const { - return Rect::MakeSize(Size(texture_->GetSize())) - .TransformBounds(GetTransform(entity)); -} - -Matrix TextureFilterInput::GetLocalTransform(const Entity& entity) const { - // Compute the local transform such that the texture is centered. - return Matrix::MakeTranslation(-Point(texture_->GetSize()) / 2); -} - -} // namespace impeller diff --git a/impeller/entity/contents/filters/filter_input.h b/impeller/entity/contents/filters/filter_input.h deleted file mode 100644 index dd1f907a6df70..0000000000000 --- a/impeller/entity/contents/filters/filter_input.h +++ /dev/null @@ -1,153 +0,0 @@ -// 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. - -#pragma once - -#include -#include -#include -#include - -#include "impeller/entity/contents/contents.h" -#include "impeller/geometry/rect.h" -#include "impeller/renderer/formats.h" - -namespace impeller { - -class ContentContext; -class Entity; -class FilterContents; - -/******************************************************************************* - ******* FilterInput - ******************************************************************************/ - -/// `FilterInput` is a lazy/single eval `Snapshot` which may be shared across -/// filter parameters and used to evaluate input coverage. -/// -/// A `FilterInput` can be re-used for any filter inputs across an entity's -/// filter graph without repeating subpasses unnecessarily. -/// -/// Filters may decide to not evaluate inputs in situations where they won't -/// contribute to the filter's output texture. -class FilterInput { - public: - using Ref = std::shared_ptr; - using Vector = std::vector; - using Variant = std::variant, - std::shared_ptr, - std::shared_ptr>; - - virtual ~FilterInput(); - - static FilterInput::Ref Make(Variant input); - - static FilterInput::Vector Make(std::initializer_list inputs); - - virtual Variant GetInput() const = 0; - - virtual std::optional GetSnapshot(const ContentContext& renderer, - const Entity& entity) const = 0; - - virtual std::optional GetCoverage(const Entity& entity) const = 0; - - /// @brief Get the local transform of this filter input. This transform is - /// relative to the `Entity` transform space. - virtual Matrix GetLocalTransform(const Entity& entity) const; - - /// @brief Get the transform of this `FilterInput`. This is equivalent to - /// calling `entity.GetTransformation() * GetLocalTransform()`. - virtual Matrix GetTransform(const Entity& entity) const; -}; - -/******************************************************************************* - ******* FilterContentsFilterInput - ******************************************************************************/ - -class FilterContentsFilterInput final : public FilterInput { - public: - ~FilterContentsFilterInput() override; - - // |FilterInput| - Variant GetInput() const override; - - // |FilterInput| - std::optional GetSnapshot(const ContentContext& renderer, - const Entity& entity) const override; - - // |FilterInput| - std::optional GetCoverage(const Entity& entity) const override; - - // |FilterInput| - Matrix GetLocalTransform(const Entity& entity) const override; - - // |FilterInput| - Matrix GetTransform(const Entity& entity) const override; - - private: - FilterContentsFilterInput(std::shared_ptr filter); - - std::shared_ptr filter_; - mutable std::optional snapshot_; - - friend FilterInput; -}; - -/******************************************************************************* - ******* ContentsFilterInput - ******************************************************************************/ - -class ContentsFilterInput final : public FilterInput { - public: - ~ContentsFilterInput() override; - - // |FilterInput| - Variant GetInput() const override; - - // |FilterInput| - std::optional GetSnapshot(const ContentContext& renderer, - const Entity& entity) const override; - - // |FilterInput| - std::optional GetCoverage(const Entity& entity) const override; - - private: - ContentsFilterInput(std::shared_ptr contents); - - std::shared_ptr contents_; - mutable std::optional snapshot_; - - friend FilterInput; -}; - -/******************************************************************************* - ******* TextureFilterInput - ******************************************************************************/ - -class TextureFilterInput final : public FilterInput { - public: - ~TextureFilterInput() override; - - // |FilterInput| - Variant GetInput() const override; - - // |FilterInput| - std::optional GetSnapshot(const ContentContext& renderer, - const Entity& entity) const override; - - // |FilterInput| - std::optional GetCoverage(const Entity& entity) const override; - - // |FilterInput| - Matrix GetLocalTransform(const Entity& entity) const override; - - private: - TextureFilterInput(std::shared_ptr texture); - - std::shared_ptr texture_; - - friend FilterInput; -}; - -} // namespace impeller