xref: /aosp_15_r20/external/skia/modules/skottie/src/effects/TransformEffect.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/SkScalar.h"
11 #include "modules/skottie/src/Adapter.h"
12 #include "modules/skottie/src/SkottiePriv.h"
13 #include "modules/skottie/src/SkottieValue.h"
14 #include "modules/skottie/src/Transform.h"
15 #include "modules/skottie/src/animator/Animator.h"
16 #include "modules/skottie/src/effects/Effects.h"
17 #include "modules/sksg/include/SkSGOpacityEffect.h"
18 #include "modules/sksg/include/SkSGRenderNode.h"
19 #include "modules/sksg/include/SkSGTransform.h"
20 
21 #include <cstddef>
22 #include <utility>
23 
24 namespace skjson {
25 class ArrayValue;
26 class ObjectValue;
27 }  // namespace skjson
28 
29 namespace skottie {
30 namespace internal {
31 
32 namespace  {
33 
34 class TransformEffectAdapter final : public DiscardableAdapterBase<TransformEffectAdapter,
35                                                                    sksg::OpacityEffect> {
36 public:
TransformEffectAdapter(const AnimationBuilder & abuilder,const skjson::ObjectValue * jopacity,const skjson::ObjectValue * jscale_uniform,const skjson::ObjectValue * jscale_width,const skjson::ObjectValue * jscale_height,sk_sp<TransformAdapter2D> tadapter,sk_sp<sksg::RenderNode> child)37     TransformEffectAdapter(const AnimationBuilder& abuilder,
38                            const skjson::ObjectValue* jopacity,
39                            const skjson::ObjectValue* jscale_uniform,
40                            const skjson::ObjectValue* jscale_width,
41                            const skjson::ObjectValue* jscale_height,
42                            sk_sp<TransformAdapter2D> tadapter,
43                            sk_sp<sksg::RenderNode> child)
44         : INHERITED(sksg::OpacityEffect::Make(std::move(child)))
45         , fTransformAdapter(std::move(tadapter)) {
46         this->bind(abuilder, jopacity      , fOpacity     );
47         this->bind(abuilder, jscale_uniform, fUniformScale);
48         this->bind(abuilder, jscale_width  , fScaleWidth  );
49         this->bind(abuilder, jscale_height , fScaleHeight );
50 
51         this->attachDiscardableAdapter(fTransformAdapter);
52     }
53 
54 private:
onSync()55     void onSync() override {
56         this->node()->setOpacity(fOpacity * 0.01f);
57 
58         // In uniform mode, the scale is based solely in ScaleHeight.
59         const auto scale = SkVector::Make(SkScalarRoundToInt(fUniformScale) ? fScaleHeight
60                                                                             : fScaleWidth,
61                                           fScaleHeight);
62 
63         // NB: this triggers an transform adapter -> SG sync.
64         fTransformAdapter->setScale(scale);
65     }
66 
67     const sk_sp<TransformAdapter2D> fTransformAdapter;
68 
69     ScalarValue fOpacity      = 100,
70                 fUniformScale =   0, // bool
71                 fScaleWidth   = 100,
72                 fScaleHeight  = 100;
73 
74     using INHERITED = DiscardableAdapterBase<TransformEffectAdapter, sksg::OpacityEffect>;
75 };
76 
77 }  // namespace
78 
attachTransformEffect(const skjson::ArrayValue & jprops,sk_sp<sksg::RenderNode> layer) const79 sk_sp<sksg::RenderNode> EffectBuilder::attachTransformEffect(const skjson::ArrayValue& jprops,
80                                                              sk_sp<sksg::RenderNode> layer) const {
81     enum : size_t {
82         kAnchorPoint_Index            =  0,
83         kPosition_Index               =  1,
84         kUniformScale_Index           =  2,
85         kScaleHeight_Index            =  3,
86         kScaleWidth_Index             =  4,
87         kSkew_Index                   =  5,
88         kSkewAxis_Index               =  6,
89         kRotation_Index               =  7,
90         kOpacity_Index                =  8,
91         // kUseCompShutterAngle_Index =  9,
92         // kShutterAngle_Index        = 10,
93         // kSampling_Index            = 11,
94     };
95 
96     auto transform_adapter = TransformAdapter2D::Make(*fBuilder,
97                                                       GetPropValue(jprops, kAnchorPoint_Index),
98                                                       GetPropValue(jprops, kPosition_Index),
99                                                       nullptr, // scale is handled externally
100                                                       GetPropValue(jprops, kRotation_Index),
101                                                       GetPropValue(jprops, kSkew_Index),
102                                                       GetPropValue(jprops, kSkewAxis_Index));
103     if (!transform_adapter) {
104         return nullptr;
105     }
106 
107     auto transform_effect_node = sksg::TransformEffect::Make(std::move(layer),
108                                                              transform_adapter->node());
109     return fBuilder->attachDiscardableAdapter<TransformEffectAdapter>
110             (*fBuilder,
111              GetPropValue(jprops, kOpacity_Index),
112              GetPropValue(jprops, kUniformScale_Index),
113              GetPropValue(jprops, kScaleWidth_Index),
114              GetPropValue(jprops, kScaleHeight_Index),
115              std::move(transform_adapter),
116              std::move(transform_effect_node)
117              );
118 }
119 
120 } // namespace internal
121 } // namespace skottie
122