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 | |
17 | class TextKeyframeAnimator final : public KeyframeAnimator { |
18 | public: |
19 | class Builder final : public KeyframeAnimatorBuilder { |
20 | public: |
21 | explicit Builder(TextValue* target) : fTarget(target) {} |
22 | |
23 | sk_sp<KeyframeAnimator> make(const AnimationBuilder& abuilder, |
24 | const skjson::ArrayValue& jkfs) override { |
25 | SkASSERT(jkfs.size() > 0); |
26 | |
27 | fValues.reserve(jkfs.size()); |
28 | if (!this->parseKeyframes(abuilder, jkfs)) { |
29 | return nullptr; |
30 | } |
31 | fValues.shrink_to_fit(); |
32 | |
33 | return sk_sp<TextKeyframeAnimator>( |
34 | new TextKeyframeAnimator(std::move(fKFs), |
35 | std::move(fCMs), |
36 | std::move(fValues), |
37 | fTarget)); |
38 | } |
39 | |
40 | bool parseValue(const AnimationBuilder& abuilder, const skjson::Value& jv) const override { |
41 | return Parse(jv, abuilder, fTarget); |
42 | } |
43 | |
44 | private: |
45 | bool parseKFValue(const AnimationBuilder& abuilder, |
46 | const skjson::ObjectValue&, |
47 | const skjson::Value& jv, |
48 | Keyframe::Value* v) override { |
49 | TextValue val; |
50 | if (!Parse(jv, abuilder, &val)) { |
51 | return false; |
52 | } |
53 | |
54 | // TODO: full deduping? |
55 | if (fValues.empty() || val != fValues.back()) { |
56 | fValues.push_back(std::move(val)); |
57 | } |
58 | |
59 | v->idx = SkToU32(fValues.size() - 1); |
60 | |
61 | return true; |
62 | } |
63 | |
64 | std::vector<TextValue> fValues; |
65 | TextValue* fTarget; |
66 | }; |
67 | |
68 | private: |
69 | TextKeyframeAnimator(std::vector<Keyframe> kfs, std::vector<SkCubicMap> cms, |
70 | std::vector<TextValue> vs, TextValue* target_value) |
71 | : INHERITED(std::move(kfs), std::move(cms)) |
72 | , fValues(std::move(vs)) |
73 | , fTarget(target_value) {} |
74 | |
75 | StateChanged onSeek(float t) override { |
76 | const auto& lerp_info = this->getLERPInfo(t); |
77 | |
78 | // Text value keyframes are treated as selectors, not as interpolated values. |
79 | if (*fTarget != fValues[SkToSizeT(lerp_info.vrec0.idx)]) { |
80 | *fTarget = fValues[SkToSizeT(lerp_info.vrec0.idx)]; |
81 | return true; |
82 | } |
83 | |
84 | return false; |
85 | } |
86 | |
87 | const std::vector<TextValue> fValues; |
88 | TextValue* fTarget; |
89 | |
90 | using INHERITED = KeyframeAnimator; |
91 | }; |
92 | |
93 | } // namespace |
94 | |
95 | template <> |
96 | bool AnimatablePropertyContainer::bind<TextValue>(const AnimationBuilder& abuilder, |
97 | const skjson::ObjectValue* jprop, |
98 | TextValue* v) { |
99 | TextKeyframeAnimator::Builder builder(v); |
100 | return this->bindImpl(abuilder, jprop, builder); |
101 | } |
102 | |
103 | } // namespace skottie::internal |
104 | |