Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
SkSGRenderEffect.cpp
Go to the documentation of this file.
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
9
17
18#include <utility>
19
20class SkMatrix;
21
22namespace sksg {
23
25 return child ? sk_sp<MaskShaderEffect>(new MaskShaderEffect(std::move(child), std::move(sh)))
26 : nullptr;
27}
28
29MaskShaderEffect::MaskShaderEffect(sk_sp<RenderNode> child, sk_sp<SkShader> sh)
30 : INHERITED(std::move(child))
31 , fShader(std::move(sh)) {
32}
33
34void MaskShaderEffect::onRender(SkCanvas* canvas, const RenderContext* ctx) const {
35 const auto local_ctx = ScopedRenderContext(canvas, ctx)
36 .modulateMaskShader(fShader, canvas->getTotalMatrix());
37
38 this->INHERITED::onRender(canvas, local_ctx);
39}
40
42 return child ? sk_sp<ShaderEffect>(new ShaderEffect(std::move(child), std::move(shader)))
43 : nullptr;
44}
45
46ShaderEffect::ShaderEffect(sk_sp<RenderNode> child, sk_sp<Shader> shader)
47 : INHERITED(std::move(child))
48 , fShader(std::move(shader)) {
49 if (fShader) {
50 this->observeInval(fShader);
51 }
52}
53
55 if (fShader) {
56 this->unobserveInval(fShader);
57 }
58}
59
61 if (fShader) {
62 this->unobserveInval(fShader);
63 }
64
65 fShader = std::move(sh);
66
67 if (fShader) {
68 this->observeInval(fShader);
69 }
70}
72 if (fShader) {
73 fShader->revalidate(ic, ctm);
74 }
75
76 return this->INHERITED::onRevalidate(ic, ctm);
77}
78
79void ShaderEffect::onRender(SkCanvas* canvas, const RenderContext* ctx) const {
80 const auto local_ctx = ScopedRenderContext(canvas, ctx)
81 .modulateShader(fShader ? fShader->getShader() : nullptr, canvas->getTotalMatrix());
82
83 this->INHERITED::onRender(canvas, local_ctx);
84}
85
86Shader::Shader() : INHERITED(kBubbleDamage_Trait) {}
87
88Shader::~Shader() = default;
89
91 SkASSERT(this->hasInval());
92
93 fShader = this->onRevalidateShader();
94 return SkRect::MakeEmpty();
95}
96
98 return filter ? sk_sp<RenderNode>(new ImageFilterEffect(std::move(child), std::move(filter)))
99 : child;
100}
101
103 // filters always override descendent damage
104 : INHERITED(std::move(child), kOverrideDamage_Trait)
105 , fImageFilter(std::move(filter)) {
106 this->observeInval(fImageFilter);
107}
108
112
114 const auto content_bounds = this->INHERITED::onRevalidate(ic, ctm);
115
116 if (fCropping == Cropping::kContent) {
117 fImageFilter->setCropRect(content_bounds);
118 } else {
119 fImageFilter->setCropRect(std::nullopt);
120 }
121
122 // FIXME: image filter effects should replace the descendents' damage!
123 fImageFilter->revalidate(ic, ctm);
124
125 const auto& filter = fImageFilter->getFilter();
126
127 // Would be nice for this this to stick, but canComputeFastBounds()
128 // appears to be conservative (false negatives).
129 // SkASSERT(!filter || filter->canComputeFastBounds());
130
131 return filter ? filter->computeFastBounds(content_bounds)
132 : content_bounds;
133}
134
136 // TODO: map p through the filter DAG and dispatch to descendants?
137 // For now, image filters occlude hit-testing.
138 SkASSERT(this->bounds().contains(p.x(), p.y()));
139 return this;
140}
141
142void ImageFilterEffect::onRender(SkCanvas* canvas, const RenderContext* ctx) const {
143 // Note: we're using the source content bounds for saveLayer, not our local/filtered bounds.
144 const auto filter_ctx =
146 canvas->getTotalMatrix(),
147 fImageFilter->getFilter());
148 this->INHERITED::onRender(canvas, filter_ctx);
149}
150
151ImageFilter::ImageFilter() : INHERITED(kBubbleDamage_Trait) {}
152
153ImageFilter::~ImageFilter() = default;
154
156 SkASSERT(this->hasInval());
157
158 fFilter = this->onRevalidateFilter();
159 return SkRect::MakeEmpty();
160}
161
162ExternalImageFilter:: ExternalImageFilter() = default;
164
168
169DropShadowImageFilter::DropShadowImageFilter()
170 : INHERITED() {}
171
173
175 if (fMode == Mode::kShadowOnly) {
176 return SkImageFilters::DropShadowOnly(fOffset.x(), fOffset.y(), fSigma.x(), fSigma.y(),
177 fColor, nullptr, this->getCropRect());
178 } else {
179 return SkImageFilters::DropShadow(fOffset.x(), fOffset.y(), fSigma.x(), fSigma.y(),
180 fColor, nullptr, this->getCropRect());
181 }
182}
183
187
188BlurImageFilter::BlurImageFilter()
189 : INHERITED() {}
190
192
194 // Tile modes other than kDecal require an explicit crop rect.
195 SkASSERT(fTileMode == SkTileMode::kDecal || this->getCropRect().has_value());
196 return SkImageFilters::Blur(fSigma.x(), fSigma.y(), fTileMode, nullptr, this->getCropRect());
197}
198
200 return child ? sk_sp<BlenderEffect>(new BlenderEffect(std::move(child), std::move(blender)))
201 : nullptr;
202}
203
204BlenderEffect::BlenderEffect(sk_sp<RenderNode> child, sk_sp<SkBlender> blender)
205 : INHERITED(std::move(child))
206 , fBlender (std::move(blender)) {}
207
209
210void BlenderEffect::onRender(SkCanvas* canvas, const RenderContext* ctx) const {
211 const auto local_ctx = ScopedRenderContext(canvas, ctx).modulateBlender(fBlender);
212
213 this->INHERITED::onRender(canvas, local_ctx);
214}
215
217 // TODO: we likely need to do something more sophisticated than delegate to descendants here.
218 return this->INHERITED::onNodeAt(p);
219}
220
222 return child ? sk_sp<LayerEffect>(new LayerEffect(std::move(child), mode))
223 : nullptr;
224}
225
226LayerEffect::LayerEffect(sk_sp<RenderNode> child, SkBlendMode mode)
227 : INHERITED(std::move(child))
228 , fMode(mode) {}
229
230LayerEffect::~LayerEffect() = default;
231
232void LayerEffect::onRender(SkCanvas* canvas, const RenderContext* ctx) const {
233 SkAutoCanvasRestore acr(canvas, false);
234
235 // Commit any potential pending paint effects to their own layer.
236 const auto local_ctx = ScopedRenderContext(canvas, ctx).setIsolation(this->bounds(),
237 canvas->getTotalMatrix(),
238 true);
239
240 SkPaint layer_paint;
241 if (ctx) {
242 // Apply all optional context overrides upfront.
243 ctx->modulatePaint(canvas->getTotalMatrix(), &layer_paint);
244 }
245 layer_paint.setBlendMode(fMode);
246
247 canvas->saveLayer(nullptr, &layer_paint);
248
249 this->INHERITED::onRender(canvas, nullptr);
250}
251
252} // namespace sksg
#define SkASSERT(cond)
Definition SkAssert.h:116
SkBlendMode
Definition SkBlendMode.h:38
static bool contains(const SkRect &r, SkPoint p)
#define INHERITED(method,...)
int saveLayer(const SkRect *bounds, const SkPaint *paint)
Definition SkCanvas.cpp:500
SkMatrix getTotalMatrix() const
static sk_sp< SkImageFilter > DropShadow(SkScalar dx, SkScalar dy, SkScalar sigmaX, SkScalar sigmaY, SkColor color, sk_sp< SkImageFilter > input, const CropRect &cropRect={})
static sk_sp< SkImageFilter > DropShadowOnly(SkScalar dx, SkScalar dy, SkScalar sigmaX, SkScalar sigmaY, SkColor color, sk_sp< SkImageFilter > input, const CropRect &cropRect={})
static sk_sp< SkImageFilter > Blur(SkScalar sigmaX, SkScalar sigmaY, SkTileMode tileMode, sk_sp< SkImageFilter > input, const CropRect &cropRect={})
void setBlendMode(SkBlendMode mode)
Definition SkPaint.cpp:151
void onRender(SkCanvas *, const RenderContext *) const override
const RenderNode * onNodeAt(const SkPoint &) const override
static sk_sp< BlenderEffect > Make(sk_sp< RenderNode > child, sk_sp< SkBlender >=nullptr)
~BlenderEffect() override
~BlurImageFilter() override
static sk_sp< BlurImageFilter > Make()
sk_sp< SkImageFilter > onRevalidateFilter() override
static sk_sp< DropShadowImageFilter > Make()
sk_sp< SkImageFilter > onRevalidateFilter() override
const sk_sp< RenderNode > & getChild() const
const RenderNode * onNodeAt(const SkPoint &) const override
void onRender(SkCanvas *, const RenderContext *) const override
SkRect onRevalidate(InvalidationController *, const SkMatrix &) override
const RenderNode * onNodeAt(const SkPoint &) const override
SkRect onRevalidate(InvalidationController *, const SkMatrix &) override
static sk_sp< RenderNode > Make(sk_sp< RenderNode > child, sk_sp< ImageFilter > filter)
void onRender(SkCanvas *, const RenderContext *) const override
~ImageFilter() override
SkRect onRevalidate(InvalidationController *, const SkMatrix &) final
virtual sk_sp< SkImageFilter > onRevalidateFilter()=0
static sk_sp< LayerEffect > Make(sk_sp< RenderNode > child, SkBlendMode mode=SkBlendMode::kSrcOver)
void onRender(SkCanvas *, const RenderContext *) const override
~LayerEffect() override
static sk_sp< MaskShaderEffect > Make(sk_sp< RenderNode >, sk_sp< SkShader >=nullptr)
void onRender(SkCanvas *, const RenderContext *) const override
void observeInval(const sk_sp< Node > &)
Definition SkSGNode.cpp:61
void unobserveInval(const sk_sp< Node > &)
Definition SkSGNode.cpp:84
const SkRect & bounds() const
Definition SkSGNode.h:55
bool hasInval() const
Definition SkSGNode.h:60
ScopedRenderContext && setFilterIsolation(const SkRect &bounds, const SkMatrix &ctm, sk_sp< SkImageFilter >)
ScopedRenderContext && modulateMaskShader(sk_sp< SkShader >, const SkMatrix &ms_ctm)
ScopedRenderContext && setIsolation(const SkRect &bounds, const SkMatrix &ctm, bool do_isolate)
ScopedRenderContext && modulateBlender(sk_sp< SkBlender >)
ScopedRenderContext && modulateShader(sk_sp< SkShader >, const SkMatrix &shader_ctm)
friend class ImageFilterEffect
SkRect onRevalidate(InvalidationController *, const SkMatrix &) override
void setShader(sk_sp< Shader >)
static sk_sp< ShaderEffect > Make(sk_sp< RenderNode > child, sk_sp< Shader > shader=nullptr)
void onRender(SkCanvas *, const RenderContext *) const override
SkRect onRevalidate(InvalidationController *, const SkMatrix &) final
~Shader() override
virtual sk_sp< SkShader > onRevalidateShader()=0
Definition Skottie.h:32
Definition ref_ptr.h:256
constexpr float y() const
constexpr float x() const
static constexpr SkRect MakeEmpty()
Definition SkRect.h:595
void modulatePaint(const SkMatrix &ctm, SkPaint *, bool is_layer_paint=false) const
SkBlendMode fMode
Definition xfermodes.cpp:52