diff --git a/flow/display_list.cc b/flow/display_list.cc index 1390a161f90e5..b219c4f4c7de3 100644 --- a/flow/display_list.cc +++ b/flow/display_list.cc @@ -205,6 +205,7 @@ DEFINE_SET_CLEAR_SKREF_OP(Shader, shader) DEFINE_SET_CLEAR_SKREF_OP(ImageFilter, filter) DEFINE_SET_CLEAR_SKREF_OP(ColorFilter, filter) DEFINE_SET_CLEAR_SKREF_OP(MaskFilter, filter) +DEFINE_SET_CLEAR_SKREF_OP(PathEffect, effect) #undef DEFINE_SET_CLEAR_SKREF_OP // 4 byte header + 4 byte payload packs into minimum 8 bytes @@ -1089,6 +1090,11 @@ void DisplayListBuilder::setColorFilter(sk_sp filter) { ? Push(0, std::move(filter)) : Push(0); } +void DisplayListBuilder::setPathEffect(sk_sp effect) { + effect // + ? Push(0, std::move(effect)) + : Push(0); +} void DisplayListBuilder::setMaskFilter(sk_sp filter) { Push(0, std::move(filter)); } diff --git a/flow/display_list.h b/flow/display_list.h index 7fde2a8480728..bbfafa7a50810 100644 --- a/flow/display_list.h +++ b/flow/display_list.h @@ -10,6 +10,7 @@ #include "third_party/skia/include/core/SkColorFilter.h" #include "third_party/skia/include/core/SkImage.h" #include "third_party/skia/include/core/SkImageFilter.h" +#include "third_party/skia/include/core/SkPathEffect.h" #include "third_party/skia/include/core/SkPicture.h" #include "third_party/skia/include/core/SkShader.h" #include "third_party/skia/include/core/SkVertices.h" @@ -84,6 +85,8 @@ namespace flutter { V(ClearColorFilter) \ V(SetImageFilter) \ V(ClearImageFilter) \ + V(SetPathEffect) \ + V(ClearPathEffect) \ \ V(ClearMaskFilter) \ V(SetMaskFilter) \ @@ -230,10 +233,11 @@ class Dispatcher { virtual void setColor(SkColor color) = 0; virtual void setBlendMode(SkBlendMode mode) = 0; virtual void setFilterQuality(SkFilterQuality quality) = 0; - virtual void setShader(const sk_sp shader) = 0; - virtual void setImageFilter(const sk_sp filter) = 0; - virtual void setColorFilter(const sk_sp filter) = 0; - virtual void setMaskFilter(const sk_sp filter) = 0; + virtual void setShader(sk_sp shader) = 0; + virtual void setImageFilter(sk_sp filter) = 0; + virtual void setColorFilter(sk_sp filter) = 0; + virtual void setPathEffect(sk_sp effect) = 0; + virtual void setMaskFilter(sk_sp filter) = 0; virtual void setMaskBlurFilter(SkBlurStyle style, SkScalar sigma) = 0; virtual void save() = 0; @@ -344,6 +348,7 @@ class DisplayListBuilder final : public virtual Dispatcher, public SkRefCnt { void setShader(sk_sp shader) override; void setImageFilter(sk_sp filter) override; void setColorFilter(sk_sp filter) override; + void setPathEffect(sk_sp effect) override; void setMaskFilter(sk_sp filter) override; void setMaskBlurFilter(SkBlurStyle style, SkScalar sigma) override; diff --git a/flow/display_list_canvas.cc b/flow/display_list_canvas.cc index c6070df8b198a..d97325aab7eda 100644 --- a/flow/display_list_canvas.cc +++ b/flow/display_list_canvas.cc @@ -471,6 +471,11 @@ void DisplayListCanvasRecorder::RecordPaintAttributes(const SkPaint* paint, builder_->setImageFilter(current_image_filter_ = sk_ref_sp(paint->getImageFilter())); } + if ((dataNeeded & kPathEffectNeeded_) != 0 && + current_path_effect_.get() != paint->getPathEffect()) { + builder_->setPathEffect(current_path_effect_ = + sk_ref_sp(paint->getPathEffect())); + } if ((dataNeeded & kMaskFilterNeeded_) != 0 && current_mask_filter_.get() != paint->getMaskFilter()) { builder_->setMaskFilter(current_mask_filter_ = diff --git a/flow/display_list_canvas.h b/flow/display_list_canvas.h index da535a7d26635..c2234104a28e5 100644 --- a/flow/display_list_canvas.h +++ b/flow/display_list_canvas.h @@ -265,8 +265,9 @@ class DisplayListCanvasRecorder static constexpr int kShaderNeeded_ = 1 << 7; static constexpr int kColorFilterNeeded_ = 1 << 8; static constexpr int kImageFilterNeeded_ = 1 << 9; - static constexpr int kMaskFilterNeeded_ = 1 << 10; - static constexpr int kDitherNeeded_ = 1 << 11; + static constexpr int kPathEffectNeeded_ = 1 << 10; + static constexpr int kMaskFilterNeeded_ = 1 << 11; + static constexpr int kDitherNeeded_ = 1 << 12; // clang-format on // Combinations of the above mask bits that are common to typical "draw" @@ -278,10 +279,10 @@ class DisplayListCanvasRecorder kBlendNeeded_ | kInvertColorsNeeded_ | kColorFilterNeeded_ | kShaderNeeded_ | kDitherNeeded_ | kImageFilterNeeded_; - static constexpr int kDrawMask_ = - kPaintMask_ | kPaintStyleNeeded_ | kMaskFilterNeeded_; - static constexpr int kStrokeMask_ = - kPaintMask_ | kStrokeStyleNeeded_ | kMaskFilterNeeded_; + static constexpr int kDrawMask_ = kPaintMask_ | kPaintStyleNeeded_ | + kMaskFilterNeeded_ | kPathEffectNeeded_; + static constexpr int kStrokeMask_ = kPaintMask_ | kStrokeStyleNeeded_ | + kMaskFilterNeeded_ | kPathEffectNeeded_; static constexpr int kImageMask_ = kColorNeeded_ | kBlendNeeded_ | kInvertColorsNeeded_ | kColorFilterNeeded_ | kDitherNeeded_ | kImageFilterNeeded_ | @@ -304,6 +305,7 @@ class DisplayListCanvasRecorder sk_sp current_shader_; sk_sp current_color_filter_; sk_sp current_image_filter_; + sk_sp current_path_effect_; sk_sp current_mask_filter_; }; diff --git a/flow/display_list_canvas_unittests.cc b/flow/display_list_canvas_unittests.cc index cd2f6ff88e620..148ef428b4e79 100644 --- a/flow/display_list_canvas_unittests.cc +++ b/flow/display_list_canvas_unittests.cc @@ -14,6 +14,8 @@ #include "third_party/skia/include/core/SkSurface.h" #include "third_party/skia/include/core/SkTextBlob.h" #include "third_party/skia/include/core/SkVertices.h" +#include "third_party/skia/include/effects/SkDashPathEffect.h" +#include "third_party/skia/include/effects/SkDiscretePathEffect.h" #include "third_party/skia/include/effects/SkGradientShader.h" #include "third_party/skia/include/effects/SkImageFilters.h" @@ -173,6 +175,14 @@ class CanvasCompareTester { cv_renderer, dl_renderer, "ImageFilter == Decal Blur 5"); } ASSERT_TRUE(filter->unique()) << "ImageFilter Cleanup"; + filter = + SkImageFilters::Blur(5.0, 5.0, SkTileMode::kClamp, nullptr, nullptr); + { + RenderWith([=](SkCanvas*, SkPaint& p) { p.setImageFilter(filter); }, + [=](DisplayListBuilder& b) { b.setImageFilter(filter); }, + cv_renderer, dl_renderer, "ImageFilter == Clamp Blur 5"); + } + ASSERT_TRUE(filter->unique()) << "ImageFilter Cleanup"; } { @@ -222,6 +232,41 @@ class CanvasCompareTester { ASSERT_TRUE(filter->unique()) << "ColorFilter Cleanup"; } + { + // Discrete path effects need a stroke width for drawPointsAsPoints + // to do something realistic + sk_sp effect = SkDiscretePathEffect::Make(3, 5); + { + // Discrete path effects need a stroke width for drawPointsAsPoints + // to do something realistic + RenderWith( + [=](SkCanvas*, SkPaint& p) { + p.setStrokeWidth(5.0); + p.setPathEffect(effect); + }, + [=](DisplayListBuilder& b) { + b.setStrokeWidth(5.0); + b.setPathEffect(effect); + }, + cv_renderer, dl_renderer, "PathEffect == Discrete-3-5"); + } + ASSERT_TRUE(effect->unique()) << "PathEffect Cleanup"; + effect = SkDiscretePathEffect::Make(2, 3); + { + RenderWith( + [=](SkCanvas*, SkPaint& p) { + p.setStrokeWidth(5.0); + p.setPathEffect(effect); + }, + [=](DisplayListBuilder& b) { + b.setStrokeWidth(5.0); + b.setPathEffect(effect); + }, + cv_renderer, dl_renderer, "PathEffect == Discrete-2-3"); + } + ASSERT_TRUE(effect->unique()) << "PathEffect Cleanup"; + } + { sk_sp filter = SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, 5.0); @@ -389,6 +434,43 @@ class CanvasCompareTester { b.setJoins(SkPaint::kMiter_Join); }, cv_renderer, dl_renderer, "Stroke Width 5, Miter 0"); + + { + const SkScalar TestDashes1[] = {4.0, 2.0}; + const SkScalar TestDashes2[] = {1.0, 1.5}; + sk_sp effect = SkDashPathEffect::Make(TestDashes1, 2, 0.0f); + { + RenderWith( + [=](SkCanvas*, SkPaint& p) { + p.setStyle(SkPaint::kStroke_Style); + p.setStrokeWidth(5.0); + p.setPathEffect(effect); + }, + [=](DisplayListBuilder& b) { + b.setDrawStyle(SkPaint::kStroke_Style); + b.setStrokeWidth(5.0); + b.setPathEffect(effect); + }, + cv_renderer, dl_renderer, "PathEffect == Dash-4-2"); + } + ASSERT_TRUE(effect->unique()) << "PathEffect Cleanup"; + effect = SkDashPathEffect::Make(TestDashes2, 2, 0.0f); + { + RenderWith( + [=](SkCanvas*, SkPaint& p) { + p.setStyle(SkPaint::kStroke_Style); + p.setStrokeWidth(5.0); + p.setPathEffect(effect); + }, + [=](DisplayListBuilder& b) { + b.setDrawStyle(SkPaint::kStroke_Style); + b.setStrokeWidth(5.0); + b.setPathEffect(effect); + }, + cv_renderer, dl_renderer, "PathEffect == Dash-1-1.5"); + } + ASSERT_TRUE(effect->unique()) << "PathEffect Cleanup"; + } } static void RenderWithTransforms(CvRenderer& cv_renderer, @@ -862,7 +944,9 @@ TEST(DisplayListCanvas, DrawPointsAsPoints) { const int count = sizeof(points) / sizeof(points[0]); CanvasCompareTester::RenderAll( [=](SkCanvas* canvas, SkPaint& paint) { // - canvas->drawPoints(SkCanvas::kPoints_PointMode, count, points, paint); + SkPaint p = paint; + p.setStyle(SkPaint::kStroke_Style); + canvas->drawPoints(SkCanvas::kPoints_PointMode, count, points, p); }, [=](DisplayListBuilder& builder) { // builder.drawPoints(SkCanvas::kPoints_PointMode, count, points); @@ -901,7 +985,9 @@ TEST(DisplayListCanvas, DrawPointsAsLines) { ASSERT_TRUE((count & 1) == 0); CanvasCompareTester::RenderAll( [=](SkCanvas* canvas, SkPaint& paint) { // - canvas->drawPoints(SkCanvas::kLines_PointMode, count, points, paint); + SkPaint p = paint; + p.setStyle(SkPaint::kStroke_Style); + canvas->drawPoints(SkCanvas::kLines_PointMode, count, points, p); }, [=](DisplayListBuilder& builder) { // builder.drawPoints(SkCanvas::kLines_PointMode, count, points); @@ -918,7 +1004,9 @@ TEST(DisplayListCanvas, DrawPointsAsPolygon) { }; CanvasCompareTester::RenderAll( [=](SkCanvas* canvas, SkPaint& paint) { // - canvas->drawPoints(SkCanvas::kPolygon_PointMode, 4, points, paint); + SkPaint p = paint; + p.setStyle(SkPaint::kStroke_Style); + canvas->drawPoints(SkCanvas::kPolygon_PointMode, 4, points, p); }, [=](DisplayListBuilder& builder) { // builder.drawPoints(SkCanvas::kPolygon_PointMode, 4, points); diff --git a/flow/display_list_unittests.cc b/flow/display_list_unittests.cc index eae1815eb047f..738a7d7147a1f 100644 --- a/flow/display_list_unittests.cc +++ b/flow/display_list_unittests.cc @@ -14,6 +14,7 @@ #include "third_party/skia/include/core/SkSurface.h" #include "third_party/skia/include/core/SkTextBlob.h" #include "third_party/skia/include/core/SkVertices.h" +#include "third_party/skia/include/effects/SkDashPathEffect.h" #include "third_party/skia/include/effects/SkGradientShader.h" #include "third_party/skia/include/effects/SkImageFilters.h" @@ -38,12 +39,24 @@ constexpr float stops[] = { 0.5, 1.0, }; + +// clang-format off constexpr float rotate_color_matrix[20] = { - 0, 1, 0, 0, 0, // - 0, 0, 1, 0, 0, // - 1, 0, 0, 0, 0, // - 0, 0, 0, 1, 0, // + 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, + 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, +}; +constexpr float invert_color_matrix[20] = { + -1.0, 0, 0, 1.0, 0, + 0, -1.0, 0, 1.0, 0, + 0, 0, -1.0, 1.0, 0, + 1.0, 1.0, 1.0, 1.0, 0, }; +// clang-format on + +const SkScalar TestDashes1[] = {4.0, 2.0}; +const SkScalar TestDashes2[] = {1.0, 1.5}; constexpr SkPoint TestPoints[] = { {10, 10}, @@ -80,10 +93,18 @@ static const sk_sp TestShader3 = SkTileMode::kDecal, 0, nullptr); -static const sk_sp TestImageFilter = +static const sk_sp TestImageFilter1 = SkImageFilters::Blur(5.0, 5.0, SkTileMode::kDecal, nullptr, nullptr); -static const sk_sp TestColorFilter = +static const sk_sp TestImageFilter2 = + SkImageFilters::Blur(5.0, 5.0, SkTileMode::kClamp, nullptr, nullptr); +static const sk_sp TestColorFilter1 = SkColorFilters::Matrix(rotate_color_matrix); +static const sk_sp TestColorFilter2 = + SkColorFilters::Matrix(invert_color_matrix); +static const sk_sp TestPathEffect1 = + SkDashPathEffect::Make(TestDashes1, 2, 0.0f); +static const sk_sp TestPathEffect2 = + SkDashPathEffect::Make(TestDashes2, 2, 0.0f); static const sk_sp TestMaskFilter = SkMaskFilter::MakeBlur(kNormal_SkBlurStyle, 5.0); constexpr SkRect TestBounds = SkRect::MakeLTRB(10, 10, 50, 60); @@ -290,12 +311,20 @@ std::vector allGroups = { }, { "SetImageFilter", { {1, 8, 0, 0, [](DisplayListBuilder& b) {b.setImageFilter(nullptr);}}, - {1, 16, 0, 0, [](DisplayListBuilder& b) {b.setImageFilter(TestImageFilter);}}, + {1, 16, 0, 0, [](DisplayListBuilder& b) {b.setImageFilter(TestImageFilter1);}}, + {1, 16, 0, 0, [](DisplayListBuilder& b) {b.setImageFilter(TestImageFilter2);}}, } }, { "SetColorFilter", { {1, 8, 0, 0, [](DisplayListBuilder& b) {b.setColorFilter(nullptr);}}, - {1, 16, 0, 0, [](DisplayListBuilder& b) {b.setColorFilter(TestColorFilter);}}, + {1, 16, 0, 0, [](DisplayListBuilder& b) {b.setColorFilter(TestColorFilter1);}}, + {1, 16, 0, 0, [](DisplayListBuilder& b) {b.setColorFilter(TestColorFilter2);}}, + } + }, + { "SetPathEffect", { + {1, 8, 0, 0, [](DisplayListBuilder& b) {b.setPathEffect(nullptr);}}, + {1, 16, 0, 0, [](DisplayListBuilder& b) {b.setPathEffect(TestPathEffect1);}}, + {1, 16, 0, 0, [](DisplayListBuilder& b) {b.setPathEffect(TestPathEffect2);}}, } }, { "SetMaskFilter", { diff --git a/flow/display_list_utils.cc b/flow/display_list_utils.cc index 474435b94c992..b1c718e9c8bb1 100644 --- a/flow/display_list_utils.cc +++ b/flow/display_list_utils.cc @@ -70,6 +70,9 @@ void SkPaintDispatchHelper::setColorFilter(sk_sp filter) { color_filter_ = filter; paint_.setColorFilter(makeColorFilter()); } +void SkPaintDispatchHelper::setPathEffect(sk_sp effect) { + paint_.setPathEffect(effect); +} void SkPaintDispatchHelper::setMaskFilter(sk_sp filter) { paint_.setMaskFilter(filter); } diff --git a/flow/display_list_utils.h b/flow/display_list_utils.h index 68b9dc56b0120..95ae27c852a4d 100644 --- a/flow/display_list_utils.h +++ b/flow/display_list_utils.h @@ -53,6 +53,7 @@ class IngoreAttributeDispatchHelper : public virtual Dispatcher { void setShader(sk_sp shader) override {} void setImageFilter(sk_sp filter) override {} void setColorFilter(sk_sp filter) override {} + void setPathEffect(sk_sp effect) override {} void setMaskFilter(sk_sp filter) override {} void setMaskBlurFilter(SkBlurStyle style, SkScalar sigma) override {} }; @@ -109,6 +110,7 @@ class SkPaintDispatchHelper : public virtual Dispatcher { void setShader(sk_sp shader) override; void setImageFilter(sk_sp filter) override; void setColorFilter(sk_sp filter) override; + void setPathEffect(sk_sp effect) override; void setMaskFilter(sk_sp filter) override; void setMaskBlurFilter(SkBlurStyle style, SkScalar sigma) override;