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