Flutter Engine
The Flutter Engine
SkottieTest.cpp
Go to the documentation of this file.
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
11#include "tests/Test.h"
12
13#include <cmath>
14#include <string>
15#include <tuple>
16#include <vector>
17
18using namespace skottie;
19
20DEF_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
32DEF_TEST(Skottie_Annotations, reporter) {
33 static constexpr char json[] = R"({
34 "v": "5.2.1",
35 "w": 100,
36 "h": 100,
37 "fr": 10,
38 "ip": 0,
39 "op": 100,
40 "layers": [
41 {
42 "ty": 1,
43 "ind": 0,
44 "ip": 0,
45 "op": 1,
46 "ks": {
47 "o": { "a": 0, "k": 50 }
48 },
49 "sw": 100,
50 "sh": 100,
51 "sc": "#ffffff"
52 }
53 ],
54 "markers": [
55 {
56 "cm": "marker_1",
57 "dr": 25,
58 "tm": 25
59 },
60 {
61 "cm": "marker_2",
62 "dr": 0,
63 "tm": 75
64 }
65 ]
66 })";
67
68 class TestMarkerObserver final : public MarkerObserver {
69 public:
70 void onMarker(const char name[], float t0, float t1) override {
71 fMarkers.push_back(std::make_tuple(name, t0, t1));
72 }
73
74 std::vector<std::tuple<std::string, float, float>> fMarkers;
75 };
76
77 SkMemoryStream stream(json, strlen(json));
78 auto observer = sk_make_sp<TestMarkerObserver>();
79
80 auto animation = skottie::Animation::Builder()
81 .setMarkerObserver(observer)
82 .make(&stream);
83
84 REPORTER_ASSERT(reporter, animation);
85 REPORTER_ASSERT(reporter, animation->duration() == 10);
86 REPORTER_ASSERT(reporter, animation->inPoint() == 0.0);
87 REPORTER_ASSERT(reporter, animation->outPoint() == 100.0);
88
89 REPORTER_ASSERT(reporter, observer->fMarkers.size() == 2ul);
90 REPORTER_ASSERT(reporter, std::get<0>(observer->fMarkers[0]) == "marker_1");
91 REPORTER_ASSERT(reporter, std::get<1>(observer->fMarkers[0]) == 0.25f);
92 REPORTER_ASSERT(reporter, std::get<2>(observer->fMarkers[0]) == 0.50f);
93 REPORTER_ASSERT(reporter, std::get<0>(observer->fMarkers[1]) == "marker_2");
94 REPORTER_ASSERT(reporter, std::get<1>(observer->fMarkers[1]) == 0.75f);
95 REPORTER_ASSERT(reporter, std::get<2>(observer->fMarkers[1]) == 0.75f);
96}
97
98DEF_TEST(Skottie_Image_Loading, reporter) {
99 class TestResourceProvider final : public skresources::ResourceProvider {
100 public:
101 TestResourceProvider(sk_sp<skresources::ImageAsset> single_asset,
103 : fSingleFrameAsset(std::move(single_asset))
104 , fMultiFrameAsset (std::move( multi_asset)) {}
105
106 private:
108 const char name[],
109 const char id[]) const override {
110 return strcmp(id, "single_frame")
111 ? fMultiFrameAsset
112 : fSingleFrameAsset;
113 }
114
115 const sk_sp<skresources::ImageAsset> fSingleFrameAsset,
116 fMultiFrameAsset;
117 };
118
119 auto make_animation = [&reporter] (sk_sp<skresources::ImageAsset> single_asset,
121 bool deferred_image_loading) {
122 static constexpr char json[] = R"({
123 "v": "5.2.1",
124 "w": 100,
125 "h": 100,
126 "fr": 10,
127 "ip": 0,
128 "op": 100,
129 "assets": [
130 {
131 "id": "single_frame",
132 "p" : "single_frame.png",
133 "u" : "images/",
134 "w" : 500,
135 "h" : 500
136 },
137 {
138 "id": "multi_frame",
139 "p" : "multi_frame.png",
140 "u" : "images/",
141 "w" : 500,
142 "h" : 500
143 }
144 ],
145 "layers": [
146 {
147 "ty": 2,
148 "refId": "single_frame",
149 "ind": 0,
150 "ip": 0,
151 "op": 100,
152 "ks": {}
153 },
154 {
155 "ty": 2,
156 "refId": "multi_frame",
157 "ind": 1,
158 "ip": 0,
159 "op": 100,
160 "ks": {}
161 }
162 ]
163 })";
164
165 SkMemoryStream stream(json, strlen(json));
166
167 const auto flags = deferred_image_loading
169 : 0;
170 auto animation =
172 .setResourceProvider(sk_make_sp<TestResourceProvider>(std::move(single_asset),
173 std::move( multi_asset)))
174 .make(&stream);
175
176 REPORTER_ASSERT(reporter, animation);
177
178 return animation;
179 };
180
181 class TestAsset final : public skresources::ImageAsset {
182 public:
183 explicit TestAsset(bool multi_frame) : fMultiFrame(multi_frame) {}
184
185 const std::vector<float>& requestedFrames() const { return fRequestedFrames; }
186
187 private:
188 bool isMultiFrame() override { return fMultiFrame; }
189
190 sk_sp<SkImage> getFrame(float t) override {
191 fRequestedFrames.push_back(t);
192
194 }
195
196 const bool fMultiFrame;
197
198 std::vector<float> fRequestedFrames;
199 };
200
201 {
202 auto single_asset = sk_make_sp<TestAsset>(false),
203 multi_asset = sk_make_sp<TestAsset>(true);
204
205 // Default image loading: single-frame images are loaded upfront, multi-frame images are
206 // loaded on-demand.
207 auto animation = make_animation(single_asset, multi_asset, false);
208
209 REPORTER_ASSERT(reporter, single_asset->requestedFrames().size() == 1);
210 REPORTER_ASSERT(reporter, multi_asset->requestedFrames().size() == 0);
211 REPORTER_ASSERT(reporter, SkScalarNearlyZero(single_asset->requestedFrames()[0]));
212
213 animation->seekFrameTime(1);
214 REPORTER_ASSERT(reporter, single_asset->requestedFrames().size() == 1);
215 REPORTER_ASSERT(reporter, multi_asset->requestedFrames().size() == 1);
216 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(multi_asset->requestedFrames()[0], 1));
217
218 animation->seekFrameTime(2);
219 REPORTER_ASSERT(reporter, single_asset->requestedFrames().size() == 1);
220 REPORTER_ASSERT(reporter, multi_asset->requestedFrames().size() == 2);
221 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(multi_asset->requestedFrames()[1], 2));
222 }
223
224 {
225 auto single_asset = sk_make_sp<TestAsset>(false),
226 multi_asset = sk_make_sp<TestAsset>(true);
227
228 // Deferred image loading: both single-frame and multi-frame images are loaded on-demand.
229 auto animation = make_animation(single_asset, multi_asset, true);
230
231 REPORTER_ASSERT(reporter, single_asset->requestedFrames().size() == 0);
232 REPORTER_ASSERT(reporter, multi_asset->requestedFrames().size() == 0);
233
234 animation->seekFrameTime(1);
235 REPORTER_ASSERT(reporter, single_asset->requestedFrames().size() == 1);
236 REPORTER_ASSERT(reporter, multi_asset->requestedFrames().size() == 1);
237 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(single_asset->requestedFrames()[0], 1));
238 REPORTER_ASSERT(reporter, SkScalarNearlyEqual (multi_asset->requestedFrames()[0], 1));
239
240 animation->seekFrameTime(2);
241 REPORTER_ASSERT(reporter, single_asset->requestedFrames().size() == 1);
242 REPORTER_ASSERT(reporter, multi_asset->requestedFrames().size() == 2);
243 REPORTER_ASSERT(reporter, SkScalarNearlyEqual(multi_asset->requestedFrames()[1], 2));
244 }
245}
246
247DEF_TEST(Skottie_Layer_NoType, r) {
248 static constexpr char json[] =
249 R"({
250 "v": "5.2.1",
251 "w": 100,
252 "h": 100,
253 "fr": 10,
254 "ip": 0,
255 "op": 100,
256 "layers": [
257 {
258 "ind": 0,
259 "ip": 0,
260 "op": 100,
261 "ks": {}
262 }
263 ]
264 })";
265
266 SkMemoryStream stream(json, strlen(json));
267 auto anim = Animation::Make(&stream);
268
269 // passes if we don't crash
270 REPORTER_ASSERT(r, anim);
271}
reporter
Definition: FontMgrTest.cpp:39
static bool SkScalarNearlyZero(SkScalar x, SkScalar tolerance=SK_ScalarNearlyZero)
Definition: SkScalar.h:101
static bool SkScalarNearlyEqual(SkScalar x, SkScalar y, SkScalar tolerance=SK_ScalarNearlyZero)
Definition: SkScalar.h:107
DEF_TEST(Skottie_OssFuzz8956, reporter)
Definition: SkottieTest.cpp:20
#define REPORTER_ASSERT(r, cond,...)
Definition: Test.h:286
sk_sp< SkImage > makeImageSnapshot()
Definition: SkSurface.cpp:90
virtual void onMarker(const char name[], float t0, float t1)=0
virtual sk_sp< SkImage > getFrame(float t)
Definition: SkResources.cpp:96
virtual bool isMultiFrame()=0
virtual sk_sp< ImageAsset > loadImageAsset(const char[], const char[], const char[]) const
Definition: SkResources.h:165
FlutterSemanticsFlag flags
SK_API sk_sp< SkDocument > Make(SkWStream *dst, const SkSerialProcs *=nullptr, std::function< void(const SkPicture *)> onEndPage=nullptr)
SK_API sk_sp< SkSurface > Raster(const SkImageInfo &imageInfo, size_t rowBytes, const SkSurfaceProps *surfaceProps)
DlVertices::Builder Builder
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
Definition: switches.h:57
DEF_SWITCHES_START aot vmservice shared library name
Definition: switches.h:32
const myers::Point & get< 1 >(const myers::Segment &s)
Definition: Myers.h:81
const myers::Point & get< 0 >(const myers::Segment &s)
Definition: Myers.h:80
static SkImageInfo MakeN32Premul(int width, int height)