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