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