• 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/animator/Animator.h"
9 
10 #include "modules/skottie/src/SkottieJson.h"
11 #include "modules/skottie/src/SkottiePriv.h"
12 #include "modules/skottie/src/animator/KeyframeAnimator.h"
13 
14 namespace skottie::internal {
15 
onSeek(float t)16 Animator::StateChanged AnimatablePropertyContainer::onSeek(float t) {
17     // The very first seek must trigger a sync, to ensure proper SG setup.
18     bool changed = !fHasSynced;
19 
20     for (const auto& animator : fAnimators) {
21         changed |= animator->seek(t);
22     }
23 
24     if (changed) {
25         this->onSync();
26         fHasSynced = true;
27     }
28 
29     return changed;
30 }
31 
attachDiscardableAdapter(sk_sp<AnimatablePropertyContainer> child)32 void AnimatablePropertyContainer::attachDiscardableAdapter(
33         sk_sp<AnimatablePropertyContainer> child) {
34     if (!child) {
35         return;
36     }
37 
38     if (child->isStatic()) {
39         child->seek(0);
40         return;
41     }
42 
43     fAnimators.push_back(child);
44 }
45 
shrink_to_fit()46 void AnimatablePropertyContainer::shrink_to_fit() {
47     fAnimators.shrink_to_fit();
48 }
49 
bindImpl(const AnimationBuilder & abuilder,const skjson::ObjectValue * jprop,KeyframeAnimatorBuilder & builder)50 bool AnimatablePropertyContainer::bindImpl(const AnimationBuilder& abuilder,
51                                            const skjson::ObjectValue* jprop,
52                                            KeyframeAnimatorBuilder& builder) {
53     if (!jprop) {
54         return false;
55     }
56 
57     const auto& jpropA = (*jprop)["a"];
58     const auto& jpropK = (*jprop)["k"];
59 
60     if (!(*jprop)["x"].is<skjson::NullValue>()) {
61         abuilder.log(Logger::Level::kWarning, nullptr, "Unsupported expression.");
62     }
63 
64     // Older Json versions don't have an "a" animation marker.
65     // For those, we attempt to parse both ways.
66     if (!ParseDefault<bool>(jpropA, false)) {
67         if (builder.parseValue(abuilder, jpropK)) {
68             // Static property.
69             return true;
70         }
71 
72         if (!jpropA.is<skjson::NullValue>()) {
73             abuilder.log(Logger::Level::kError, jprop,
74                          "Could not parse (explicit) static property.");
75             return false;
76         }
77     }
78 
79     // Keyframed property.
80     sk_sp<KeyframeAnimator> animator;
81     const skjson::ArrayValue* jkfs = jpropK;
82     if (jkfs && jkfs->size() > 0) {
83         animator = builder.make(abuilder, *jkfs);
84     }
85 
86     if (!animator) {
87         abuilder.log(Logger::Level::kError, jprop, "Could not parse keyframed property.");
88         return false;
89     }
90 
91     if (animator->isConstant()) {
92         // If all keyframes are constant, there is no reason to treat this
93         // as an animated property - apply immediately and discard the animator.
94         animator->seek(0);
95     } else {
96         fAnimators.push_back(std::move(animator));
97     }
98 
99     return true;
100 }
101 
102 } // namespace skottie::internal
103