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