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