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 
15 namespace skottie {
16 namespace internal {
17 
18 namespace  {
19 
20 class GaussianBlurEffectAdapter final : public AnimatablePropertyContainer {
21 public:
Make(const skjson::ArrayValue & jprops,sk_sp<sksg::RenderNode> layer,const AnimationBuilder * abuilder)22     static sk_sp<GaussianBlurEffectAdapter> Make(const skjson::ArrayValue& jprops,
23                                                  sk_sp<sksg::RenderNode> layer,
24                                                  const AnimationBuilder* abuilder) {
25         return sk_sp<GaussianBlurEffectAdapter>(new GaussianBlurEffectAdapter(jprops,
26                                                                               std::move(layer),
27                                                                               abuilder));
28     }
29 
node() const30     const sk_sp<sksg::RenderNode>& node() const { return fImageFilterEffect; }
31 
32 private:
GaussianBlurEffectAdapter(const skjson::ArrayValue & jprops,sk_sp<sksg::RenderNode> layer,const AnimationBuilder * abuilder)33     GaussianBlurEffectAdapter(const skjson::ArrayValue& jprops,
34                               sk_sp<sksg::RenderNode> layer,
35                               const AnimationBuilder* abuilder)
36         : fBlur(sksg::BlurImageFilter::Make())
37         , fImageFilterEffect(sksg::ImageFilterEffect::Make(std::move(layer), fBlur)) {
38         enum : size_t {
39             kBlurriness_Index = 0,
40             kDimensions_Index = 1,
41             kRepeatEdge_Index = 2,
42         };
43 
44         EffectBinder(jprops, *abuilder, this)
45                 .bind(kBlurriness_Index, fBlurriness)
46                 .bind(kDimensions_Index, fDimensions)
47                 .bind(kRepeatEdge_Index, fRepeatEdge);
48     }
49 
onSync()50     void onSync() override {
51         static constexpr SkVector kDimensionsMap[] = {
52             { 1, 1 }, // 1 -> horizontal and vertical
53             { 1, 0 }, // 2 -> horizontal
54             { 0, 1 }, // 3 -> vertical
55         };
56 
57         const auto dim_index = SkTPin<size_t>(static_cast<size_t>(fDimensions),
58                                               1, SK_ARRAY_COUNT(kDimensionsMap)) - 1;
59 
60         const auto sigma = fBlurriness * kBlurSizeToSigma;
61 
62         fBlur->setSigma({ sigma * kDimensionsMap[dim_index].x(),
63                           sigma * kDimensionsMap[dim_index].y() });
64 
65         static constexpr SkTileMode kRepeatEdgeMap[] = {
66             SkTileMode::kDecal, // 0 -> repeat edge pixels: off
67             SkTileMode::kClamp, // 1 -> repeat edge pixels: on
68         };
69 
70         const auto repeat_index = SkTPin<size_t>(static_cast<size_t>(fRepeatEdge),
71                                                  0, SK_ARRAY_COUNT(kRepeatEdgeMap) - 1);
72         fBlur->setTileMode(kRepeatEdgeMap[repeat_index]);
73     }
74 
75     const sk_sp<sksg::BlurImageFilter> fBlur;
76     const sk_sp<sksg::RenderNode>      fImageFilterEffect;
77 
78     ScalarValue fBlurriness = 0, // Controls the blur sigma.
79                 fDimensions = 1, // 1 -> horizontal & vertical, 2 -> horizontal, 3 -> vertical
80                 fRepeatEdge = 0; // 0 -> clamp, 1 -> repeat
81 };
82 
83 }  // namespace
84 
attachGaussianBlurEffect(const skjson::ArrayValue & jprops,sk_sp<sksg::RenderNode> layer) const85 sk_sp<sksg::RenderNode> EffectBuilder::attachGaussianBlurEffect(
86         const skjson::ArrayValue& jprops,
87         sk_sp<sksg::RenderNode> layer) const {
88     return fBuilder->attachDiscardableAdapter<GaussianBlurEffectAdapter>(jprops,
89                                                                          std::move(layer),
90                                                                          fBuilder);
91 }
92 
93 } // namespace internal
94 } // namespace skottie
95