blob: 8109b477492d089ba471ef2a133b99fc32a45803 [file] [log] [blame]
Florin Malitadafd6522019-02-10 01:49:46 +00001/*
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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "modules/sksg/include/SkSGRenderEffect.h"
Florin Malitadafd6522019-02-10 01:49:46 +00009
Mike Kleinc0bd9f92019-04-23 12:05:21 -050010#include "include/core/SkCanvas.h"
Florin Malita9c47e152019-06-18 21:13:21 -040011#include "include/core/SkMaskFilter.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050012#include "include/core/SkShader.h"
Florin Malita9c47e152019-06-18 21:13:21 -040013#include "src/core/SkMaskFilterBase.h"
Florin Malitadafd6522019-02-10 01:49:46 +000014
15namespace sksg {
16
Florin Malita40540612020-03-06 18:41:41 -050017sk_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)))
Florin Malita9c47e152019-06-18 21:13:21 -040019 : nullptr;
20}
21
Florin Malita40540612020-03-06 18:41:41 -050022MaskShaderEffect::MaskShaderEffect(sk_sp<RenderNode> child, sk_sp<SkShader> sh)
23 : INHERITED(std::move(child))
24 , fShader(std::move(sh)) {
Florin Malita9c47e152019-06-18 21:13:21 -040025}
26
Florin Malita40540612020-03-06 18:41:41 -050027void MaskShaderEffect::onRender(SkCanvas* canvas, const RenderContext* ctx) const {
Florin Malita9c47e152019-06-18 21:13:21 -040028 const auto local_ctx = ScopedRenderContext(canvas, ctx)
Florin Malita40540612020-03-06 18:41:41 -050029 .modulateMaskShader(fShader, canvas->getTotalMatrix());
Florin Malita9c47e152019-06-18 21:13:21 -040030
31 this->INHERITED::onRender(canvas, local_ctx);
32}
33
Florin Malita3d846c92019-04-02 09:43:18 -040034sk_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;
Florin Malitafb4bce82019-04-01 13:40:58 -040037}
38
39ShaderEffect::ShaderEffect(sk_sp<RenderNode> child, sk_sp<Shader> shader)
40 : INHERITED(std::move(child))
41 , fShader(std::move(shader)) {
Florin Malita3d846c92019-04-02 09:43:18 -040042 if (fShader) {
43 this->observeInval(fShader);
44 }
Florin Malitafb4bce82019-04-01 13:40:58 -040045}
46
47ShaderEffect::~ShaderEffect() {
Florin Malita3d846c92019-04-02 09:43:18 -040048 if (fShader) {
49 this->unobserveInval(fShader);
50 }
Florin Malitafb4bce82019-04-01 13:40:58 -040051}
52
Florin Malita3d846c92019-04-02 09:43:18 -040053void 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}
Florin Malitafb4bce82019-04-01 13:40:58 -040064SkRect ShaderEffect::onRevalidate(InvalidationController* ic, const SkMatrix& ctm) {
Florin Malita3d846c92019-04-02 09:43:18 -040065 if (fShader) {
66 fShader->revalidate(ic, ctm);
67 }
Florin Malitafb4bce82019-04-01 13:40:58 -040068
69 return this->INHERITED::onRevalidate(ic, ctm);
70}
71
72void ShaderEffect::onRender(SkCanvas* canvas, const RenderContext* ctx) const {
Florin Malita3d846c92019-04-02 09:43:18 -040073 const auto local_ctx = ScopedRenderContext(canvas, ctx)
Florin Malita866e2622019-04-03 15:30:16 -040074 .modulateShader(fShader ? fShader->getShader() : nullptr, canvas->getTotalMatrix());
Florin Malitafb4bce82019-04-01 13:40:58 -040075
76 this->INHERITED::onRender(canvas, local_ctx);
77}
78
79Shader::Shader() : INHERITED(kBubbleDamage_Trait) {}
80
81Shader::~Shader() = default;
82
83SkRect Shader::onRevalidate(InvalidationController*, const SkMatrix&) {
84 SkASSERT(this->hasInval());
85
86 fShader = this->onRevalidateShader();
87 return SkRect::MakeEmpty();
88}
89
Florin Malitadafd6522019-02-10 01:49:46 +000090sk_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
95ImageFilterEffect::ImageFilterEffect(sk_sp<RenderNode> child, sk_sp<ImageFilter> filter)
Florin Malitaef26fcb2019-02-10 12:54:20 -050096 // filters always override descendent damage
97 : INHERITED(std::move(child), kOverrideDamage_Trait)
Florin Malitadafd6522019-02-10 01:49:46 +000098 , fImageFilter(std::move(filter)) {
99 this->observeInval(fImageFilter);
100}
101
102ImageFilterEffect::~ImageFilterEffect() {
103 this->unobserveInval(fImageFilter);
104}
105
106SkRect 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();
Florin Malitae35a7ea2020-04-17 13:08:46 -0400111
112 // Would be nice for this this to stick, but canComputeFastBounds()
113 // appears to be conservative (false negatives).
114 // SkASSERT(!filter || filter->canComputeFastBounds());
Florin Malitadafd6522019-02-10 01:49:46 +0000115
Florin Malitaa720d762019-03-07 15:11:27 -0500116 const auto content_bounds = this->INHERITED::onRevalidate(ic, ctm);
117
118 return filter ? filter->computeFastBounds(content_bounds)
119 : content_bounds;
Florin Malitadafd6522019-02-10 01:49:46 +0000120}
121
Florin Malitaeb46bd82019-02-12 09:33:21 -0500122const 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
Florin Malitadafd6522019-02-10 01:49:46 +0000129void ImageFilterEffect::onRender(SkCanvas* canvas, const RenderContext* ctx) const {
Florin Malitadafd6522019-02-10 01:49:46 +0000130 // 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(),
Florin Malita866e2622019-04-03 15:30:16 -0400133 canvas->getTotalMatrix(),
Florin Malitadafd6522019-02-10 01:49:46 +0000134 fImageFilter->getFilter());
135 this->INHERITED::onRender(canvas, filter_ctx);
136}
137
138ImageFilter::ImageFilter(sk_sp<ImageFilter> input)
Mike Kleinf46d5ca2019-12-11 10:45:01 -0500139 : ImageFilter(input ? std::make_unique<InputsT>(1, std::move(input)) : nullptr) {}
Florin Malitadafd6522019-02-10 01:49:46 +0000140
141ImageFilter::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
151ImageFilter::~ImageFilter() {
152 if (fInputs) {
153 for (const auto& input : *fInputs) {
154 this->unobserveInval(input);
155 }
156 }
157}
158
159sk_sp<SkImageFilter> ImageFilter::refInput(size_t i) const {
160 return (fInputs && i < fInputs->size()) ? (*fInputs)[i]->getFilter() : nullptr;
161}
162
163SkRect ImageFilter::onRevalidate(InvalidationController*, const SkMatrix&) {
164 SkASSERT(this->hasInval());
165
166 fFilter = this->onRevalidateFilter();
167 return SkRect::MakeEmpty();
168}
169
Florin Malitae35a7ea2020-04-17 13:08:46 -0400170ExternalImageFilter:: ExternalImageFilter() = default;
171ExternalImageFilter::~ExternalImageFilter() = default;
172
Florin Malitadafd6522019-02-10 01:49:46 +0000173sk_sp<DropShadowImageFilter> DropShadowImageFilter::Make(sk_sp<ImageFilter> input) {
174 return sk_sp<DropShadowImageFilter>(new DropShadowImageFilter(std::move(input)));
175}
176
177DropShadowImageFilter::DropShadowImageFilter(sk_sp<ImageFilter> input)
178 : INHERITED(std::move(input)) {}
179
180DropShadowImageFilter::~DropShadowImageFilter() = default;
181
182sk_sp<SkImageFilter> DropShadowImageFilter::onRevalidateFilter() {
Michael Ludwig297587b2019-08-01 16:40:20 -0400183 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 }
Florin Malitadafd6522019-02-10 01:49:46 +0000190}
191
Florin Malitaa720d762019-03-07 15:11:27 -0500192sk_sp<BlurImageFilter> BlurImageFilter::Make(sk_sp<ImageFilter> input) {
193 return sk_sp<BlurImageFilter>(new BlurImageFilter(std::move(input)));
194}
195
196BlurImageFilter::BlurImageFilter(sk_sp<ImageFilter> input)
197 : INHERITED(std::move(input)) {}
198
199BlurImageFilter::~BlurImageFilter() = default;
200
201sk_sp<SkImageFilter> BlurImageFilter::onRevalidateFilter() {
Michael Ludwig297587b2019-08-01 16:40:20 -0400202 return SkImageFilters::Blur(fSigma.x(), fSigma.y(), fTileMode, this->refInput(0));
Florin Malitaa720d762019-03-07 15:11:27 -0500203}
204
Florin Malitabd64f182019-02-25 09:55:04 -0500205sk_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
210BlendModeEffect::BlendModeEffect(sk_sp<RenderNode> child, SkBlendMode mode)
211 : INHERITED(std::move(child))
212 , fMode(mode) {}
213
214BlendModeEffect::~BlendModeEffect() = default;
215
216void 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
222const 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
Florin Malitaa524ea22020-07-20 10:51:07 -0400227sk_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
232LayerEffect::LayerEffect(sk_sp<RenderNode> child, SkBlendMode mode)
233 : INHERITED(std::move(child))
234 , fMode(mode) {}
235
236LayerEffect::~LayerEffect() = default;
237
238void 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
Florin Malitadafd6522019-02-10 01:49:46 +0000258} // namespace sksg