Coverage Report

Created: 2024-09-14 07:19

/src/skia/modules/sksg/src/SkSGRenderEffect.cpp
Line
Count
Source (jump to first uncovered line)
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/SkBlender.h"
11
#include "include/core/SkCanvas.h"
12
#include "include/core/SkPaint.h"
13
#include "include/core/SkShader.h"
14
#include "include/core/SkTileMode.h"
15
#include "include/effects/SkImageFilters.h"
16
#include "modules/sksg/include/SkSGRenderNode.h"
17
18
#include <utility>
19
20
class SkMatrix;
21
22
namespace sksg {
23
24
0
sk_sp<MaskShaderEffect> MaskShaderEffect::Make(sk_sp<RenderNode> child, sk_sp<SkShader> sh) {
25
0
    return child ? sk_sp<MaskShaderEffect>(new MaskShaderEffect(std::move(child), std::move(sh)))
26
0
                 : nullptr;
27
0
}
28
29
MaskShaderEffect::MaskShaderEffect(sk_sp<RenderNode> child, sk_sp<SkShader> sh)
30
    : INHERITED(std::move(child))
31
0
    , fShader(std::move(sh)) {
32
0
}
33
34
0
void MaskShaderEffect::onRender(SkCanvas* canvas, const RenderContext* ctx) const {
35
0
    const auto local_ctx = ScopedRenderContext(canvas, ctx)
36
0
            .modulateMaskShader(fShader, canvas->getTotalMatrix());
37
38
0
    this->INHERITED::onRender(canvas, local_ctx);
39
0
}
40
41
1.10k
sk_sp<ShaderEffect> ShaderEffect::Make(sk_sp<RenderNode> child, sk_sp<Shader> shader) {
42
1.10k
    return child ? sk_sp<ShaderEffect>(new ShaderEffect(std::move(child), std::move(shader)))
43
1.10k
                 : nullptr;
44
1.10k
}
45
46
ShaderEffect::ShaderEffect(sk_sp<RenderNode> child, sk_sp<Shader> shader)
47
    : INHERITED(std::move(child))
48
1.10k
    , fShader(std::move(shader)) {
49
1.10k
    if (fShader) {
50
0
        this->observeInval(fShader);
51
0
    }
52
1.10k
}
53
54
1.10k
ShaderEffect::~ShaderEffect() {
55
1.10k
    if (fShader) {
56
1.10k
        this->unobserveInval(fShader);
57
1.10k
    }
58
1.10k
}
59
60
1.10k
void ShaderEffect::setShader(sk_sp<Shader> sh) {
61
1.10k
    if (fShader) {
62
0
        this->unobserveInval(fShader);
63
0
    }
64
65
1.10k
    fShader = std::move(sh);
66
67
1.10k
    if (fShader) {
68
1.10k
        this->observeInval(fShader);
69
1.10k
    }
70
1.10k
}
71
1.94k
SkRect ShaderEffect::onRevalidate(InvalidationController* ic, const SkMatrix& ctm) {
72
1.94k
    if (fShader) {
73
1.94k
        fShader->revalidate(ic, ctm);
74
1.94k
    }
75
76
1.94k
    return this->INHERITED::onRevalidate(ic, ctm);
77
1.94k
}
78
79
43
void ShaderEffect::onRender(SkCanvas* canvas, const RenderContext* ctx) const {
80
43
    const auto local_ctx = ScopedRenderContext(canvas, ctx)
81
43
            .modulateShader(fShader ? fShader->getShader() : nullptr, canvas->getTotalMatrix());
82
83
43
    this->INHERITED::onRender(canvas, local_ctx);
84
43
}
85
86
21.3k
Shader::Shader() : INHERITED(kBubbleDamage_Trait) {}
87
88
21.3k
Shader::~Shader() = default;
89
90
14.9k
SkRect Shader::onRevalidate(InvalidationController*, const SkMatrix&) {
91
14.9k
    SkASSERT(this->hasInval());
92
93
14.9k
    fShader = this->onRevalidateShader();
94
14.9k
    return SkRect::MakeEmpty();
95
14.9k
}
96
97
96.3k
sk_sp<RenderNode> ImageFilterEffect::Make(sk_sp<RenderNode> child, sk_sp<ImageFilter> filter) {
98
96.3k
    return filter ? sk_sp<RenderNode>(new ImageFilterEffect(std::move(child), std::move(filter)))
99
96.3k
                  : child;
100
96.3k
}
101
102
ImageFilterEffect::ImageFilterEffect(sk_sp<RenderNode> child, sk_sp<ImageFilter> filter)
103
    // filters always override descendent damage
104
    : INHERITED(std::move(child), kOverrideDamage_Trait)
105
88.1k
    , fImageFilter(std::move(filter)) {
106
88.1k
    this->observeInval(fImageFilter);
107
88.1k
}
108
109
88.1k
ImageFilterEffect::~ImageFilterEffect() {
110
88.1k
    this->unobserveInval(fImageFilter);
111
88.1k
}
112
113
97.1k
SkRect ImageFilterEffect::onRevalidate(InvalidationController* ic, const SkMatrix& ctm) {
114
97.1k
    const auto content_bounds = this->INHERITED::onRevalidate(ic, ctm);
115
116
97.1k
    if (fCropping == Cropping::kContent) {
117
34
        fImageFilter->setCropRect(content_bounds);
118
97.0k
    } else {
119
97.0k
        fImageFilter->setCropRect(std::nullopt);
120
97.0k
    }
121
122
    // FIXME: image filter effects should replace the descendents' damage!
123
97.1k
    fImageFilter->revalidate(ic, ctm);
124
125
97.1k
    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
97.1k
    return filter ? filter->computeFastBounds(content_bounds)
132
97.1k
                  : content_bounds;
133
97.1k
}
134
135
0
const RenderNode* ImageFilterEffect::onNodeAt(const SkPoint& p) const {
136
    // TODO: map p through the filter DAG and dispatch to descendants?
137
    // For now, image filters occlude hit-testing.
138
0
    SkASSERT(this->bounds().contains(p.x(), p.y()));
139
0
    return this;
140
0
}
141
142
1.27k
void 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
1.27k
    const auto filter_ctx =
145
1.27k
        ScopedRenderContext(canvas, ctx).setFilterIsolation(this->getChild()->bounds(),
146
1.27k
                                                            canvas->getTotalMatrix(),
147
1.27k
                                                            fImageFilter->getFilter());
148
1.27k
    this->INHERITED::onRender(canvas, filter_ctx);
149
1.27k
}
150
151
88.1k
ImageFilter::ImageFilter() : INHERITED(kBubbleDamage_Trait) {}
152
153
88.1k
ImageFilter::~ImageFilter() = default;
154
155
87.9k
SkRect ImageFilter::onRevalidate(InvalidationController*, const SkMatrix&) {
156
87.9k
    SkASSERT(this->hasInval());
157
158
87.9k
    fFilter = this->onRevalidateFilter();
159
87.9k
    return SkRect::MakeEmpty();
160
87.9k
}
161
162
74.9k
ExternalImageFilter:: ExternalImageFilter() = default;
163
74.9k
ExternalImageFilter::~ExternalImageFilter() = default;
164
165
12.3k
sk_sp<DropShadowImageFilter> DropShadowImageFilter::Make() {
166
12.3k
    return sk_sp<DropShadowImageFilter>(new DropShadowImageFilter());
167
12.3k
}
168
169
DropShadowImageFilter::DropShadowImageFilter()
170
12.3k
    : INHERITED() {}
171
172
DropShadowImageFilter::~DropShadowImageFilter() = default;
173
174
12.1k
sk_sp<SkImageFilter> DropShadowImageFilter::onRevalidateFilter() {
175
12.1k
    if (fMode == Mode::kShadowOnly) {
176
1.60k
        return SkImageFilters::DropShadowOnly(fOffset.x(), fOffset.y(), fSigma.x(), fSigma.y(),
177
1.60k
                                              fColor, nullptr, this->getCropRect());
178
10.5k
    } else {
179
10.5k
        return SkImageFilters::DropShadow(fOffset.x(), fOffset.y(), fSigma.x(), fSigma.y(),
180
10.5k
                                          fColor, nullptr, this->getCropRect());
181
10.5k
    }
182
12.1k
}
183
184
852
sk_sp<BlurImageFilter> BlurImageFilter::Make() {
185
852
    return sk_sp<BlurImageFilter>(new BlurImageFilter());
186
852
}
187
188
BlurImageFilter::BlurImageFilter()
189
852
    : INHERITED() {}
190
191
BlurImageFilter::~BlurImageFilter() = default;
192
193
847
sk_sp<SkImageFilter> BlurImageFilter::onRevalidateFilter() {
194
    // Tile modes other than kDecal require an explicit crop rect.
195
847
    SkASSERT(fTileMode == SkTileMode::kDecal || this->getCropRect().has_value());
196
847
    return SkImageFilters::Blur(fSigma.x(), fSigma.y(), fTileMode, nullptr, this->getCropRect());
197
847
}
198
199
14.3k
sk_sp<BlenderEffect> BlenderEffect::Make(sk_sp<RenderNode> child, sk_sp<SkBlender> blender) {
200
14.3k
    return child ? sk_sp<BlenderEffect>(new BlenderEffect(std::move(child), std::move(blender)))
201
14.3k
                 : nullptr;
202
14.3k
}
203
204
BlenderEffect::BlenderEffect(sk_sp<RenderNode> child, sk_sp<SkBlender> blender)
205
    : INHERITED(std::move(child))
206
8.19k
    , fBlender (std::move(blender)) {}
207
208
8.19k
BlenderEffect::~BlenderEffect() = default;
209
210
366
void BlenderEffect::onRender(SkCanvas* canvas, const RenderContext* ctx) const {
211
366
    const auto local_ctx = ScopedRenderContext(canvas, ctx).modulateBlender(fBlender);
212
213
366
    this->INHERITED::onRender(canvas, local_ctx);
214
366
}
215
216
0
const RenderNode* BlenderEffect::onNodeAt(const SkPoint& p) const {
217
    // TODO: we likely need to do something more sophisticated than delegate to descendants here.
218
0
    return this->INHERITED::onNodeAt(p);
219
0
}
220
221
0
sk_sp<LayerEffect> LayerEffect::Make(sk_sp<RenderNode> child, SkBlendMode mode) {
222
0
    return child ? sk_sp<LayerEffect>(new LayerEffect(std::move(child), mode))
223
0
                 : nullptr;
224
0
}
225
226
LayerEffect::LayerEffect(sk_sp<RenderNode> child, SkBlendMode mode)
227
    : INHERITED(std::move(child))
228
0
    , fMode(mode) {}
229
230
0
LayerEffect::~LayerEffect() = default;
231
232
0
void LayerEffect::onRender(SkCanvas* canvas, const RenderContext* ctx) const {
233
0
    SkAutoCanvasRestore acr(canvas, false);
234
235
    // Commit any potential pending paint effects to their own layer.
236
0
    const auto local_ctx = ScopedRenderContext(canvas, ctx).setIsolation(this->bounds(),
237
0
                                                                         canvas->getTotalMatrix(),
238
0
                                                                         true);
239
240
0
    SkPaint layer_paint;
241
0
    if (ctx) {
242
        // Apply all optional context overrides upfront.
243
0
        ctx->modulatePaint(canvas->getTotalMatrix(), &layer_paint);
244
0
    }
245
0
    layer_paint.setBlendMode(fMode);
246
247
0
    canvas->saveLayer(nullptr, &layer_paint);
248
249
0
    this->INHERITED::onRender(canvas, nullptr);
250
0
}
251
252
} // namespace sksg