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/base/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, std::size(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, std::size(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