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 | sk_sp<KeyframeAnimator> make(const AnimationBuilder& abuilder, |
22 | const skjson::ArrayValue& jkfs, |
23 | void* target_value) override { |
24 | SkASSERT(jkfs.size() > 0); |
25 | |
26 | fValues.reserve(jkfs.size()); |
27 | if (!this->parseKeyframes(abuilder, jkfs)) { |
28 | return nullptr; |
29 | } |
30 | fValues.shrink_to_fit(); |
31 | |
32 | return sk_sp<TextKeyframeAnimator>( |
33 | new TextKeyframeAnimator(std::move(fKFs), |
34 | std::move(fCMs), |
35 | std::move(fValues), |
36 | static_cast<TextValue*>(target_value))); |
37 | } |
38 | |
39 | bool parseValue(const AnimationBuilder& abuilder, |
40 | const skjson::Value& jv, void* v) const override { |
41 | return Parse(jv, abuilder, static_cast<TextValue*>(v)); |
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 | }; |
66 | |
67 | private: |
68 | TextKeyframeAnimator(std::vector<Keyframe> kfs, std::vector<SkCubicMap> cms, |
69 | std::vector<TextValue> vs, TextValue* target_value) |
70 | : INHERITED(std::move(kfs), std::move(cms)) |
71 | , fValues(std::move(vs)) |
72 | , fTarget(target_value) {} |
73 | |
74 | StateChanged onSeek(float t) override { |
75 | const auto& lerp_info = this->getLERPInfo(t); |
76 | |
77 | // Text value keyframes are treated as selectors, not as interpolated values. |
78 | if (*fTarget != fValues[SkToSizeT(lerp_info.vrec0.idx)]) { |
79 | *fTarget = fValues[SkToSizeT(lerp_info.vrec0.idx)]; |
80 | return true; |
81 | } |
82 | |
83 | return false; |
84 | } |
85 | |
86 | const std::vector<TextValue> fValues; |
87 | TextValue* fTarget; |
88 | |
89 | using INHERITED = KeyframeAnimator; |
90 | }; |
91 | |
92 | } // namespace |
93 | |
94 | template <> |
95 | bool AnimatablePropertyContainer::bind<TextValue>(const AnimationBuilder& abuilder, |
96 | const skjson::ObjectValue* jprop, |
97 | TextValue* v) { |
98 | TextKeyframeAnimator::Builder builder; |
99 | return this->bindImpl(abuilder, jprop, builder, v); |
100 | } |
101 | |
102 | } // namespace skottie::internal |
103 | |