xref: /aosp_15_r20/external/skia/modules/skottie/src/animator/ScalarKeyframeAnimator.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1 /*
2  * Copyright 2020 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/SkCubicMap.h"
9 #include "include/core/SkRefCnt.h"
10 #include "include/core/SkString.h"
11 #include "include/private/base/SkAssert.h"
12 #include "modules/skottie/include/Skottie.h"
13 #include "modules/skottie/include/SlotManager.h"
14 #include "modules/skottie/src/SkottieJson.h"
15 #include "modules/skottie/src/SkottiePriv.h"
16 #include "modules/skottie/src/SkottieValue.h"
17 #include "modules/skottie/src/animator/Animator.h"
18 #include "modules/skottie/src/animator/KeyframeAnimator.h"
19 #include "src/utils/SkJSON.h"
20 
21 #include <utility>
22 #include <vector>
23 
24 namespace skottie::internal {
25 
26 namespace  {
27 
28     // Scalar specialization: stores scalar values (floats) inline in keyframes.
29 class ScalarKeyframeAnimator final : public KeyframeAnimator {
30 public:
ScalarKeyframeAnimator(std::vector<Keyframe> kfs,std::vector<SkCubicMap> cms,ScalarValue * target_value)31     ScalarKeyframeAnimator(std::vector<Keyframe> kfs,
32                            std::vector<SkCubicMap> cms,
33                            ScalarValue* target_value)
34         : INHERITED(std::move(kfs), std::move(cms))
35         , fTarget(target_value) {}
36 
37 private:
38 
onSeek(float t)39     StateChanged onSeek(float t) override {
40         const auto& lerp_info = this->getLERPInfo(t);
41         const auto  old_value = *fTarget;
42 
43         *fTarget = Lerp(lerp_info.vrec0.flt, lerp_info.vrec1.flt, lerp_info.weight);
44 
45         return *fTarget != old_value;
46     }
47 
48     ScalarValue* fTarget;
49 
50     using INHERITED = KeyframeAnimator;
51 };
52 
53     // Scalar specialization: stores scalar values (floats).
54 class ScalarExpressionAnimator final : public Animator {
55 public:
ScalarExpressionAnimator(sk_sp<ExpressionEvaluator<ScalarValue>> expression_evaluator,ScalarValue * target_value)56     ScalarExpressionAnimator(sk_sp<ExpressionEvaluator<ScalarValue>> expression_evaluator,
57         ScalarValue* target_value)
58         : fExpressionEvaluator(std::move(expression_evaluator))
59         , fTarget(target_value) {}
60 
61 private:
62 
onSeek(float t)63     StateChanged onSeek(float t) override {
64         auto old_value = *fTarget;
65 
66         *fTarget = fExpressionEvaluator->evaluate(t);
67 
68         return *fTarget != old_value;
69     }
70 
71     sk_sp<ExpressionEvaluator<ScalarValue>> fExpressionEvaluator;
72     ScalarValue* fTarget;
73 };
74 
75 class ScalarAnimatorBuilder final : public AnimatorBuilder {
76     public:
ScalarAnimatorBuilder(ScalarValue * target)77         explicit ScalarAnimatorBuilder(ScalarValue* target)
78             : INHERITED(Keyframe::Value::Type::kScalar)
79             , fTarget(target) {}
80 
makeFromKeyframes(const AnimationBuilder & abuilder,const skjson::ArrayValue & jkfs)81         sk_sp<KeyframeAnimator> makeFromKeyframes(const AnimationBuilder& abuilder,
82                                      const skjson::ArrayValue& jkfs) override {
83             SkASSERT(jkfs.size() > 0);
84             if (!this->parseKeyframes(abuilder, jkfs)) {
85                 return nullptr;
86             }
87 
88             return sk_sp<ScalarKeyframeAnimator>(
89                         new ScalarKeyframeAnimator(std::move(fKFs), std::move(fCMs), fTarget));
90         }
91 
makeFromExpression(ExpressionManager & em,const char * expr)92         sk_sp<Animator> makeFromExpression(ExpressionManager& em, const char* expr) override {
93             sk_sp<ExpressionEvaluator<ScalarValue>> expression_evaluator =
94                 em.createNumberExpressionEvaluator(expr);
95             return sk_make_sp<ScalarExpressionAnimator>(expression_evaluator, fTarget);
96         }
97 
98 
parseValue(const AnimationBuilder &,const skjson::Value & jv) const99         bool parseValue(const AnimationBuilder&, const skjson::Value& jv) const override {
100             return ::skottie::Parse(jv, fTarget);
101         }
102 
103     private:
parseKFValue(const AnimationBuilder &,const skjson::ObjectValue &,const skjson::Value & jv,Keyframe::Value * v)104         bool parseKFValue(const AnimationBuilder&,
105                           const skjson::ObjectValue&,
106                           const skjson::Value& jv,
107                           Keyframe::Value* v) override {
108             return ::skottie::Parse(jv, &v->flt);
109         }
110 
111         ScalarValue* fTarget;
112 
113         using INHERITED = AnimatorBuilder;
114     };
115 
116 } // namespace
117 
118 template <>
bind(const AnimationBuilder & abuilder,const skjson::ObjectValue * jprop,ScalarValue * v)119 bool AnimatablePropertyContainer::bind<ScalarValue>(const AnimationBuilder& abuilder,
120                                                     const skjson::ObjectValue* jprop,
121                                                     ScalarValue* v) {
122     if (const auto* sid = ParseSlotID(jprop)) {
123         fHasSlotID = true;
124         abuilder.fSlotManager->trackScalarValue(SkString(sid->begin()), v, sk_ref_sp(this));
125     }
126     ScalarAnimatorBuilder builder(v);
127 
128     return this->bindImpl(abuilder, jprop, builder);
129 }
130 
131 } // namespace skottie::internal
132