• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "modules/sksg/include/SkSGRenderEffect.h"
9 
10 #include "include/core/SkCanvas.h"
11 #include "include/core/SkMaskFilter.h"
12 #include "include/core/SkShader.h"
13 #include "src/core/SkMaskFilterBase.h"
14 
15 namespace sksg {
16 
MaskFilter(sk_sp<SkMaskFilter> mf)17 MaskFilter::MaskFilter(sk_sp<SkMaskFilter> mf)
18     : INHERITED(kBubbleDamage_Trait)
19     , fMaskFilter(std::move(mf)) {}
20 
21 MaskFilter::~MaskFilter() = default;
22 
setMaskFilter(sk_sp<SkMaskFilter> mf)23 void MaskFilter::setMaskFilter(sk_sp<SkMaskFilter> mf) {
24     if (mf != fMaskFilter) {
25         fMaskFilter = std::move(mf);
26         this->invalidate();
27     }
28 }
29 
onRevalidate(InvalidationController * ic,const SkMatrix & ctm)30 SkRect MaskFilter::onRevalidate(InvalidationController* ic, const SkMatrix& ctm) {
31     SkASSERT(this->hasInval());
32 
33     fMaskFilter = this->onRevalidateMask();
34     return SkRect::MakeEmpty();
35 }
36 
onRevalidateMask()37 sk_sp<SkMaskFilter> MaskFilter::onRevalidateMask() {
38     return fMaskFilter;
39 }
40 
Make(sk_sp<RenderNode> child,sk_sp<MaskFilter> mf)41 sk_sp<MaskFilterEffect> MaskFilterEffect::Make(sk_sp<RenderNode> child, sk_sp<MaskFilter> mf) {
42     return child ? sk_sp<MaskFilterEffect>(new MaskFilterEffect(std::move(child), std::move(mf)))
43                  : nullptr;
44 }
45 
MaskFilterEffect(sk_sp<RenderNode> child,sk_sp<MaskFilter> mf)46 MaskFilterEffect::MaskFilterEffect(sk_sp<RenderNode> child, sk_sp<MaskFilter> mf)
47     // masks may override descendent damage
48     : INHERITED(std::move(child), kOverrideDamage_Trait)
49     , fMaskFilter(std::move(mf)) {
50     this->observeInval(fMaskFilter);
51 }
52 
~MaskFilterEffect()53 MaskFilterEffect::~MaskFilterEffect() {
54     this->unobserveInval(fMaskFilter);
55 }
56 
onRevalidate(InvalidationController * ic,const SkMatrix & ctm)57 SkRect MaskFilterEffect::onRevalidate(InvalidationController* ic, const SkMatrix& ctm) {
58     auto bounds = this->INHERITED::onRevalidate(ic, ctm);
59 
60     if (fMaskFilter) {
61         fMaskFilter->revalidate(ic, ctm);
62         if (const auto* mfb = as_MFB(fMaskFilter->getMaskFilter())) {
63             mfb->computeFastBounds(bounds, &bounds);
64         }
65     }
66 
67     return bounds;
68 }
69 
onRender(SkCanvas * canvas,const RenderContext * ctx) const70 void MaskFilterEffect::onRender(SkCanvas* canvas, const RenderContext* ctx) const {
71     const auto local_ctx = ScopedRenderContext(canvas, ctx)
72             .modulateMaskFilter(fMaskFilter ? fMaskFilter->getMaskFilter() : nullptr,
73                                 canvas->getTotalMatrix());
74 
75     this->INHERITED::onRender(canvas, local_ctx);
76 }
77 
Make(sk_sp<RenderNode> child,sk_sp<Shader> shader)78 sk_sp<ShaderEffect> ShaderEffect::Make(sk_sp<RenderNode> child, sk_sp<Shader> shader) {
79     return child ? sk_sp<ShaderEffect>(new ShaderEffect(std::move(child), std::move(shader)))
80                  : nullptr;
81 }
82 
ShaderEffect(sk_sp<RenderNode> child,sk_sp<Shader> shader)83 ShaderEffect::ShaderEffect(sk_sp<RenderNode> child, sk_sp<Shader> shader)
84     : INHERITED(std::move(child))
85     , fShader(std::move(shader)) {
86     if (fShader) {
87         this->observeInval(fShader);
88     }
89 }
90 
~ShaderEffect()91 ShaderEffect::~ShaderEffect() {
92     if (fShader) {
93         this->unobserveInval(fShader);
94     }
95 }
96 
setShader(sk_sp<Shader> sh)97 void ShaderEffect::setShader(sk_sp<Shader> sh) {
98     if (fShader) {
99         this->unobserveInval(fShader);
100     }
101 
102     fShader = std::move(sh);
103 
104     if (fShader) {
105         this->observeInval(fShader);
106     }
107 }
onRevalidate(InvalidationController * ic,const SkMatrix & ctm)108 SkRect ShaderEffect::onRevalidate(InvalidationController* ic, const SkMatrix& ctm) {
109     if (fShader) {
110         fShader->revalidate(ic, ctm);
111     }
112 
113     return this->INHERITED::onRevalidate(ic, ctm);
114 }
115 
onRender(SkCanvas * canvas,const RenderContext * ctx) const116 void ShaderEffect::onRender(SkCanvas* canvas, const RenderContext* ctx) const {
117     const auto local_ctx = ScopedRenderContext(canvas, ctx)
118             .modulateShader(fShader ? fShader->getShader() : nullptr, canvas->getTotalMatrix());
119 
120     this->INHERITED::onRender(canvas, local_ctx);
121 }
122 
Shader()123 Shader::Shader() : INHERITED(kBubbleDamage_Trait) {}
124 
125 Shader::~Shader() = default;
126 
onRevalidate(InvalidationController *,const SkMatrix &)127 SkRect Shader::onRevalidate(InvalidationController*, const SkMatrix&) {
128     SkASSERT(this->hasInval());
129 
130     fShader = this->onRevalidateShader();
131     return SkRect::MakeEmpty();
132 }
133 
Make(sk_sp<RenderNode> child,sk_sp<ImageFilter> filter)134 sk_sp<RenderNode> ImageFilterEffect::Make(sk_sp<RenderNode> child, sk_sp<ImageFilter> filter) {
135     return filter ? sk_sp<RenderNode>(new ImageFilterEffect(std::move(child), std::move(filter)))
136                   : child;
137 }
138 
ImageFilterEffect(sk_sp<RenderNode> child,sk_sp<ImageFilter> filter)139 ImageFilterEffect::ImageFilterEffect(sk_sp<RenderNode> child, sk_sp<ImageFilter> filter)
140     // filters always override descendent damage
141     : INHERITED(std::move(child), kOverrideDamage_Trait)
142     , fImageFilter(std::move(filter)) {
143     this->observeInval(fImageFilter);
144 }
145 
~ImageFilterEffect()146 ImageFilterEffect::~ImageFilterEffect() {
147     this->unobserveInval(fImageFilter);
148 }
149 
onRevalidate(InvalidationController * ic,const SkMatrix & ctm)150 SkRect ImageFilterEffect::onRevalidate(InvalidationController* ic, const SkMatrix& ctm) {
151     // FIXME: image filter effects should replace the descendents' damage!
152     fImageFilter->revalidate(ic, ctm);
153 
154     const auto& filter = fImageFilter->getFilter();
155     SkASSERT(!filter || filter->canComputeFastBounds());
156 
157     const auto content_bounds = this->INHERITED::onRevalidate(ic, ctm);
158 
159     return filter ? filter->computeFastBounds(content_bounds)
160                   : content_bounds;
161 }
162 
onNodeAt(const SkPoint & p) const163 const RenderNode* ImageFilterEffect::onNodeAt(const SkPoint& p) const {
164     // TODO: map p through the filter DAG and dispatch to descendants?
165     // For now, image filters occlude hit-testing.
166     SkASSERT(this->bounds().contains(p.x(), p.y()));
167     return this;
168 }
169 
onRender(SkCanvas * canvas,const RenderContext * ctx) const170 void ImageFilterEffect::onRender(SkCanvas* canvas, const RenderContext* ctx) const {
171     // Note: we're using the source content bounds for saveLayer, not our local/filtered bounds.
172     const auto filter_ctx =
173         ScopedRenderContext(canvas, ctx).setFilterIsolation(this->getChild()->bounds(),
174                                                             canvas->getTotalMatrix(),
175                                                             fImageFilter->getFilter());
176     this->INHERITED::onRender(canvas, filter_ctx);
177 }
178 
ImageFilter(sk_sp<ImageFilter> input)179 ImageFilter::ImageFilter(sk_sp<ImageFilter> input)
180     : ImageFilter(input ? std::make_unique<InputsT>(1, std::move(input)) : nullptr) {}
181 
ImageFilter(std::unique_ptr<InputsT> inputs)182 ImageFilter::ImageFilter(std::unique_ptr<InputsT> inputs)
183     : INHERITED(kBubbleDamage_Trait)
184     , fInputs(std::move(inputs)) {
185     if (fInputs) {
186         for (const auto& input : *fInputs) {
187             this->observeInval(input);
188         }
189     }
190 }
191 
~ImageFilter()192 ImageFilter::~ImageFilter() {
193     if (fInputs) {
194         for (const auto& input : *fInputs) {
195             this->unobserveInval(input);
196         }
197     }
198 }
199 
refInput(size_t i) const200 sk_sp<SkImageFilter> ImageFilter::refInput(size_t i) const {
201     return (fInputs && i < fInputs->size()) ? (*fInputs)[i]->getFilter() : nullptr;
202 }
203 
onRevalidate(InvalidationController *,const SkMatrix &)204 SkRect ImageFilter::onRevalidate(InvalidationController*, const SkMatrix&) {
205     SkASSERT(this->hasInval());
206 
207     fFilter = this->onRevalidateFilter();
208     return SkRect::MakeEmpty();
209 }
210 
Make(sk_sp<ImageFilter> input)211 sk_sp<DropShadowImageFilter> DropShadowImageFilter::Make(sk_sp<ImageFilter> input) {
212     return sk_sp<DropShadowImageFilter>(new DropShadowImageFilter(std::move(input)));
213 }
214 
DropShadowImageFilter(sk_sp<ImageFilter> input)215 DropShadowImageFilter::DropShadowImageFilter(sk_sp<ImageFilter> input)
216     : INHERITED(std::move(input)) {}
217 
218 DropShadowImageFilter::~DropShadowImageFilter() = default;
219 
onRevalidateFilter()220 sk_sp<SkImageFilter> DropShadowImageFilter::onRevalidateFilter() {
221     if (fMode == Mode::kShadowOnly) {
222         return SkImageFilters::DropShadowOnly(fOffset.x(), fOffset.y(), fSigma.x(), fSigma.y(),
223                                               fColor, this->refInput(0));
224     } else {
225         return SkImageFilters::DropShadow(fOffset.x(), fOffset.y(), fSigma.x(), fSigma.y(),
226                                           fColor, this->refInput(0));
227     }
228 }
229 
Make(sk_sp<ImageFilter> input)230 sk_sp<BlurImageFilter> BlurImageFilter::Make(sk_sp<ImageFilter> input) {
231     return sk_sp<BlurImageFilter>(new BlurImageFilter(std::move(input)));
232 }
233 
BlurImageFilter(sk_sp<ImageFilter> input)234 BlurImageFilter::BlurImageFilter(sk_sp<ImageFilter> input)
235     : INHERITED(std::move(input)) {}
236 
237 BlurImageFilter::~BlurImageFilter() = default;
238 
onRevalidateFilter()239 sk_sp<SkImageFilter> BlurImageFilter::onRevalidateFilter() {
240     return SkImageFilters::Blur(fSigma.x(), fSigma.y(), fTileMode, this->refInput(0));
241 }
242 
Make(sk_sp<RenderNode> child,SkBlendMode mode)243 sk_sp<BlendModeEffect> BlendModeEffect::Make(sk_sp<RenderNode> child, SkBlendMode mode) {
244     return child ? sk_sp<BlendModeEffect>(new BlendModeEffect(std::move(child), mode))
245                  : nullptr;
246 }
247 
BlendModeEffect(sk_sp<RenderNode> child,SkBlendMode mode)248 BlendModeEffect::BlendModeEffect(sk_sp<RenderNode> child, SkBlendMode mode)
249     : INHERITED(std::move(child))
250     , fMode(mode) {}
251 
252 BlendModeEffect::~BlendModeEffect() = default;
253 
onRender(SkCanvas * canvas,const RenderContext * ctx) const254 void BlendModeEffect::onRender(SkCanvas* canvas, const RenderContext* ctx) const {
255     const auto local_ctx = ScopedRenderContext(canvas, ctx).modulateBlendMode(fMode);
256 
257     this->INHERITED::onRender(canvas, local_ctx);
258 }
259 
onNodeAt(const SkPoint & p) const260 const RenderNode* BlendModeEffect::onNodeAt(const SkPoint& p) const {
261     // TODO: we likely need to do something more sophisticated than delegate to descendants here.
262     return this->INHERITED::onNodeAt(p);
263 }
264 
265 } // namespace sksg
266