1 /*
2 * Copyright 2021 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 <iostream>
9 #include "modules/skottie/include/Skottie.h"
10 #include "modules/skottie/include/SkottieProperty.h"
11 #include "tests/Test.h"
12
13 using namespace skottie;
14
15 namespace {
16
17 class FakeScalarExpressionEvaluator : public ExpressionEvaluator<float> {
18 public:
evaluate(float t)19 float evaluate(float t) override { return 7.0f; }
20 };
21
22 class FakeVectorExpressionEvaluator : public ExpressionEvaluator<std::vector<float>> {
23 public:
evaluate(float t)24 std::vector<float> evaluate(float t) override { return {0.1f, 0.2f, 0.3f, 1.0f}; }
25 };
26
27 class FakeStringExpressionEvaluator : public ExpressionEvaluator<SkString> {
28 public:
evaluate(float t)29 SkString evaluate(float t) override { return SkString("Hello, world!"); }
30 };
31
32 class FakeExpressionManager : public ExpressionManager {
33 public:
createNumberExpressionEvaluator(const char expression[])34 sk_sp<ExpressionEvaluator<float>> createNumberExpressionEvaluator(
35 const char expression[]) override {
36 return sk_make_sp<FakeScalarExpressionEvaluator>();
37 }
38
createStringExpressionEvaluator(const char expression[])39 sk_sp<ExpressionEvaluator<SkString>> createStringExpressionEvaluator(
40 const char expression[]) override {
41 return sk_make_sp<FakeStringExpressionEvaluator>();
42 }
43
createArrayExpressionEvaluator(const char expression[])44 sk_sp<ExpressionEvaluator<std::vector<float>>> createArrayExpressionEvaluator(
45 const char expression[]) override {
46 return sk_make_sp<FakeVectorExpressionEvaluator>();
47 }
48 };
49
50 class FakePropertyObserver : public PropertyObserver {
51 public:
onOpacityProperty(const char node_name[],const LazyHandle<OpacityPropertyHandle> & opacity_handle)52 void onOpacityProperty(const char node_name[],
53 const LazyHandle<OpacityPropertyHandle>& opacity_handle) override {
54 opacity_handle_.reset(opacity_handle().release());
55 }
56
onTransformProperty(const char node_name[],const LazyHandle<TransformPropertyHandle> & transform_handle)57 void onTransformProperty(const char node_name[],
58 const LazyHandle<TransformPropertyHandle>& transform_handle) override {
59 transform_handle_.reset(transform_handle().release());
60 }
61
onColorProperty(const char node_name[],const LazyHandle<ColorPropertyHandle> & color_handle)62 void onColorProperty(const char node_name[],
63 const LazyHandle<ColorPropertyHandle>& color_handle) override {
64 color_handle_.reset(color_handle().release());
65 }
66
onTextProperty(const char node_name[],const LazyHandle<TextPropertyHandle> & text_handle)67 void onTextProperty(const char node_name[],
68 const LazyHandle<TextPropertyHandle>& text_handle) override {
69 text_handle_.reset(text_handle().release());
70 }
71
72 std::unique_ptr<OpacityPropertyHandle> opacity_handle_;
73 std::unique_ptr<TransformPropertyHandle> transform_handle_;
74 std::unique_ptr<ColorPropertyHandle> color_handle_;
75 std::unique_ptr<TextPropertyHandle> text_handle_;
76 };
77 } // namespace
78
DEF_TEST(Skottie_Expression,r)79 DEF_TEST(Skottie_Expression, r) {
80 static constexpr char json[] =
81 R"({
82 "v": "5.2.1",
83 "w": 100,
84 "h": 100,
85 "fr": 10,
86 "ip": 0,
87 "op": 100,
88 "layers": [
89 {
90 "ip": 0,
91 "op": 100,
92 "ty": 1,
93 "nm": "My Layer",
94 "sr": 1,
95 "ks": {
96 "o": {
97 "a": 0,
98 "k": 100,
99 "ix": 11,
100 "x": "fake; return value is specified by the FakeScalarExpressionEvaluator."
101 },
102 "r": {
103 "a": 0,
104 "k": 0,
105 "ix": 10
106 },
107 "p": {
108 "a": 0,
109 "k": [
110 50,
111 50,
112 0
113 ],
114 "ix": 2,
115 "l": 2
116 },
117 "a": {
118 "a": 0,
119 "k": [
120 50,
121 50,
122 0
123 ],
124 "ix": 1,
125 "l": 2,
126 "x": "fake; return value is specified by the FakeArrayExpressionEvaluator."
127 },
128 "s": {
129 "a": 0,
130 "k": [
131 100,
132 100,
133 100
134 ],
135 "ix": 6,
136 "l": 2
137 }
138 },
139 "ef": [
140 {
141 "ty": 21,
142 "nm": "Fill",
143 "np": 9,
144 "mn": "ADBE Fill",
145 "ix": 1,
146 "en": 1,
147 "ef": [
148 {
149 "ty": 10,
150 "nm": "Fill Mask",
151 "mn": "ADBE Fill-0001",
152 "ix": 1,
153 "v": {
154 "a": 0,
155 "k": 0,
156 "ix": 1
157 }
158 },
159 {
160 "ty": 7,
161 "nm": "All Masks",
162 "mn": "ADBE Fill-0007",
163 "ix": 2,
164 "v": {
165 "a": 0,
166 "k": 0,
167 "ix": 2
168 }
169 },
170 {
171 "ty": 2,
172 "nm": "Color",
173 "mn": "ADBE Fill-0002",
174 "ix": 3,
175 "v": {
176 "a": 0,
177 "k": [
178 1,
179 0,
180 0,
181 1
182 ],
183 "ix": 3,
184 "x": "fake; return value is specified by the FakeArrayExpressionEvaluator."
185 }
186 },
187 {
188 "ty": 7,
189 "nm": "Invert",
190 "mn": "ADBE Fill-0006",
191 "ix": 4,
192 "v": {
193 "a": 0,
194 "k": 0,
195 "ix": 4
196 }
197 },
198 {
199 "ty": 0,
200 "nm": "Horizontal Feather",
201 "mn": "ADBE Fill-0003",
202 "ix": 5,
203 "v": {
204 "a": 0,
205 "k": 0,
206 "ix": 5
207 }
208 },
209 {
210 "ty": 0,
211 "nm": "Vertical Feather",
212 "mn": "ADBE Fill-0004",
213 "ix": 6,
214 "v": {
215 "a": 0,
216 "k": 0,
217 "ix": 6
218 }
219 },
220 {
221 "ty": 0,
222 "nm": "Opacity",
223 "mn": "ADBE Fill-0005",
224 "ix": 7,
225 "v": {
226 "a": 0,
227 "k": 1,
228 "ix": 7
229 }
230 }
231 ]
232 }
233 ],
234 "ao": 0,
235 "sw": 100,
236 "sh": 100,
237 "sc": "#000000",
238 "st": 0,
239 "bm": 0
240 }
241 ]
242 })";
243
244 SkMemoryStream stream(json, strlen(json));
245
246 auto em = sk_make_sp<FakeExpressionManager>();
247 auto observer = sk_make_sp<FakePropertyObserver>();
248
249 auto anim = Animation::Builder()
250 .setExpressionManager(em)
251 .setPropertyObserver(observer)
252 .make(&stream);
253
254 REPORTER_ASSERT(r, anim);
255
256 anim->seekFrameTime(0);
257
258 REPORTER_ASSERT(r, SkScalarNearlyEqual(observer->opacity_handle_->get(), 7.0f));
259 SkPoint anchor_point = observer->transform_handle_->get().fAnchorPoint;
260 REPORTER_ASSERT(r, SkScalarNearlyEqual(anchor_point.fX, 0.1f));
261 REPORTER_ASSERT(r, SkScalarNearlyEqual(anchor_point.fY, 0.2f));
262 REPORTER_ASSERT(r, (observer->color_handle_->get() == SkColor4f{0.1f, 0.2f, 0.3f, 1.0f}.toSkColor()));
263 }
264
DEF_TEST(Skottie_ExpressionText,r)265 DEF_TEST(Skottie_ExpressionText, r) {
266 static constexpr char text_json[] =
267 R"({
268 "layers":[
269 {
270 "ty":5,
271 "ks":{
272 "a":{
273 "k":[
274 0,
275 0
276 ]
277 },
278 "p":{
279 "k":[
280 128,
281 144
282 ]
283 },
284 "o":{
285 "k":100
286 }
287 },
288 "ind":0,
289 "ip":0,
290 "op":2,
291 "nm":"TextLayer_0",
292 "t":{
293 "d":{
294 "k":[
295 {
296 "t":0,
297 "s":{
298 "f": "Helvetica",
299 "s":14,
300 "t":"will be replaced.",
301 "j":0,
302 "ps":[
303 0,
304 0
305 ],
306 "sz":[
307 384,
308 360
309 ],
310 "fc":[
311 0.95686274766921997,
312 0.37254902720451355,
313 0.25490197539329529,
314 1
315 ],
316 "lh":16
317 }
318 }
319 ],
320 "x": "fake; return value is specified by the FakeStringExpressionEvaluator."
321 }
322 }
323 }
324 ],
325 "ip":0,
326 "op":2,
327 "fr":25,
328 "w":1280,
329 "h":720,
330 "ddd":false,
331 "v":"5.2.2",
332 "nm":"skottie_animation",
333 "fonts":{
334 "list":[
335 {
336 "fName": "Helvetica",
337 "fFamily":"external_font_family",
338 "fStyle":"Regular"
339 }
340 ]
341 }
342 })";
343
344 SkMemoryStream stream(text_json, strlen(text_json));
345
346 auto em = sk_make_sp<FakeExpressionManager>();
347 auto observer = sk_make_sp<FakePropertyObserver>();
348
349 auto anim = Animation::Builder()
350 .setExpressionManager(em)
351 .setPropertyObserver(observer)
352 .make(&stream);
353
354 REPORTER_ASSERT(r, anim);
355
356 anim->seekFrameTime(0);
357
358 REPORTER_ASSERT(r, observer->text_handle_->get().fText == SkString("Hello, world!"));
359 }
360