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