xref: /aosp_15_r20/external/skia/modules/skottie/src/effects/GaussianBlurEffect.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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 "include/core/SkPoint.h"
9 #include "include/core/SkRefCnt.h"
10 #include "include/core/SkTileMode.h"
11 #include "include/private/base/SkTPin.h"
12 #include "modules/skottie/src/SkottiePriv.h"
13 #include "modules/skottie/src/SkottieValue.h"
14 #include "modules/skottie/src/animator/Animator.h"
15 #include "modules/skottie/src/effects/Effects.h"
16 #include "modules/sksg/include/SkSGRenderEffect.h"
17 #include "modules/sksg/include/SkSGRenderNode.h"
18 
19 #include <array>
20 #include <cstddef>
21 #include <utility>
22 
23 namespace skjson {
24 class ArrayValue;
25 }
26 
27 namespace skottie {
28 namespace internal {
29 
30 namespace  {
31 
32 class GaussianBlurEffectAdapter final : public AnimatablePropertyContainer {
33 public:
Make(const skjson::ArrayValue & jprops,sk_sp<sksg::RenderNode> layer,const AnimationBuilder * abuilder)34     static sk_sp<GaussianBlurEffectAdapter> Make(const skjson::ArrayValue& jprops,
35                                                  sk_sp<sksg::RenderNode> layer,
36                                                  const AnimationBuilder* abuilder) {
37         return sk_sp<GaussianBlurEffectAdapter>(new GaussianBlurEffectAdapter(jprops,
38                                                                               std::move(layer),
39                                                                               abuilder));
40     }
41 
node() const42     const sk_sp<sksg::RenderNode>& node() const { return fImageFilterEffect; }
43 
44 private:
GaussianBlurEffectAdapter(const skjson::ArrayValue & jprops,sk_sp<sksg::RenderNode> layer,const AnimationBuilder * abuilder)45     GaussianBlurEffectAdapter(const skjson::ArrayValue& jprops,
46                               sk_sp<sksg::RenderNode> layer,
47                               const AnimationBuilder* abuilder)
48         : fBlur(sksg::BlurImageFilter::Make())
49         , fImageFilterEffect(sksg::ImageFilterEffect::Make(std::move(layer), fBlur)) {
50         enum : size_t {
51             kBlurriness_Index = 0,
52             kDimensions_Index = 1,
53             kRepeatEdge_Index = 2,
54         };
55 
56         EffectBinder(jprops, *abuilder, this)
57                 .bind(kBlurriness_Index, fBlurriness)
58                 .bind(kDimensions_Index, fDimensions)
59                 .bind(kRepeatEdge_Index, fRepeatEdge);
60     }
61 
onSync()62     void onSync() override {
63         static constexpr SkVector kDimensionsMap[] = {
64             { 1, 1 }, // 1 -> horizontal and vertical
65             { 1, 0 }, // 2 -> horizontal
66             { 0, 1 }, // 3 -> vertical
67         };
68 
69         const auto dim_index = SkTPin<size_t>(static_cast<size_t>(fDimensions),
70                                               1, std::size(kDimensionsMap)) - 1;
71 
72         const auto sigma = fBlurriness * kBlurSizeToSigma;
73 
74         fBlur->setSigma({ sigma * kDimensionsMap[dim_index].x(),
75                           sigma * kDimensionsMap[dim_index].y() });
76 
77         // 0 -> repeat edge pixels: off
78         // 1 -> repeat edge pixels: on
79         const auto repeat_edge = static_cast<bool>(fRepeatEdge);
80 
81         // Repeat edge pixels implies two things:
82         //  - the blur uses kClamp tiling
83         //  - the output is cropped to content size
84         fBlur->setTileMode(repeat_edge
85             ? SkTileMode::kClamp
86             : SkTileMode::kDecal);
87         static_cast<sksg::ImageFilterEffect*>(fImageFilterEffect.get())->setCropping(repeat_edge
88             ? sksg::ImageFilterEffect::Cropping::kContent
89             : sksg::ImageFilterEffect::Cropping::kNone);
90     }
91 
92     const sk_sp<sksg::BlurImageFilter> fBlur;
93     const sk_sp<sksg::RenderNode>      fImageFilterEffect;
94 
95     ScalarValue fBlurriness = 0, // Controls the blur sigma.
96                 fDimensions = 1, // 1 -> horizontal & vertical, 2 -> horizontal, 3 -> vertical
97                 fRepeatEdge = 0; // 0 -> clamp, 1 -> repeat
98 };
99 
100 }  // namespace
101 
attachGaussianBlurEffect(const skjson::ArrayValue & jprops,sk_sp<sksg::RenderNode> layer) const102 sk_sp<sksg::RenderNode> EffectBuilder::attachGaussianBlurEffect(
103         const skjson::ArrayValue& jprops,
104         sk_sp<sksg::RenderNode> layer) const {
105     return fBuilder->attachDiscardableAdapter<GaussianBlurEffectAdapter>(jprops,
106                                                                          std::move(layer),
107                                                                          fBuilder);
108 }
109 
110 } // namespace internal
111 } // namespace skottie
112