• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2018 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 "SkMatrix.h"
9 #include "Skottie.h"
10 #include "SkottieProperty.h"
11 #include "SkStream.h"
12 
13 #include "Test.h"
14 
15 #include <tuple>
16 #include <vector>
17 
18 using namespace skottie;
19 
DEF_TEST(Skottie_OssFuzz8956,reporter)20 DEF_TEST(Skottie_OssFuzz8956, reporter) {
21     static constexpr char json[] =
22         "{\"v\":\" \",\"fr\":3,\"w\":4,\"h\":3,\"layers\":[{\"ty\": 1, \"sw\": 10, \"sh\": 10,"
23             " \"sc\":\"#ffffff\", \"ks\":{\"o\":{\"a\": true, \"k\":"
24             " [{\"t\": 0, \"s\": 0, \"e\": 1, \"i\": {\"x\":[]}}]}}}]}";
25 
26     SkMemoryStream stream(json, strlen(json));
27 
28     // Passes if parsing doesn't crash.
29     auto animation = Animation::Make(&stream);
30 }
31 
DEF_TEST(Skottie_Properties,reporter)32 DEF_TEST(Skottie_Properties, reporter) {
33     static constexpr char json[] = R"({
34                                      "v": "5.2.1",
35                                      "w": 100,
36                                      "h": 100,
37                                      "fr": 1,
38                                      "ip": 0,
39                                      "op": 1,
40                                      "layers": [
41                                        {
42                                          "ty": 4,
43                                          "nm": "layer_0",
44                                          "ind": 0,
45                                          "ip": 0,
46                                          "op": 1,
47                                          "ks": {
48                                            "o": { "a": 0, "k": 50 }
49                                          },
50                                          "shapes": [
51                                            {
52                                              "ty": "el",
53                                              "nm": "geometry_0",
54                                              "p": { "a": 0, "k": [ 50, 50 ] },
55                                              "s": { "a": 0, "k": [ 50, 50 ] }
56                                            },
57                                            {
58                                              "ty": "fl",
59                                              "nm": "fill_0",
60                                              "c": { "a": 0, "k": [ 1, 0, 0] }
61                                            },
62                                            {
63                                              "ty": "tr",
64                                              "nm": "shape_transform_0",
65                                              "o": { "a": 0, "k": 100 },
66                                              "s": { "a": 0, "k": [ 50, 50 ] }
67                                            }
68                                          ]
69                                        }
70                                      ]
71                                    })";
72 
73     class TestPropertyObserver final : public PropertyObserver {
74     public:
75         struct ColorInfo {
76             SkString node_name;
77             SkColor  color;
78         };
79 
80         struct OpacityInfo {
81             SkString node_name;
82             float    opacity;
83         };
84 
85         struct TransformInfo {
86             SkString                        node_name;
87             skottie::TransformPropertyValue transform;
88         };
89 
90         void onColorProperty(const char node_name[],
91                 const PropertyObserver::LazyHandle<ColorPropertyHandle>& lh) override {
92             fColors.push_back({SkString(node_name), lh()->get()});
93         }
94 
95         void onOpacityProperty(const char node_name[],
96                 const PropertyObserver::LazyHandle<OpacityPropertyHandle>& lh) override {
97             fOpacities.push_back({SkString(node_name), lh()->get()});
98         }
99 
100         void onTransformProperty(const char node_name[],
101                 const PropertyObserver::LazyHandle<TransformPropertyHandle>& lh) override {
102             fTransforms.push_back({SkString(node_name), lh()->get()});
103         }
104 
105         const std::vector<ColorInfo>& colors() const { return fColors; }
106         const std::vector<OpacityInfo>& opacities() const { return fOpacities; }
107         const std::vector<TransformInfo>& transforms() const { return fTransforms; }
108 
109     private:
110         std::vector<ColorInfo>     fColors;
111         std::vector<OpacityInfo>   fOpacities;
112         std::vector<TransformInfo> fTransforms;
113     };
114 
115     SkMemoryStream stream(json, strlen(json));
116     auto observer = sk_make_sp<TestPropertyObserver>();
117 
118     auto animation = skottie::Animation::Builder()
119             .setPropertyObserver(observer)
120             .make(&stream);
121 
122     REPORTER_ASSERT(reporter, animation);
123 
124     const auto& colors = observer->colors();
125     REPORTER_ASSERT(reporter, colors.size() == 1);
126     REPORTER_ASSERT(reporter, colors[0].node_name.equals("fill_0"));
127     REPORTER_ASSERT(reporter, colors[0].color == 0xffff0000);
128 
129     const auto& opacities = observer->opacities();
130     REPORTER_ASSERT(reporter, opacities.size() == 2);
131     REPORTER_ASSERT(reporter, opacities[0].node_name.equals("shape_transform_0"));
132     REPORTER_ASSERT(reporter, SkScalarNearlyEqual(opacities[0].opacity, 100));
133     REPORTER_ASSERT(reporter, opacities[1].node_name.equals("layer_0"));
134     REPORTER_ASSERT(reporter, SkScalarNearlyEqual(opacities[1].opacity, 50));
135 
136     const auto& transforms = observer->transforms();
137     REPORTER_ASSERT(reporter, transforms.size() == 2);
138     REPORTER_ASSERT(reporter, transforms[0].node_name.equals("shape_transform_0"));
139     REPORTER_ASSERT(reporter, transforms[0].transform == skottie::TransformPropertyValue({
140         SkPoint::Make(0, 0),
141         SkPoint::Make(0, 0),
142         SkVector::Make(50, 50),
143         0,
144         0,
145         0
146     }));
147     REPORTER_ASSERT(reporter, transforms[1].node_name.equals("layer_0"));
148     REPORTER_ASSERT(reporter, transforms[1].transform == skottie::TransformPropertyValue({
149         SkPoint::Make(0, 0),
150         SkPoint::Make(0, 0),
151         SkVector::Make(100, 100),
152         0,
153         0,
154         0
155     }));
156 }
157 
DEF_TEST(Skottie_Annotations,reporter)158 DEF_TEST(Skottie_Annotations, reporter) {
159     static constexpr char json[] = R"({
160                                      "v": "5.2.1",
161                                      "w": 100,
162                                      "h": 100,
163                                      "fr": 10,
164                                      "ip": 0,
165                                      "op": 100,
166                                      "layers": [
167                                        {
168                                          "ty": 1,
169                                          "ind": 0,
170                                          "ip": 0,
171                                          "op": 1,
172                                          "ks": {
173                                            "o": { "a": 0, "k": 50 }
174                                          },
175                                          "sw": 100,
176                                          "sh": 100,
177                                          "sc": "#ffffff"
178                                        }
179                                      ],
180                                      "markers": [
181                                        {
182                                            "cm": "marker_1",
183                                            "dr": 25,
184                                            "tm": 25
185                                        },
186                                        {
187                                            "cm": "marker_2",
188                                            "dr": 0,
189                                            "tm": 75
190                                        }
191                                      ]
192                                    })";
193 
194     class TestMarkerObserver final : public MarkerObserver {
195     public:
196         void onMarker(const char name[], float t0, float t1) override {
197             fMarkers.push_back(std::make_tuple(name, t0, t1));
198         }
199 
200         std::vector<std::tuple<std::string, float, float>> fMarkers;
201     };
202 
203     SkMemoryStream stream(json, strlen(json));
204     auto observer = sk_make_sp<TestMarkerObserver>();
205 
206     auto animation = skottie::Animation::Builder()
207             .setMarkerObserver(observer)
208             .make(&stream);
209 
210     REPORTER_ASSERT(reporter, animation);
211 
212     REPORTER_ASSERT(reporter, observer->fMarkers.size() == 2ul);
213     REPORTER_ASSERT(reporter, std::get<0>(observer->fMarkers[0]) == "marker_1");
214     REPORTER_ASSERT(reporter, std::get<1>(observer->fMarkers[0]) == 0.25f);
215     REPORTER_ASSERT(reporter, std::get<2>(observer->fMarkers[0]) == 0.50f);
216     REPORTER_ASSERT(reporter, std::get<0>(observer->fMarkers[1]) == "marker_2");
217     REPORTER_ASSERT(reporter, std::get<1>(observer->fMarkers[1]) == 0.75f);
218     REPORTER_ASSERT(reporter, std::get<2>(observer->fMarkers[1]) == 0.75f);
219 }
220