1 /*
2 * Copyright 2019 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "SkSGRenderEffect.h"
9
10 #include "SkDropShadowImageFilter.h"
11 #include "SkMakeUnique.h"
12 #include "SkSGColor.h"
13
14 namespace sksg {
15
Make(sk_sp<RenderNode> child,sk_sp<ImageFilter> filter)16 sk_sp<RenderNode> ImageFilterEffect::Make(sk_sp<RenderNode> child, sk_sp<ImageFilter> filter) {
17 return filter ? sk_sp<RenderNode>(new ImageFilterEffect(std::move(child), std::move(filter)))
18 : child;
19 }
20
ImageFilterEffect(sk_sp<RenderNode> child,sk_sp<ImageFilter> filter)21 ImageFilterEffect::ImageFilterEffect(sk_sp<RenderNode> child, sk_sp<ImageFilter> filter)
22 // filters always override descendent damage
23 : INHERITED(std::move(child), kOverrideDamage_Trait)
24 , fImageFilter(std::move(filter)) {
25 this->observeInval(fImageFilter);
26 }
27
~ImageFilterEffect()28 ImageFilterEffect::~ImageFilterEffect() {
29 this->unobserveInval(fImageFilter);
30 }
31
onRevalidate(InvalidationController * ic,const SkMatrix & ctm)32 SkRect ImageFilterEffect::onRevalidate(InvalidationController* ic, const SkMatrix& ctm) {
33 // FIXME: image filter effects should replace the descendents' damage!
34 fImageFilter->revalidate(ic, ctm);
35
36 const auto& filter = fImageFilter->getFilter();
37 SkASSERT(!filter || filter->canComputeFastBounds());
38
39 const auto content_bounds = this->INHERITED::onRevalidate(ic, ctm);
40
41 return filter ? filter->computeFastBounds(content_bounds)
42 : content_bounds;
43 }
44
onNodeAt(const SkPoint & p) const45 const RenderNode* ImageFilterEffect::onNodeAt(const SkPoint& p) const {
46 // TODO: map p through the filter DAG and dispatch to descendants?
47 // For now, image filters occlude hit-testing.
48 SkASSERT(this->bounds().contains(p.x(), p.y()));
49 return this;
50 }
51
onRender(SkCanvas * canvas,const RenderContext * ctx) const52 void ImageFilterEffect::onRender(SkCanvas* canvas, const RenderContext* ctx) const {
53 // Note: we're using the source content bounds for saveLayer, not our local/filtered bounds.
54 const auto filter_ctx =
55 ScopedRenderContext(canvas, ctx).setFilterIsolation(this->getChild()->bounds(),
56 fImageFilter->getFilter());
57 this->INHERITED::onRender(canvas, filter_ctx);
58 }
59
ImageFilter(sk_sp<ImageFilter> input)60 ImageFilter::ImageFilter(sk_sp<ImageFilter> input)
61 : ImageFilter(input ? skstd::make_unique<InputsT>(1, std::move(input)) : nullptr) {}
62
ImageFilter(std::unique_ptr<InputsT> inputs)63 ImageFilter::ImageFilter(std::unique_ptr<InputsT> inputs)
64 : INHERITED(kBubbleDamage_Trait)
65 , fInputs(std::move(inputs)) {
66 if (fInputs) {
67 for (const auto& input : *fInputs) {
68 this->observeInval(input);
69 }
70 }
71 }
72
~ImageFilter()73 ImageFilter::~ImageFilter() {
74 if (fInputs) {
75 for (const auto& input : *fInputs) {
76 this->unobserveInval(input);
77 }
78 }
79 }
80
refInput(size_t i) const81 sk_sp<SkImageFilter> ImageFilter::refInput(size_t i) const {
82 return (fInputs && i < fInputs->size()) ? (*fInputs)[i]->getFilter() : nullptr;
83 }
84
onRevalidate(InvalidationController *,const SkMatrix &)85 SkRect ImageFilter::onRevalidate(InvalidationController*, const SkMatrix&) {
86 SkASSERT(this->hasInval());
87
88 fFilter = this->onRevalidateFilter();
89 return SkRect::MakeEmpty();
90 }
91
Make(sk_sp<ImageFilter> input)92 sk_sp<DropShadowImageFilter> DropShadowImageFilter::Make(sk_sp<ImageFilter> input) {
93 return sk_sp<DropShadowImageFilter>(new DropShadowImageFilter(std::move(input)));
94 }
95
DropShadowImageFilter(sk_sp<ImageFilter> input)96 DropShadowImageFilter::DropShadowImageFilter(sk_sp<ImageFilter> input)
97 : INHERITED(std::move(input)) {}
98
99 DropShadowImageFilter::~DropShadowImageFilter() = default;
100
onRevalidateFilter()101 sk_sp<SkImageFilter> DropShadowImageFilter::onRevalidateFilter() {
102 const auto mode = (fMode == Mode::kShadowOnly)
103 ? SkDropShadowImageFilter::kDrawShadowOnly_ShadowMode
104 : SkDropShadowImageFilter::kDrawShadowAndForeground_ShadowMode;
105
106 return SkDropShadowImageFilter::Make(fOffset.x(), fOffset.y(),
107 fSigma.x(), fSigma.y(),
108 fColor, mode, this->refInput(0));
109 }
110
Make(sk_sp<ImageFilter> input)111 sk_sp<BlurImageFilter> BlurImageFilter::Make(sk_sp<ImageFilter> input) {
112 return sk_sp<BlurImageFilter>(new BlurImageFilter(std::move(input)));
113 }
114
BlurImageFilter(sk_sp<ImageFilter> input)115 BlurImageFilter::BlurImageFilter(sk_sp<ImageFilter> input)
116 : INHERITED(std::move(input)) {}
117
118 BlurImageFilter::~BlurImageFilter() = default;
119
onRevalidateFilter()120 sk_sp<SkImageFilter> BlurImageFilter::onRevalidateFilter() {
121 return SkBlurImageFilter::Make(fSigma.x(), fSigma.y(), this->refInput(0), nullptr, fTileMode);
122 }
123
Make(sk_sp<RenderNode> child,SkBlendMode mode)124 sk_sp<BlendModeEffect> BlendModeEffect::Make(sk_sp<RenderNode> child, SkBlendMode mode) {
125 return child ? sk_sp<BlendModeEffect>(new BlendModeEffect(std::move(child), mode))
126 : nullptr;
127 }
128
BlendModeEffect(sk_sp<RenderNode> child,SkBlendMode mode)129 BlendModeEffect::BlendModeEffect(sk_sp<RenderNode> child, SkBlendMode mode)
130 : INHERITED(std::move(child))
131 , fMode(mode) {}
132
133 BlendModeEffect::~BlendModeEffect() = default;
134
onRender(SkCanvas * canvas,const RenderContext * ctx) const135 void BlendModeEffect::onRender(SkCanvas* canvas, const RenderContext* ctx) const {
136 const auto local_ctx = ScopedRenderContext(canvas, ctx).modulateBlendMode(fMode);
137
138 this->INHERITED::onRender(canvas, local_ctx);
139 }
140
onNodeAt(const SkPoint & p) const141 const RenderNode* BlendModeEffect::onNodeAt(const SkPoint& p) const {
142 // TODO: we likely need to do something more sophisticated than delegate to descendants here.
143 return this->INHERITED::onNodeAt(p);
144 }
145
146 } // namespace sksg
147