• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "modules/skottie/src/SkottieAdapter.h"
11 #include "modules/skottie/src/SkottieValue.h"
12 #include "modules/sksg/include/SkSGRenderEffect.h"
13 #include "src/utils/SkJSON.h"
14 
15 namespace skottie {
16 namespace internal {
17 
18 namespace  {
19 
20 class DropShadowAdapter final : public SkNVRefCnt<DropShadowAdapter> {
21 public:
DropShadowAdapter(sk_sp<sksg::DropShadowImageFilter> dropShadow)22     explicit DropShadowAdapter(sk_sp<sksg::DropShadowImageFilter> dropShadow)
23         : fDropShadow(std::move(dropShadow)) {
24         SkASSERT(fDropShadow);
25     }
26 
27     ADAPTER_PROPERTY(Color     , SkColor , SK_ColorBLACK)
28     ADAPTER_PROPERTY(Opacity   , SkScalar,           255)
29     ADAPTER_PROPERTY(Direction , SkScalar,             0)
30     ADAPTER_PROPERTY(Distance  , SkScalar,             0)
31     ADAPTER_PROPERTY(Softness  , SkScalar,             0)
32     ADAPTER_PROPERTY(ShadowOnly, bool    ,         false)
33 
34 private:
apply()35     void apply() {
36         // fColor -> RGB, fOpacity -> A
37         fDropShadow->setColor(SkColorSetA(fColor, SkTPin(SkScalarRoundToInt(fOpacity), 0, 255)));
38 
39         // The offset is specified in terms of a bearing angle + distance.
40         SkScalar rad = SkDegreesToRadians(90 - fDirection);
41         fDropShadow->setOffset(SkVector::Make( fDistance * SkScalarCos(rad),
42                                               -fDistance * SkScalarSin(rad)));
43 
44         // Close enough to AE.
45         static constexpr SkScalar kSoftnessToSigmaFactor = 0.3f;
46         const auto sigma = fSoftness * kSoftnessToSigmaFactor;
47         fDropShadow->setSigma(SkVector::Make(sigma, sigma));
48 
49         fDropShadow->setMode(fShadowOnly ? sksg::DropShadowImageFilter::Mode::kShadowOnly
50                                          : sksg::DropShadowImageFilter::Mode::kShadowAndForeground);
51     }
52 
53     const sk_sp<sksg::DropShadowImageFilter> fDropShadow;
54 };
55 
56 } // anonymous ns
57 
attachDropShadowEffect(const skjson::ArrayValue & jprops,sk_sp<sksg::RenderNode> layer) const58 sk_sp<sksg::RenderNode> EffectBuilder::attachDropShadowEffect(const skjson::ArrayValue& jprops,
59                                                               sk_sp<sksg::RenderNode> layer) const {
60     enum : size_t {
61         kShadowColor_Index = 0,
62         kOpacity_Index     = 1,
63         kDirection_Index   = 2,
64         kDistance_Index    = 3,
65         kSoftness_Index    = 4,
66         kShadowOnly_Index  = 5,
67     };
68 
69     auto shadow_effect  = sksg::DropShadowImageFilter::Make();
70     auto shadow_adapter = sk_make_sp<DropShadowAdapter>(shadow_effect);
71 
72     fBuilder->bindProperty<VectorValue>(GetPropValue(jprops, kShadowColor_Index),
73         [shadow_adapter](const VectorValue& c) {
74             shadow_adapter->setColor(ValueTraits<VectorValue>::As<SkColor>(c));
75         });
76     fBuilder->bindProperty<ScalarValue>(GetPropValue(jprops, kOpacity_Index),
77         [shadow_adapter](const ScalarValue& o) {
78             shadow_adapter->setOpacity(o);
79         });
80     fBuilder->bindProperty<ScalarValue>(GetPropValue(jprops, kDirection_Index),
81         [shadow_adapter](const ScalarValue& d) {
82             shadow_adapter->setDirection(d);
83         });
84     fBuilder->bindProperty<ScalarValue>(GetPropValue(jprops, kDistance_Index),
85         [shadow_adapter](const ScalarValue& d) {
86             shadow_adapter->setDistance(d);
87         });
88     fBuilder->bindProperty<ScalarValue>(GetPropValue(jprops, kSoftness_Index),
89         [shadow_adapter](const ScalarValue& s) {
90             shadow_adapter->setSoftness(s);
91         });
92     fBuilder->bindProperty<ScalarValue>(GetPropValue(jprops, kShadowOnly_Index),
93         [shadow_adapter](const ScalarValue& s) {
94             shadow_adapter->setShadowOnly(SkToBool(s));
95         });
96 
97     return sksg::ImageFilterEffect::Make(std::move(layer), std::move(shadow_effect));
98 }
99 
100 } // namespace internal
101 } // namespace skottie
102