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/skottie/src/effects/Effects.h" 9 10#include "include/private/SkTPin.h" 11#include "modules/skottie/src/SkottieValue.h" 12#include "modules/sksg/include/SkSGRenderEffect.h" 13#include "src/utils/SkJSON.h" 14 15namespace skottie { 16namespace internal { 17 18namespace { 19 20class DropShadowAdapter final : public AnimatablePropertyContainer { 21public: 22 static sk_sp<DropShadowAdapter> Make(const skjson::ArrayValue& jprops, 23 sk_sp<sksg::RenderNode> layer, 24 const AnimationBuilder& abuilder) { 25 enum : size_t { 26 kShadowColor_Index = 0, 27 kOpacity_Index = 1, 28 kDirection_Index = 2, 29 kDistance_Index = 3, 30 kSoftness_Index = 4, 31 kShadowOnly_Index = 5, 32 }; 33 34 sk_sp<DropShadowAdapter> adapter(new DropShadowAdapter(std::move(layer))); 35 36 EffectBinder(jprops, abuilder, adapter.get()) 37 .bind(kShadowColor_Index, adapter->fColor ) 38 .bind( kOpacity_Index, adapter->fOpacity ) 39 .bind( kDirection_Index, adapter->fDirection) 40 .bind( kDistance_Index, adapter->fDistance ) 41 .bind( kSoftness_Index, adapter->fSoftness ) 42 .bind( kShadowOnly_Index, adapter->fShdwOnly ); 43 44 return adapter; 45 } 46 47 const sk_sp<sksg::RenderNode>& node() const { return fImageFilterEffect; } 48 49private: 50 explicit DropShadowAdapter(sk_sp<sksg::RenderNode> layer) 51 : fDropShadow(sksg::DropShadowImageFilter::Make()) 52 , fImageFilterEffect(sksg::ImageFilterEffect::Make(std::move(layer), fDropShadow)) {} 53 54 void onSync() override { 55 // fColor -> RGB, fOpacity -> A 56 const SkColor color = fColor; 57 fDropShadow->setColor(SkColorSetA(color, SkTPin(SkScalarRoundToInt(fOpacity), 0, 255))); 58 59 // The offset is specified in terms of a bearing + distance. 60 const auto rad = SkDegreesToRadians(90 - fDirection); 61 fDropShadow->setOffset(SkVector::Make( fDistance * SkScalarCos(rad), 62 -fDistance * SkScalarSin(rad))); 63 64 const auto sigma = fSoftness * kBlurSizeToSigma; 65 fDropShadow->setSigma(SkVector::Make(sigma, sigma)); 66 67 fDropShadow->setMode(SkToBool(fShdwOnly) 68 ? sksg::DropShadowImageFilter::Mode::kShadowOnly 69 : sksg::DropShadowImageFilter::Mode::kShadowAndForeground); 70 } 71 72 const sk_sp<sksg::DropShadowImageFilter> fDropShadow; 73 const sk_sp<sksg::RenderNode> fImageFilterEffect; 74 75 VectorValue fColor = { 0, 0, 0, 1 }; 76 ScalarValue fOpacity = 255, 77 fDirection = 0, 78 fDistance = 0, 79 fSoftness = 0, 80 fShdwOnly = 0; 81}; 82 83} // namespace 84 85sk_sp<sksg::RenderNode> EffectBuilder::attachDropShadowEffect(const skjson::ArrayValue& jprops, 86 sk_sp<sksg::RenderNode> layer) const { 87 return fBuilder->attachDiscardableAdapter<DropShadowAdapter>(jprops, 88 std::move(layer), 89 *fBuilder); 90} 91 92} // namespace internal 93} // namespace skottie 94