Home | History | Annotate | Download | only in src
      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 "SkSGRenderEffect.h"
      9 
     10 #include "SkDropShadowImageFilter.h"
     11 #include "SkMakeUnique.h"
     12 #include "SkSGColor.h"
     13 
     14 namespace sksg {
     15 
     16 sk_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 
     21 ImageFilterEffect::ImageFilterEffect(sk_sp<RenderNode> child, sk_sp<ImageFilter> filter)
     22     // filters always override descendent damage
     23     : INHERITED(std::move(child), kOverrideDamage_Trait)
     24     , fImageFilter(std::move(filter)) {
     25     this->observeInval(fImageFilter);
     26 }
     27 
     28 ImageFilterEffect::~ImageFilterEffect() {
     29     this->unobserveInval(fImageFilter);
     30 }
     31 
     32 SkRect 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 || filter->canComputeFastBounds());
     38 
     39     const auto content_bounds = this->INHERITED::onRevalidate(ic, ctm);
     40 
     41     return filter ? filter->computeFastBounds(content_bounds)
     42                   : content_bounds;
     43 }
     44 
     45 const RenderNode* ImageFilterEffect::onNodeAt(const SkPoint& p) const {
     46     // TODO: map p through the filter DAG and dispatch to descendants?
     47     // For now, image filters occlude hit-testing.
     48     SkASSERT(this->bounds().contains(p.x(), p.y()));
     49     return this;
     50 }
     51 
     52 void ImageFilterEffect::onRender(SkCanvas* canvas, const RenderContext* ctx) const {
     53     // Note: we're using the source content bounds for saveLayer, not our local/filtered bounds.
     54     const auto filter_ctx =
     55         ScopedRenderContext(canvas, ctx).setFilterIsolation(this->getChild()->bounds(),
     56                                                             fImageFilter->getFilter());
     57     this->INHERITED::onRender(canvas, filter_ctx);
     58 }
     59 
     60 ImageFilter::ImageFilter(sk_sp<ImageFilter> input)
     61     : ImageFilter(input ? skstd::make_unique<InputsT>(1, std::move(input)) : nullptr) {}
     62 
     63 ImageFilter::ImageFilter(std::unique_ptr<InputsT> inputs)
     64     : INHERITED(kBubbleDamage_Trait)
     65     , fInputs(std::move(inputs)) {
     66     if (fInputs) {
     67         for (const auto& input : *fInputs) {
     68             this->observeInval(input);
     69         }
     70     }
     71 }
     72 
     73 ImageFilter::~ImageFilter() {
     74     if (fInputs) {
     75         for (const auto& input : *fInputs) {
     76             this->unobserveInval(input);
     77         }
     78     }
     79 }
     80 
     81 sk_sp<SkImageFilter> ImageFilter::refInput(size_t i) const {
     82     return (fInputs && i < fInputs->size()) ? (*fInputs)[i]->getFilter() : nullptr;
     83 }
     84 
     85 SkRect ImageFilter::onRevalidate(InvalidationController*, const SkMatrix&) {
     86     SkASSERT(this->hasInval());
     87 
     88     fFilter = this->onRevalidateFilter();
     89     return SkRect::MakeEmpty();
     90 }
     91 
     92 sk_sp<DropShadowImageFilter> DropShadowImageFilter::Make(sk_sp<ImageFilter> input) {
     93     return sk_sp<DropShadowImageFilter>(new DropShadowImageFilter(std::move(input)));
     94 }
     95 
     96 DropShadowImageFilter::DropShadowImageFilter(sk_sp<ImageFilter> input)
     97     : INHERITED(std::move(input)) {}
     98 
     99 DropShadowImageFilter::~DropShadowImageFilter() = default;
    100 
    101 sk_sp<SkImageFilter> DropShadowImageFilter::onRevalidateFilter() {
    102     const auto mode = (fMode == Mode::kShadowOnly)
    103             ? SkDropShadowImageFilter::kDrawShadowOnly_ShadowMode
    104             : SkDropShadowImageFilter::kDrawShadowAndForeground_ShadowMode;
    105 
    106     return SkDropShadowImageFilter::Make(fOffset.x(), fOffset.y(),
    107                                          fSigma.x(), fSigma.y(),
    108                                          fColor, mode, this->refInput(0));
    109 }
    110 
    111 sk_sp<BlurImageFilter> BlurImageFilter::Make(sk_sp<ImageFilter> input) {
    112     return sk_sp<BlurImageFilter>(new BlurImageFilter(std::move(input)));
    113 }
    114 
    115 BlurImageFilter::BlurImageFilter(sk_sp<ImageFilter> input)
    116     : INHERITED(std::move(input)) {}
    117 
    118 BlurImageFilter::~BlurImageFilter() = default;
    119 
    120 sk_sp<SkImageFilter> BlurImageFilter::onRevalidateFilter() {
    121     return SkBlurImageFilter::Make(fSigma.x(), fSigma.y(), this->refInput(0), nullptr, fTileMode);
    122 }
    123 
    124 sk_sp<BlendModeEffect> BlendModeEffect::Make(sk_sp<RenderNode> child, SkBlendMode mode) {
    125     return child ? sk_sp<BlendModeEffect>(new BlendModeEffect(std::move(child), mode))
    126                  : nullptr;
    127 }
    128 
    129 BlendModeEffect::BlendModeEffect(sk_sp<RenderNode> child, SkBlendMode mode)
    130     : INHERITED(std::move(child))
    131     , fMode(mode) {}
    132 
    133 BlendModeEffect::~BlendModeEffect() = default;
    134 
    135 void BlendModeEffect::onRender(SkCanvas* canvas, const RenderContext* ctx) const {
    136     const auto local_ctx = ScopedRenderContext(canvas, ctx).modulateBlendMode(fMode);
    137 
    138     this->INHERITED::onRender(canvas, local_ctx);
    139 }
    140 
    141 const RenderNode* BlendModeEffect::onNodeAt(const SkPoint& p) const {
    142     // TODO: we likely need to do something more sophisticated than delegate to descendants here.
    143     return this->INHERITED::onNodeAt(p);
    144 }
    145 
    146 } // namespace sksg
    147