blob: dcfdbe4e497380020ff3685b5f2a61635edcc8ff [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
8#include "SkSGRenderEffect.h"
9
10#include "SkDropShadowImageFilter.h"
11#include "SkMakeUnique.h"
12#include "SkSGColor.h"
13
14namespace sksg {
15
16sk_sp<RenderNode> ImageFilterEffect::Make(sk_sp<RenderNode> child, sk_sp<ImageFilter> filter) {
17 return filter ? sk_sp<RenderNode>(new ImageFilterEffect(std::move(child), std::move(filter)))
18 : child;
19}
20
21ImageFilterEffect::ImageFilterEffect(sk_sp<RenderNode> child, sk_sp<ImageFilter> filter)
Florin Malitaef26fcb2019-02-10 12:54:20 -050022 // filters always override descendent damage
23 : INHERITED(std::move(child), kOverrideDamage_Trait)
Florin Malitadafd6522019-02-10 01:49:46 +000024 , fImageFilter(std::move(filter)) {
25 this->observeInval(fImageFilter);
26}
27
28ImageFilterEffect::~ImageFilterEffect() {
29 this->unobserveInval(fImageFilter);
30}
31
32SkRect ImageFilterEffect::onRevalidate(InvalidationController* ic, const SkMatrix& ctm) {
33 // FIXME: image filter effects should replace the descendents' damage!
34 fImageFilter->revalidate(ic, ctm);
35
36 const auto& filter = fImageFilter->getFilter();
37 SkASSERT(filter->canComputeFastBounds());
38
39 return filter->computeFastBounds(this->INHERITED::onRevalidate(ic, ctm));
40}
41
Florin Malitaeb46bd82019-02-12 09:33:21 -050042const RenderNode* ImageFilterEffect::onNodeAt(const SkPoint& p) const {
43 // TODO: map p through the filter DAG and dispatch to descendants?
44 // For now, image filters occlude hit-testing.
45 SkASSERT(this->bounds().contains(p.x(), p.y()));
46 return this;
47}
48
Florin Malitadafd6522019-02-10 01:49:46 +000049void ImageFilterEffect::onRender(SkCanvas* canvas, const RenderContext* ctx) const {
50 // TODO: hoist these checks to RenderNode?
51 if (this->bounds().isEmpty())
52 return;
53
54 // Note: we're using the source content bounds for saveLayer, not our local/filtered bounds.
55 const auto filter_ctx =
56 ScopedRenderContext(canvas, ctx).setFilterIsolation(this->getChild()->bounds(),
57 fImageFilter->getFilter());
58 this->INHERITED::onRender(canvas, filter_ctx);
59}
60
61ImageFilter::ImageFilter(sk_sp<ImageFilter> input)
62 : ImageFilter(input ? skstd::make_unique<InputsT>(1, std::move(input)) : nullptr) {}
63
64ImageFilter::ImageFilter(std::unique_ptr<InputsT> inputs)
65 : INHERITED(kBubbleDamage_Trait)
66 , fInputs(std::move(inputs)) {
67 if (fInputs) {
68 for (const auto& input : *fInputs) {
69 this->observeInval(input);
70 }
71 }
72}
73
74ImageFilter::~ImageFilter() {
75 if (fInputs) {
76 for (const auto& input : *fInputs) {
77 this->unobserveInval(input);
78 }
79 }
80}
81
82sk_sp<SkImageFilter> ImageFilter::refInput(size_t i) const {
83 return (fInputs && i < fInputs->size()) ? (*fInputs)[i]->getFilter() : nullptr;
84}
85
86SkRect ImageFilter::onRevalidate(InvalidationController*, const SkMatrix&) {
87 SkASSERT(this->hasInval());
88
89 fFilter = this->onRevalidateFilter();
90 return SkRect::MakeEmpty();
91}
92
93sk_sp<DropShadowImageFilter> DropShadowImageFilter::Make(sk_sp<ImageFilter> input) {
94 return sk_sp<DropShadowImageFilter>(new DropShadowImageFilter(std::move(input)));
95}
96
97DropShadowImageFilter::DropShadowImageFilter(sk_sp<ImageFilter> input)
98 : INHERITED(std::move(input)) {}
99
100DropShadowImageFilter::~DropShadowImageFilter() = default;
101
102sk_sp<SkImageFilter> DropShadowImageFilter::onRevalidateFilter() {
103 const auto mode = (fMode == Mode::kShadowOnly)
104 ? SkDropShadowImageFilter::kDrawShadowOnly_ShadowMode
105 : SkDropShadowImageFilter::kDrawShadowAndForeground_ShadowMode;
106
107 return SkDropShadowImageFilter::Make(fOffset.x(), fOffset.y(),
108 fSigma.x(), fSigma.y(),
109 fColor, mode, this->refInput(0));
110}
111
112} // namespace sksg