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