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