blob: fdde23acdc06968783b2d384ddac9c79ad11c868 [file] [log] [blame]
/*
* Copyright 2019 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkSGRenderEffect.h"
#include "SkDropShadowImageFilter.h"
#include "SkMakeUnique.h"
#include "SkSGColor.h"
namespace sksg {
sk_sp<RenderNode> ImageFilterEffect::Make(sk_sp<RenderNode> child, sk_sp<ImageFilter> filter) {
return filter ? sk_sp<RenderNode>(new ImageFilterEffect(std::move(child), std::move(filter)))
: child;
}
ImageFilterEffect::ImageFilterEffect(sk_sp<RenderNode> child, sk_sp<ImageFilter> filter)
// filters always override descendent damage
: INHERITED(std::move(child), kOverrideDamage_Trait)
, fImageFilter(std::move(filter)) {
this->observeInval(fImageFilter);
}
ImageFilterEffect::~ImageFilterEffect() {
this->unobserveInval(fImageFilter);
}
SkRect ImageFilterEffect::onRevalidate(InvalidationController* ic, const SkMatrix& ctm) {
// FIXME: image filter effects should replace the descendents' damage!
fImageFilter->revalidate(ic, ctm);
const auto& filter = fImageFilter->getFilter();
SkASSERT(filter->canComputeFastBounds());
return filter->computeFastBounds(this->INHERITED::onRevalidate(ic, ctm));
}
void ImageFilterEffect::onRender(SkCanvas* canvas, const RenderContext* ctx) const {
// TODO: hoist these checks to RenderNode?
if (this->bounds().isEmpty())
return;
// Note: we're using the source content bounds for saveLayer, not our local/filtered bounds.
const auto filter_ctx =
ScopedRenderContext(canvas, ctx).setFilterIsolation(this->getChild()->bounds(),
fImageFilter->getFilter());
this->INHERITED::onRender(canvas, filter_ctx);
}
ImageFilter::ImageFilter(sk_sp<ImageFilter> input)
: ImageFilter(input ? skstd::make_unique<InputsT>(1, std::move(input)) : nullptr) {}
ImageFilter::ImageFilter(std::unique_ptr<InputsT> inputs)
: INHERITED(kBubbleDamage_Trait)
, fInputs(std::move(inputs)) {
if (fInputs) {
for (const auto& input : *fInputs) {
this->observeInval(input);
}
}
}
ImageFilter::~ImageFilter() {
if (fInputs) {
for (const auto& input : *fInputs) {
this->unobserveInval(input);
}
}
}
sk_sp<SkImageFilter> ImageFilter::refInput(size_t i) const {
return (fInputs && i < fInputs->size()) ? (*fInputs)[i]->getFilter() : nullptr;
}
SkRect ImageFilter::onRevalidate(InvalidationController*, const SkMatrix&) {
SkASSERT(this->hasInval());
fFilter = this->onRevalidateFilter();
return SkRect::MakeEmpty();
}
sk_sp<DropShadowImageFilter> DropShadowImageFilter::Make(sk_sp<ImageFilter> input) {
return sk_sp<DropShadowImageFilter>(new DropShadowImageFilter(std::move(input)));
}
DropShadowImageFilter::DropShadowImageFilter(sk_sp<ImageFilter> input)
: INHERITED(std::move(input)) {}
DropShadowImageFilter::~DropShadowImageFilter() = default;
sk_sp<SkImageFilter> DropShadowImageFilter::onRevalidateFilter() {
const auto mode = (fMode == Mode::kShadowOnly)
? SkDropShadowImageFilter::kDrawShadowOnly_ShadowMode
: SkDropShadowImageFilter::kDrawShadowAndForeground_ShadowMode;
return SkDropShadowImageFilter::Make(fOffset.x(), fOffset.y(),
fSigma.x(), fSigma.y(),
fColor, mode, this->refInput(0));
}
} // namespace sksg