xref: /aosp_15_r20/external/skia/modules/skottie/src/animator/KeyframeAnimator.h (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 #ifndef SkottieKeyframeAnimator_DEFINED
9 #define SkottieKeyframeAnimator_DEFINED
10 
11 #include "include/core/SkCubicMap.h"
12 #include "include/core/SkPoint.h"
13 #include "include/core/SkRefCnt.h"
14 #include "include/private/base/SkAssert.h"
15 #include "include/private/base/SkNoncopyable.h"
16 #include "modules/skottie/src/animator/Animator.h"
17 
18 #include <cstdint>
19 #include <utility>
20 #include <vector>
21 
22 namespace skjson {
23 class ArrayValue;
24 class ObjectValue;
25 class Value;
26 } // namespace skjson
27 
28 namespace skottie {
29 class ExpressionManager;
30 }
31 
32 namespace skottie::internal {
33 
34 class AnimationBuilder;
35 
36 struct Keyframe {
37     // We can store scalar values inline; other types are stored externally,
38     // and we track them by index.
39     struct Value {
40         enum class Type {
41             kIndex,
42             kScalar,
43         };
44 
45         union {
46             uint32_t idx;
47             float    flt;
48         };
49 
equalsKeyframe::Value50         bool equals(const Value& other, Type ty) const {
51             return ty == Type::kIndex
52                 ? idx == other.idx
53                 : flt == other.flt;
54         }
55     };
56 
57     float    t;
58     Value    v;
59     uint32_t mapping; // Encodes the value interpolation in [KFRec_n .. KFRec_n+1):
60                       //   0 -> constant
61                       //   1 -> linear
62                       //   n -> cubic: cubic_mappers[n-2]
63 
64     inline static constexpr uint32_t kConstantMapping  = 0;
65     inline static constexpr uint32_t kLinearMapping    = 1;
66     inline static constexpr uint32_t kCubicIndexOffset = 2;
67 };
68 
69 class KeyframeAnimator : public Animator {
70 public:
71     ~KeyframeAnimator() override;
72 
isConstant()73     bool isConstant() const {
74         SkASSERT(!fKFs.empty());
75 
76         // parseKeyFrames() ensures we only keep a single frame for constant properties.
77         return fKFs.size() == 1;
78     }
79 
80 protected:
KeyframeAnimator(std::vector<Keyframe> kfs,std::vector<SkCubicMap> cms)81     KeyframeAnimator(std::vector<Keyframe> kfs, std::vector<SkCubicMap> cms)
82         : fKFs(std::move(kfs))
83         , fCMs(std::move(cms)) {}
84 
85     struct LERPInfo {
86         float           weight; // vrec0/vrec1 weight [0..1]
87         Keyframe::Value vrec0, vrec1;
88     };
89 
90     // Main entry point: |t| -> LERPInfo
91     LERPInfo getLERPInfo(float t) const;
92 
93 private:
94     // Two sequential KFRecs determine how the value varies within [kf0 .. kf1)
95     struct KFSegment {
96         const Keyframe* kf0;
97         const Keyframe* kf1;
98 
containsKFSegment99         bool contains(float t) const {
100             SkASSERT(!!kf0 == !!kf1);
101             SkASSERT(!kf0 || kf1 == kf0 + 1);
102 
103             return kf0 && kf0->t <= t && t < kf1->t;
104         }
105     };
106 
107     // Find the KFSegment containing |t|.
108     KFSegment find_segment(float t) const;
109 
110     // Given a |t| and a containing KFSegment, compute the local interpolation weight.
111     float compute_weight(const KFSegment& seg, float t) const;
112 
113     const std::vector<Keyframe>   fKFs; // Keyframe records, one per AE/Lottie keyframe.
114     const std::vector<SkCubicMap> fCMs; // Optional cubic mappers (Bezier interpolation).
115     mutable KFSegment             fCurrentSegment = { nullptr, nullptr }; // Cached segment.
116 };
117 
118 class AnimatorBuilder : public SkNoncopyable {
119 public:
120     virtual ~AnimatorBuilder();
121 
122     virtual sk_sp<KeyframeAnimator> makeFromKeyframes(const AnimationBuilder&,
123                                                       const skjson::ArrayValue&) = 0;
124 
125     virtual sk_sp<Animator> makeFromExpression(ExpressionManager&, const char*) = 0;
126 
127     virtual bool parseValue(const AnimationBuilder&, const skjson::Value&) const = 0;
128 
129 protected:
AnimatorBuilder(Keyframe::Value::Type ty)130     explicit AnimatorBuilder(Keyframe::Value::Type ty)
131         : keyframe_type(ty) {}
132 
133     virtual bool parseKFValue(const AnimationBuilder&,
134                               const skjson::ObjectValue&,
135                               const skjson::Value&,
136                               Keyframe::Value*) = 0;
137 
138     bool parseKeyframes(const AnimationBuilder&, const skjson::ArrayValue&);
139 
140     std::vector<Keyframe>   fKFs; // Keyframe records, one per AE/Lottie keyframe.
141     std::vector<SkCubicMap> fCMs; // Optional cubic mappers (Bezier interpolation).
142 
143 private:
144     uint32_t parseMapping(const skjson::ObjectValue&);
145 
146     const Keyframe::Value::Type keyframe_type;
147 
148     // Track previous cubic map parameters (for deduping).
149     SkPoint                     prev_c0 = { 0, 0 },
150                                 prev_c1 = { 0, 0 };
151 };
152 
153 template <typename T>
Lerp(const T & a,const T & b,float t)154 T Lerp(const T& a, const T& b, float t) { return a + (b - a) * t; }
155 
156 } // namespace skottie::internal
157 
158 #endif // SkottieKeyframeAnimator_DEFINED
159