98 {
110
111 static const struct {
113 int fFrameCount;
114
115
116 std::vector<int> fRequiredFrames;
117
118 std::vector<SkAlphaType> fAlphas;
119
120
121 std::vector<int> fDurations;
122 int fRepetitionCount;
123 std::vector<SkCodecAnimation::DisposalMethod> fDisposalMethods;
124 std::vector<bool> fAlphaWithinBounds;
125 std::vector<SkCodecAnimation::Blend> fBlends;
126 std::vector<SkIRect> fFrameRects;
127 } gRecs[] = {
128 { "images/required.gif", 7,
129 { 0, 1, 2, 3, 4, 5 },
131 { 100, 100, 100, 100, 100, 100, 100 },
132 0,
134 { false, true, true, true, true, true, true },
137 { {0, 0, 100, 100}, {0, 0, 75, 75}, {0, 0, 50, 50}, {0, 0, 60, 60},
138 {0, 0, 100, 100}, {0, 0, 50, 50}, {0, 0, 75, 75}},
139 },
140 { "images/alphabetAnim.gif", 13,
141 { kNoFrame, 0, 0, 0, 0, 5, 6, kNoFrame, kNoFrame, 9, 10, 11 },
144 { 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100 },
145 0,
146 {
kKeep, kRestorePrev, kRestorePrev, kRestorePrev, kRestorePrev,
149 { true, false, true, false, true, true, true, true, true, true, true, true, true },
153 { {25, 25, 75, 75}, {25, 25, 75, 75}, {25, 25, 75, 75}, {37, 37, 62, 62},
154 {37, 37, 62, 62}, {25, 25, 75, 75}, {0, 0, 50, 50}, {0, 0, 100, 100},
155 {25, 25, 75, 75}, {25, 25, 75, 75}, {0, 0, 100, 100}, {25, 25, 75, 75},
156 {37, 37, 62, 62}},
157 },
158 { "images/randPixelsAnim2.gif", 4,
159
160 { 0, 0, 1 },
161
163
164 { 0, 1000, 170, 40 },
165
166 0,
168 { false, true, false, false },
170 { {0, 0, 8, 8}, {6, 6, 8, 8}, {4, 4, 8, 8}, {7, 0, 8, 8} },
171 },
172 { "images/randPixelsAnim.gif", 13,
173
174 { 0, 1, 2, 3, 4, 3, 6, 7, 7, 7, 9, 9 },
177
178 { 0, 1000, 170, 40, 220, 7770, 90, 90, 90, 90, 90, 90, 90 },
179
180 0,
182 kRestoreBG, kRestorePrev, kRestoreBG, kRestorePrev, kRestorePrev,
183 kRestorePrev, },
184 { false, true, true, false, true, true, false, false, true, true, false, false,
185 true },
189 { {4, 4, 12, 12}, {4, 4, 12, 12}, {4, 4, 12, 12}, {0, 0, 8, 8}, {8, 8, 16, 16},
190 {8, 8, 16, 16}, {8, 8, 16, 16}, {2, 2, 10, 10}, {7, 7, 15, 15}, {7, 7, 15, 15},
191 {7, 7, 15, 15}, {0, 0, 8, 8}, {14, 14, 16, 16} },
192 },
193 {
"images/box.gif", 1, {}, {}, {},
SkCodec::kRepetitionCountInfinite, {
kKeep }, {}, {}, {} },
194 {
"images/color_wheel.gif", 1, {}, {}, {},
SkCodec::kRepetitionCountInfinite, {
kKeep }, {}, {}, {} },
195 { "images/test640x479.gif", 4, { 0, 1, 2 },
197 { 200, 200, 200, 200 },
200 { false, true, true, true },
202 { {0, 0, 640, 479}, {0, 0, 640, 479}, {0, 0, 640, 479}, {0, 0, 640, 479} },
203 },
204 {
"images/colorTables.gif", 2, { 0 }, {
kOpaque }, { 1000, 1000 }, 5,
206 { {0, 0, 640, 400}, {0, 0, 640, 200}},
207 },
208
209 { "images/arrow.png", 1, {}, {}, {}, 0, {}, {}, {}, {} },
210 { "images/google_chrome.ico", 1, {}, {}, {}, 0, {}, {}, {}, {} },
211 { "images/brickwork-texture.jpg", 1, {}, {}, {}, 0, {}, {}, {}, {} },
212#if defined(SK_CODEC_DECODES_RAW) && (!defined(_WIN32))
213 { "images/dng_with_preview.dng", 1, {}, {}, {}, 0, {}, {}, {}, {} },
214#endif
215 { "images/mandrill.wbmp", 1, {}, {}, {}, 0, {}, {}, {}, {} },
216 { "images/randPixels.bmp", 1, {}, {}, {}, 0, {}, {}, {}, {} },
217 { "images/yellow_rose.webp", 1, {}, {}, {}, 0, {}, {}, {}, {} },
222 { {0, 0, 11, 29}, {2, 10, 9, 27}, {2, 2, 9, 18}},
223 },
224 { "images/blendBG.webp", 7,
225 { 0, kNoFrame, kNoFrame, kNoFrame, 4, 4 },
227 { 525, 500, 525, 437, 609, 729, 444 },
228 6,
230 { false, true, false, true, false, true, true },
232 { {0, 0, 200, 200}, {0, 0, 200, 200}, {0, 0, 200, 200}, {0, 0, 200, 200},
233 {0, 0, 200, 200}, {100, 100, 200, 200}, {100, 100, 200, 200} },
234 },
235 { "images/required.webp", 7,
236 { 0, 1, 1, kNoFrame, 4, 4 },
238 { 100, 100, 100, 100, 100, 100, 100 },
239 0,
241 { false, false, false, false, false, false, false },
244 { {0, 0, 100, 100}, {0, 0, 75, 75}, {0, 0, 50, 50}, {0, 0, 60, 60},
245 {0, 0, 100, 100}, {0, 0, 50, 50}, {0, 0, 75, 75}},
246 },
247 };
248
249 for (const auto& rec : gRecs) {
252
253
254
255 continue;
256 }
257
259 if (!codec) {
260 ERRORF(r,
"Failed to create an SkCodec from '%s'", rec.fName);
261 continue;
262 }
263
264 {
267 }
268
269 const int expected = rec.fFrameCount;
270 if (rec.fRequiredFrames.size() + 1 != static_cast<size_t>(expected)) {
271 ERRORF(r,
"'%s' has wrong number entries in fRequiredFrames; expected: %i\tactual: %zu",
272 rec.fName, expected - 1, rec.fRequiredFrames.size());
273 continue;
274 }
275
276 if (expected > 1) {
277 if (rec.fDurations.size() != static_cast<size_t>(expected)) {
278 ERRORF(r,
"'%s' has wrong number entries in fDurations; expected: %i\tactual: %zu",
279 rec.fName, expected, rec.fDurations.size());
280 continue;
281 }
282
283 if (rec.fAlphas.size() + 1 != static_cast<size_t>(expected)) {
284 ERRORF(r,
"'%s' has wrong number entries in fAlphas; expected: %i\tactual: %zu",
285 rec.fName, expected - 1, rec.fAlphas.size());
286 continue;
287 }
288
289 if (rec.fDisposalMethods.size() != static_cast<size_t>(expected)) {
290 ERRORF(r,
"'%s' has wrong number entries in fDisposalMethods; "
291 "expected %i\tactual: %zu",
292 rec.fName, expected, rec.fDisposalMethods.size());
293 continue;
294 }
295 }
296
297 enum class TestMode {
298 kVector,
299 kIndividual,
300 };
301
302 for (
auto mode : { TestMode::kVector, TestMode::kIndividual }) {
303
305
306 int frameCount;
307 std::vector<SkCodec::FrameInfo> frameInfos;
309 case TestMode::kVector:
310 frameInfos = codec->getFrameInfo();
311
312 frameCount = frameInfos.empty() ? 1 : frameInfos.size();
313 break;
314 case TestMode::kIndividual:
315 frameCount = codec->getFrameCount();
316 break;
317 }
318
319 if (frameCount != expected) {
320 ERRORF(r,
"'%s' expected frame count: %i\tactual: %i",
321 rec.fName, expected, frameCount);
322 continue;
323 }
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338 const int repetitionCount = codec->getRepetitionCount();
339 if (repetitionCount != rec.fRepetitionCount) {
340 ERRORF(r,
"%s repetition count does not match! expected: %i\tactual: %i",
341 rec.fName, rec.fRepetitionCount, repetitionCount);
342 }
343
344
345 if (1 == frameCount) {
346 continue;
347 }
348
349 for (
int i = 0;
i < frameCount;
i++) {
352 case TestMode::kVector:
353 frameInfo = frameInfos[
i];
354 break;
355 case TestMode::kIndividual:
358 break;
359 }
360
361 if (rec.fDurations[
i] != frameInfo.
fDuration) {
362 ERRORF(r,
"%s frame %i's durations do not match! expected: %i\tactual: %i",
363 rec.fName,
i, rec.fDurations[
i], frameInfo.
fDuration);
364 }
365
367 switch (alpha) {
369 return "unpremul";
371 return "opaque";
372 default:
374 return "unknown";
375 }
376 };
377
378 auto expectedAlpha = 0 ==
i ? codec->getInfo().alphaType() : rec.fAlphas[
i-1];
380 if (expectedAlpha != alpha) {
381 ERRORF(r,
"%s's frame %i has wrong alpha type! expected: %s\tactual: %s",
383 }
384
388 ERRORF(r,
"%s's frame %i has wrong dependency! expected: %i\tactual: %i",
390 }
391
393
394 reporter_assert_equals<bool>(r, rec.fName,
i,
"alpha within bounds",
395 rec.fAlphaWithinBounds[
i],
397
398 reporter_assert_equals(r, rec.fName,
i,
"blend mode", rec.fBlends[
i],
400
401 reporter_assert_equals(r, rec.fName,
i,
"frame rect", rec.fFrameRects[
i],
403 }
404
405 if (TestMode::kIndividual ==
mode) {
406
407 continue;
408 }
409
410
411
412
413
414
415
416
417 std::vector<SkBitmap> cachedFrames(frameCount);
418 const auto info = codec->getInfo().makeColorType(kN32_SkColorType);
419
421 auto decodeInfo =
info;
422 if (index > 0) {
424 }
427
428 const bool success =
431 }
436 &opts);
440 return true;
441 }
442 ERRORF(r,
"Using a kRestorePrevious frame as fPriorFrame should fail");
443 return false;
444 }
446 ERRORF(r,
"Failed to decode frame %i from %s when providing prior frame %i, "
447 "error %i", index, rec.fName, cachedIndex,
result);
448 }
450 };
451
452 for (
int i = 0;
i < frameCount;
i++) {
455 continue;
456 }
457 const auto reqFrame = frameInfos[
i].fRequiredFrame;
459
460 continue;
461 }
462 for (
int j = reqFrame; j <
i; j++) {
466 continue;
467 }
469 continue;
470 }
471
472
473 const size_t rowLen =
info.bytesPerPixel() *
info.width();
474 for (
int y = 0;
y <
info.height();
y++) {
475 const void* cachedAddr = cachedFrame.
getAddr(0,
y);
479 const bool lineMatches = memcmp(cachedAddr,
addr, rowLen) == 0;
480 if (!lineMatches) {
485 ERRORF(r,
"%s's frame %i is different (starting from line %i) when "
486 "providing prior frame %i!", rec.fName,
i,
y, j);
487 break;
488 }
489 }
490 }
491 }
492 }
493 }
494}
static bool restore_previous(const SkCodec::FrameInfo &info)
void write_bm(const char *name, const SkBitmap &bm)
@ kOpaque_SkAlphaType
pixel is opaque
SK_API SkString SkStringPrintf(const char *format,...) SK_PRINTF_LIKE(1
Creates a new string and writes into it using a printf()-style format.
void * getAddr(int x, int y) const
static constexpr int kRepetitionCountInfinite
DEF_SWITCHES_START aot vmservice shared library name
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive mode
@ kSrcOver
r = s + (1-sa)*d
@ kKeep
Don't modify the current stencil value.
static SkString to_string(int n)
static DecodeResult decode(std::string path)
SkCodecAnimation::DisposalMethod fDisposalMethod
SkCodecAnimation::Blend fBlend
bool fHasAlphaWithinBounds