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 "modules/skottie/src/SkottieJson.h"
9 #include "modules/skottie/src/SkottieValue.h"
10 #include "modules/skottie/src/animator/Animator.h"
11 #include "modules/skottie/src/animator/KeyframeAnimator.h"
12 
13 namespace skottie::internal {
14 
15 namespace  {
16 
17 // Scalar specialization: stores scalar values (floats) inline in keyframes.
18 class ScalarKeyframeAnimator final : public KeyframeAnimator {
19 public:
20     class Builder final : public KeyframeAnimatorBuilder {
21     public:
Builder(ScalarValue * target)22         explicit Builder(ScalarValue* target) : fTarget(target) {}
23 
make(const AnimationBuilder & abuilder,const skjson::ArrayValue & jkfs)24         sk_sp<KeyframeAnimator> make(const AnimationBuilder& abuilder,
25                                      const skjson::ArrayValue& jkfs) override {
26             SkASSERT(jkfs.size() > 0);
27             if (!this->parseKeyframes(abuilder, jkfs)) {
28                 return nullptr;
29             }
30 
31             return sk_sp<ScalarKeyframeAnimator>(
32                         new ScalarKeyframeAnimator(std::move(fKFs), std::move(fCMs), fTarget));
33         }
34 
parseValue(const AnimationBuilder &,const skjson::Value & jv) const35         bool parseValue(const AnimationBuilder&, const skjson::Value& jv) const override {
36             return Parse(jv, fTarget);
37         }
38 
39     private:
parseKFValue(const AnimationBuilder &,const skjson::ObjectValue &,const skjson::Value & jv,Keyframe::Value * v)40         bool parseKFValue(const AnimationBuilder&,
41                           const skjson::ObjectValue&,
42                           const skjson::Value& jv,
43                           Keyframe::Value* v) override {
44             return Parse(jv, &v->flt);
45         }
46 
47         ScalarValue* fTarget;
48     };
49 
50 private:
ScalarKeyframeAnimator(std::vector<Keyframe> kfs,std::vector<SkCubicMap> cms,ScalarValue * target_value)51     ScalarKeyframeAnimator(std::vector<Keyframe> kfs,
52                            std::vector<SkCubicMap> cms,
53                            ScalarValue* target_value)
54         : INHERITED(std::move(kfs), std::move(cms))
55         , fTarget(target_value) {}
56 
onSeek(float t)57     StateChanged onSeek(float t) override {
58         const auto& lerp_info = this->getLERPInfo(t);
59         const auto  old_value = *fTarget;
60 
61         *fTarget = Lerp(lerp_info.vrec0.flt, lerp_info.vrec1.flt, lerp_info.weight);
62 
63         return *fTarget != old_value;
64     }
65 
66     ScalarValue* fTarget;
67 
68     using INHERITED = KeyframeAnimator;
69 };
70 
71 } // namespace
72 
73 template <>
bind(const AnimationBuilder & abuilder,const skjson::ObjectValue * jprop,ScalarValue * v)74 bool AnimatablePropertyContainer::bind<ScalarValue>(const AnimationBuilder& abuilder,
75                                                     const skjson::ObjectValue* jprop,
76                                                     ScalarValue* v) {
77     ScalarKeyframeAnimator::Builder builder(v);
78 
79     return this->bindImpl(abuilder, jprop, builder);
80 }
81 
82 } // namespace skottie::internal
83