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.h"
9 #include "modules/skottie/src/SkottiePriv.h"
10 #include "modules/skottie/src/SkottieValue.h"
11 #include "src/utils/SkJSON.h"
12 #include "tests/Test.h"
13
14 #include <cmath>
15
16 using namespace skottie;
17 using namespace skottie::internal;
18
19 namespace {
20
21 template <typename T>
22 class MockProperty final : public AnimatablePropertyContainer {
23 public:
MockProperty(const char * jprop)24 explicit MockProperty(const char* jprop) {
25 AnimationBuilder abuilder(nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
26 {100, 100}, 10, 1, 0);
27 skjson::DOM json_dom(jprop, strlen(jprop));
28
29 fDidBind = this->bind(abuilder, json_dom.root(), &fValue);
30 }
31
operator bool() const32 operator bool() const { return fDidBind; }
33
operator ()(float t)34 const T& operator()(float t) { this->tick(t); return fValue; }
35
36 private:
onSync()37 void onSync() override {}
38
39 T fValue = T();
40 bool fDidBind;
41 };
42
43 }
44
DEF_TEST(Skottie_Keyframe,reporter)45 DEF_TEST(Skottie_Keyframe, reporter) {
46 {
47 MockProperty<ScalarValue> prop(R"({})");
48 REPORTER_ASSERT(reporter, !prop);
49 }
50 {
51 MockProperty<ScalarValue> prop(R"({ "a": 1, "k": [] })");
52 REPORTER_ASSERT(reporter, !prop);
53 }
54 {
55 // New style
56 MockProperty<ScalarValue> prop(R"({
57 "a": 1,
58 "k": [
59 { "t": 1, "s": 1 },
60 { "t": 2, "s": 2 },
61 { "t": 3, "s": 4 }
62 ]
63 })");
64 REPORTER_ASSERT(reporter, prop);
65 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(prop( -1), 1));
66 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(prop( 0), 1));
67 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(prop( 1), 1));
68 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(prop(1.5), 1.5f));
69 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(prop( 2), 2));
70 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(prop(2.5), 3));
71 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(prop( 3), 4));
72 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(prop( 4), 4));
73 }
74 {
75 // New style hold (hard stops)
76 MockProperty<ScalarValue> prop(R"({
77 "a": 1,
78 "k": [
79 { "t": 1, "s": 1, "h": true },
80 { "t": 2, "s": 2, "h": true },
81 { "t": 3, "s": 4, "h": true }
82 ]
83 })");
84 REPORTER_ASSERT(reporter, prop);
85 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(prop(0 ), 1));
86 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(prop(1 ), 1));
87 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(prop(1.5), 1));
88 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(prop(std::nextafter(2.f, 0.f)), 1));
89 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(prop(2 ), 2));
90 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(prop(2.5), 2));
91 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(prop(std::nextafter(3.f, 0.f)), 2));
92 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(prop(3 ), 4));
93 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(prop(4 ), 4));
94 }
95 {
96 // Legacy style
97 MockProperty<ScalarValue> prop(R"({
98 "a": 1,
99 "k": [
100 { "t": 1, "s": 1, "e": 2 },
101 { "t": 2, "s": 2, "e": 4 },
102 { "t": 3 }
103 ]
104 })");
105 REPORTER_ASSERT(reporter, prop);
106 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(prop(-1), 1));
107 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(prop( 0), 1));
108 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(prop( 1 ), 1));
109 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(prop( 1.5), 1.5f));
110 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(prop( 2 ), 2));
111 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(prop( 2.5), 3));
112 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(prop( 3 ), 4));
113 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(prop( 4 ), 4));
114 }
115 {
116 // Legacy style hold (hard stops)
117 MockProperty<ScalarValue> prop(R"({
118 "a": 1,
119 "k": [
120 { "t": 1, "s": 1, "e": 2, "h": true },
121 { "t": 2, "s": 2, "e": 4, "h": true },
122 { "t": 3 }
123 ]
124 })");
125 REPORTER_ASSERT(reporter, prop);
126 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(prop(0 ), 1));
127 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(prop(1 ), 1));
128 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(prop(1.5), 1));
129 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(prop(std::nextafter(2.f, 0.f)), 1));
130 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(prop(2 ), 2));
131 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(prop(2.5), 2));
132 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(prop(std::nextafter(3.f, 0.f)), 2));
133 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(prop(3 ), 4));
134 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(prop(4 ), 4));
135 }
136 }
137