• 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 #include "modules/skottie/src/SkottieJson.h"
9 #include "modules/skottie/src/SkottieValue.h"
10 #include "modules/skottie/src/animator/KeyframeAnimator.h"
11 #include "modules/skottie/src/text/TextValue.h"
12 
13 namespace skottie::internal {
14 
15 namespace  {
16 class TextKeyframeAnimator final : public KeyframeAnimator {
17 public:
TextKeyframeAnimator(std::vector<Keyframe> kfs,std::vector<SkCubicMap> cms,std::vector<TextValue> vs,TextValue * target_value)18     TextKeyframeAnimator(std::vector<Keyframe> kfs, std::vector<SkCubicMap> cms,
19                          std::vector<TextValue> vs, TextValue* target_value)
20         : INHERITED(std::move(kfs), std::move(cms))
21         , fValues(std::move(vs))
22         , fTarget(target_value) {}
23 
24 private:
onSeek(float t)25     StateChanged onSeek(float t) override {
26         const auto& lerp_info = this->getLERPInfo(t);
27 
28         // Text value keyframes are treated as selectors, not as interpolated values.
29         if (*fTarget != fValues[SkToSizeT(lerp_info.vrec0.idx)]) {
30             *fTarget = fValues[SkToSizeT(lerp_info.vrec0.idx)];
31             return true;
32         }
33 
34         return false;
35     }
36 
37     const std::vector<TextValue> fValues;
38     TextValue*                   fTarget;
39 
40     using INHERITED = KeyframeAnimator;
41 };
42 
43 class TextExpressionAnimator final : public Animator {
44 public:
TextExpressionAnimator(sk_sp<ExpressionEvaluator<SkString>> expression_evaluator,TextValue * target_value)45     TextExpressionAnimator(sk_sp<ExpressionEvaluator<SkString>> expression_evaluator,
46         TextValue* target_value)
47         : fExpressionEvaluator(std::move(expression_evaluator))
48         , fTarget(target_value) {}
49 
50 private:
51 
onSeek(float t)52     StateChanged onSeek(float t) override {
53         SkString old_value = fTarget->fText;
54 
55         fTarget->fText = fExpressionEvaluator->evaluate(t);
56 
57         return fTarget->fText != old_value;
58     }
59 
60     sk_sp<ExpressionEvaluator<SkString>> fExpressionEvaluator;
61     TextValue* fTarget;
62 };
63 
64 class TextAnimatorBuilder final : public AnimatorBuilder {
65 public:
TextAnimatorBuilder(TextValue * target)66     explicit TextAnimatorBuilder(TextValue* target)
67         : INHERITED(Keyframe::Value::Type::kIndex)
68         , fTarget(target) {}
69 
makeFromKeyframes(const AnimationBuilder & abuilder,const skjson::ArrayValue & jkfs)70     sk_sp<KeyframeAnimator> makeFromKeyframes(const AnimationBuilder& abuilder,
71                                     const skjson::ArrayValue& jkfs) override {
72         SkASSERT(jkfs.size() > 0);
73 
74         fValues.reserve(jkfs.size());
75         if (!this->parseKeyframes(abuilder, jkfs)) {
76             return nullptr;
77         }
78         fValues.shrink_to_fit();
79 
80         return sk_sp<TextKeyframeAnimator>(
81                     new TextKeyframeAnimator(std::move(fKFs),
82                                                 std::move(fCMs),
83                                                 std::move(fValues),
84                                                 fTarget));
85     }
86 
makeFromExpression(ExpressionManager & em,const char * expr)87     sk_sp<Animator> makeFromExpression(ExpressionManager& em, const char* expr) override {
88          sk_sp<ExpressionEvaluator<SkString>> expression_evaluator =
89                 em.createStringExpressionEvaluator(expr);
90             return sk_make_sp<TextExpressionAnimator>(expression_evaluator, fTarget);
91     }
92 
parseValue(const AnimationBuilder & abuilder,const skjson::Value & jv) const93     bool parseValue(const AnimationBuilder& abuilder, const skjson::Value& jv) const override {
94         return Parse(jv, abuilder, fTarget);
95     }
96 
97 private:
parseKFValue(const AnimationBuilder & abuilder,const skjson::ObjectValue &,const skjson::Value & jv,Keyframe::Value * v)98     bool parseKFValue(const AnimationBuilder& abuilder,
99                         const skjson::ObjectValue&,
100                         const skjson::Value& jv,
101                         Keyframe::Value* v) override {
102         TextValue val;
103         if (!Parse(jv, abuilder, &val)) {
104             return false;
105         }
106 
107         // TODO: full deduping?
108         if (fValues.empty() || val != fValues.back()) {
109             fValues.push_back(std::move(val));
110         }
111 
112         v->idx = SkToU32(fValues.size() - 1);
113 
114         return true;
115     }
116 
117     std::vector<TextValue> fValues;
118     TextValue*             fTarget;
119 
120     using INHERITED = AnimatorBuilder;
121 };
122 
123 } // namespace
124 
125 template <>
bind(const AnimationBuilder & abuilder,const skjson::ObjectValue * jprop,TextValue * v)126 bool AnimatablePropertyContainer::bind<TextValue>(const AnimationBuilder& abuilder,
127                                                   const skjson::ObjectValue* jprop,
128                                                   TextValue* v) {
129     TextAnimatorBuilder builder(v);
130     return this->bindImpl(abuilder, jprop, builder);
131 }
132 
133 } // namespace skottie::internal
134