1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5 #include "gtest/gtest.h"
6
7 #include "Common.h"
8 #include "AnimationSurfaceProvider.h"
9 #include "DecodePool.h"
10 #include "Decoder.h"
11 #include "DecoderFactory.h"
12 #include "decoders/nsBMPDecoder.h"
13 #include "IDecodingTask.h"
14 #include "ImageOps.h"
15 #include "imgIContainer.h"
16 #include "ImageFactory.h"
17 #include "mozilla/ScopeExit.h"
18 #include "mozilla/gfx/2D.h"
19 #include "nsComponentManagerUtils.h"
20 #include "nsCOMPtr.h"
21 #include "nsIInputStream.h"
22 #include "mozilla/RefPtr.h"
23 #include "nsStreamUtils.h"
24 #include "nsString.h"
25 #include "nsThreadUtils.h"
26 #include "ProgressTracker.h"
27 #include "SourceBuffer.h"
28
29 using namespace mozilla;
30 using namespace mozilla::gfx;
31 using namespace mozilla::image;
32
CheckDecoderState(const ImageTestCase & aTestCase,image::Decoder * aDecoder)33 static already_AddRefed<SourceSurface> CheckDecoderState(
34 const ImageTestCase& aTestCase, image::Decoder* aDecoder) {
35 // image::Decoder should match what we asked for in the MIME type.
36 EXPECT_NE(aDecoder->GetType(), DecoderType::UNKNOWN);
37 EXPECT_EQ(aDecoder->GetType(),
38 DecoderFactory::GetDecoderType(aTestCase.mMimeType));
39
40 EXPECT_TRUE(aDecoder->GetDecodeDone());
41 EXPECT_EQ(bool(aTestCase.mFlags & TEST_CASE_HAS_ERROR), aDecoder->HasError());
42
43 // Verify that the decoder made the expected progress.
44 Progress progress = aDecoder->TakeProgress();
45 EXPECT_EQ(bool(aTestCase.mFlags & TEST_CASE_HAS_ERROR),
46 bool(progress & FLAG_HAS_ERROR));
47
48 if (aTestCase.mFlags & TEST_CASE_HAS_ERROR) {
49 return nullptr; // That's all we can check for bad images.
50 }
51
52 EXPECT_TRUE(bool(progress & FLAG_SIZE_AVAILABLE));
53 EXPECT_TRUE(bool(progress & FLAG_DECODE_COMPLETE));
54 EXPECT_TRUE(bool(progress & FLAG_FRAME_COMPLETE));
55 EXPECT_EQ(bool(aTestCase.mFlags & TEST_CASE_IS_TRANSPARENT),
56 bool(progress & FLAG_HAS_TRANSPARENCY));
57 EXPECT_EQ(bool(aTestCase.mFlags & TEST_CASE_IS_ANIMATED),
58 bool(progress & FLAG_IS_ANIMATED));
59
60 // The decoder should get the correct size.
61 IntSize size = aDecoder->Size();
62 EXPECT_EQ(aTestCase.mSize.width, size.width);
63 EXPECT_EQ(aTestCase.mSize.height, size.height);
64
65 // Get the current frame, which is always the first frame of the image
66 // because CreateAnonymousDecoder() forces a first-frame-only decode.
67 RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef();
68 RefPtr<SourceSurface> surface = currentFrame->GetSourceSurface();
69
70 // Verify that the resulting surfaces matches our expectations.
71 EXPECT_TRUE(surface->IsDataSourceSurface());
72 EXPECT_TRUE(surface->GetFormat() == SurfaceFormat::OS_RGBX ||
73 surface->GetFormat() == SurfaceFormat::OS_RGBA);
74 EXPECT_EQ(aTestCase.mOutputSize, surface->GetSize());
75
76 return surface.forget();
77 }
78
CheckDecoderResults(const ImageTestCase & aTestCase,image::Decoder * aDecoder)79 static void CheckDecoderResults(const ImageTestCase& aTestCase,
80 image::Decoder* aDecoder) {
81 RefPtr<SourceSurface> surface = CheckDecoderState(aTestCase, aDecoder);
82 if (!surface) {
83 return;
84 }
85
86 if (aTestCase.mFlags & TEST_CASE_IGNORE_OUTPUT) {
87 return;
88 }
89
90 // Check the output.
91 EXPECT_TRUE(IsSolidColor(surface, aTestCase.Color(), aTestCase.Fuzz()));
92 }
93
94 template <typename Func>
WithBadBufferDecode(const ImageTestCase & aTestCase,const Maybe<IntSize> & aOutputSize,Func aResultChecker)95 void WithBadBufferDecode(const ImageTestCase& aTestCase,
96 const Maybe<IntSize>& aOutputSize,
97 Func aResultChecker) {
98 // Prepare a SourceBuffer with an error that will immediately move iterators
99 // to COMPLETE.
100 auto sourceBuffer = MakeNotNull<RefPtr<SourceBuffer>>();
101 sourceBuffer->ExpectLength(SIZE_MAX);
102
103 // Create a decoder.
104 DecoderType decoderType = DecoderFactory::GetDecoderType(aTestCase.mMimeType);
105 RefPtr<image::Decoder> decoder = DecoderFactory::CreateAnonymousDecoder(
106 decoderType, sourceBuffer, aOutputSize, DecoderFlags::FIRST_FRAME_ONLY,
107 aTestCase.mSurfaceFlags);
108 ASSERT_TRUE(decoder != nullptr);
109 RefPtr<IDecodingTask> task =
110 new AnonymousDecodingTask(WrapNotNull(decoder), /* aResumable */ false);
111
112 // Run the full decoder synchronously on the main thread.
113 task->Run();
114
115 // Call the lambda to verify the expected results.
116 aResultChecker(decoder);
117 }
118
CheckDecoderBadBuffer(const ImageTestCase & aTestCase)119 static void CheckDecoderBadBuffer(const ImageTestCase& aTestCase) {
120 WithBadBufferDecode(aTestCase, Nothing(), [&](image::Decoder* aDecoder) {
121 CheckDecoderResults(aTestCase, aDecoder);
122 });
123 }
124
125 template <typename Func>
WithSingleChunkDecode(const ImageTestCase & aTestCase,const Maybe<IntSize> & aOutputSize,bool aUseDecodePool,Func aResultChecker)126 void WithSingleChunkDecode(const ImageTestCase& aTestCase,
127 const Maybe<IntSize>& aOutputSize,
128 bool aUseDecodePool, Func aResultChecker) {
129 nsCOMPtr<nsIInputStream> inputStream = LoadFile(aTestCase.mPath);
130 ASSERT_TRUE(inputStream != nullptr);
131
132 // Figure out how much data we have.
133 uint64_t length;
134 nsresult rv = inputStream->Available(&length);
135 ASSERT_TRUE(NS_SUCCEEDED(rv));
136
137 // Write the data into a SourceBuffer.
138 auto sourceBuffer = MakeNotNull<RefPtr<SourceBuffer>>();
139 sourceBuffer->ExpectLength(length);
140 rv = sourceBuffer->AppendFromInputStream(inputStream, length);
141 ASSERT_TRUE(NS_SUCCEEDED(rv));
142 sourceBuffer->Complete(NS_OK);
143
144 // Create a decoder.
145 DecoderType decoderType = DecoderFactory::GetDecoderType(aTestCase.mMimeType);
146 RefPtr<image::Decoder> decoder = DecoderFactory::CreateAnonymousDecoder(
147 decoderType, sourceBuffer, aOutputSize, DecoderFlags::FIRST_FRAME_ONLY,
148 aTestCase.mSurfaceFlags);
149 ASSERT_TRUE(decoder != nullptr);
150 RefPtr<IDecodingTask> task =
151 new AnonymousDecodingTask(WrapNotNull(decoder), /* aResumable */ false);
152
153 if (aUseDecodePool) {
154 DecodePool::Singleton()->AsyncRun(task.get());
155
156 while (!decoder->GetDecodeDone()) {
157 task->Resume();
158 }
159 } else { // Run the full decoder synchronously on the main thread.
160 task->Run();
161 }
162
163 // Call the lambda to verify the expected results.
164 aResultChecker(decoder);
165 }
166
CheckDecoderSingleChunk(const ImageTestCase & aTestCase,bool aUseDecodePool=false)167 static void CheckDecoderSingleChunk(const ImageTestCase& aTestCase,
168 bool aUseDecodePool = false) {
169 WithSingleChunkDecode(aTestCase, Nothing(), aUseDecodePool,
170 [&](image::Decoder* aDecoder) {
171 CheckDecoderResults(aTestCase, aDecoder);
172 });
173 }
174
175 template <typename Func>
WithDelayedChunkDecode(const ImageTestCase & aTestCase,const Maybe<IntSize> & aOutputSize,Func aResultChecker)176 void WithDelayedChunkDecode(const ImageTestCase& aTestCase,
177 const Maybe<IntSize>& aOutputSize,
178 Func aResultChecker) {
179 nsCOMPtr<nsIInputStream> inputStream = LoadFile(aTestCase.mPath);
180 ASSERT_TRUE(inputStream != nullptr);
181
182 // Figure out how much data we have.
183 uint64_t length;
184 nsresult rv = inputStream->Available(&length);
185 ASSERT_TRUE(NS_SUCCEEDED(rv));
186
187 // Prepare an empty SourceBuffer.
188 auto sourceBuffer = MakeNotNull<RefPtr<SourceBuffer>>();
189
190 // Create a decoder.
191 DecoderType decoderType = DecoderFactory::GetDecoderType(aTestCase.mMimeType);
192 RefPtr<image::Decoder> decoder = DecoderFactory::CreateAnonymousDecoder(
193 decoderType, sourceBuffer, aOutputSize, DecoderFlags::FIRST_FRAME_ONLY,
194 aTestCase.mSurfaceFlags);
195 ASSERT_TRUE(decoder != nullptr);
196 RefPtr<IDecodingTask> task =
197 new AnonymousDecodingTask(WrapNotNull(decoder), /* aResumable */ true);
198
199 // Run the full decoder synchronously. It should now be waiting on
200 // the iterator to yield some data since we haven't written anything yet.
201 task->Run();
202
203 // Writing all of the data should wake up the decoder to complete.
204 sourceBuffer->ExpectLength(length);
205 rv = sourceBuffer->AppendFromInputStream(inputStream, length);
206 ASSERT_TRUE(NS_SUCCEEDED(rv));
207 sourceBuffer->Complete(NS_OK);
208
209 // It would have gotten posted to the main thread to avoid mutex contention.
210 SpinPendingEvents();
211
212 // Call the lambda to verify the expected results.
213 aResultChecker(decoder);
214 }
215
CheckDecoderDelayedChunk(const ImageTestCase & aTestCase)216 static void CheckDecoderDelayedChunk(const ImageTestCase& aTestCase) {
217 WithDelayedChunkDecode(aTestCase, Nothing(), [&](image::Decoder* aDecoder) {
218 CheckDecoderResults(aTestCase, aDecoder);
219 });
220 }
221
CheckDecoderMultiChunk(const ImageTestCase & aTestCase,uint64_t aChunkSize=1)222 static void CheckDecoderMultiChunk(const ImageTestCase& aTestCase,
223 uint64_t aChunkSize = 1) {
224 nsCOMPtr<nsIInputStream> inputStream = LoadFile(aTestCase.mPath);
225 ASSERT_TRUE(inputStream != nullptr);
226
227 // Figure out how much data we have.
228 uint64_t length;
229 nsresult rv = inputStream->Available(&length);
230 ASSERT_TRUE(NS_SUCCEEDED(rv));
231
232 // Create a SourceBuffer and a decoder.
233 auto sourceBuffer = MakeNotNull<RefPtr<SourceBuffer>>();
234 sourceBuffer->ExpectLength(length);
235 DecoderType decoderType = DecoderFactory::GetDecoderType(aTestCase.mMimeType);
236 RefPtr<image::Decoder> decoder = DecoderFactory::CreateAnonymousDecoder(
237 decoderType, sourceBuffer, Nothing(), DecoderFlags::FIRST_FRAME_ONLY,
238 aTestCase.mSurfaceFlags);
239 ASSERT_TRUE(decoder != nullptr);
240 RefPtr<IDecodingTask> task =
241 new AnonymousDecodingTask(WrapNotNull(decoder), /* aResumable */ true);
242
243 // Run the full decoder synchronously. It should now be waiting on
244 // the iterator to yield some data since we haven't written anything yet.
245 task->Run();
246
247 while (length > 0) {
248 uint64_t read = length > aChunkSize ? aChunkSize : length;
249 length -= read;
250
251 uint64_t available = 0;
252 rv = inputStream->Available(&available);
253 ASSERT_TRUE(available >= read);
254 ASSERT_TRUE(NS_SUCCEEDED(rv));
255
256 // Writing any data should wake up the decoder to complete.
257 rv = sourceBuffer->AppendFromInputStream(inputStream, read);
258 ASSERT_TRUE(NS_SUCCEEDED(rv));
259
260 // It would have gotten posted to the main thread to avoid mutex contention.
261 SpinPendingEvents();
262 }
263
264 sourceBuffer->Complete(NS_OK);
265 SpinPendingEvents();
266
267 CheckDecoderResults(aTestCase, decoder);
268 }
269
CheckDownscaleDuringDecode(const ImageTestCase & aTestCase)270 static void CheckDownscaleDuringDecode(const ImageTestCase& aTestCase) {
271 // This function expects that |aTestCase| consists of 25 lines of green,
272 // followed by 25 lines of red, followed by 25 lines of green, followed by 25
273 // more lines of red. We'll downscale it from 100x100 to 20x20.
274 IntSize outputSize(20, 20);
275
276 WithSingleChunkDecode(
277 aTestCase, Some(outputSize), /* aUseDecodePool */ false,
278 [&](image::Decoder* aDecoder) {
279 RefPtr<SourceSurface> surface = CheckDecoderState(aTestCase, aDecoder);
280
281 // There are no downscale-during-decode tests that have
282 // TEST_CASE_HAS_ERROR set, so we expect to always get a surface here.
283 EXPECT_TRUE(surface != nullptr);
284
285 if (aTestCase.mFlags & TEST_CASE_IGNORE_OUTPUT) {
286 return;
287 }
288
289 // Check that the downscaled image is correct. Note that we skip rows
290 // near the transitions between colors, since the downscaler does not
291 // produce a sharp boundary at these points. Even some of the rows we
292 // test need a small amount of fuzz; this is just the nature of Lanczos
293 // downscaling.
294 EXPECT_TRUE(RowsAreSolidColor(surface, 0, 4,
295 aTestCase.ChooseColor(BGRAColor::Green()),
296 /* aFuzz = */ 47));
297 EXPECT_TRUE(RowsAreSolidColor(surface, 6, 3,
298 aTestCase.ChooseColor(BGRAColor::Red()),
299 /* aFuzz = */ 27));
300 EXPECT_TRUE(RowsAreSolidColor(surface, 11, 3, BGRAColor::Green(),
301 /* aFuzz = */ 47));
302 EXPECT_TRUE(RowsAreSolidColor(surface, 16, 4,
303 aTestCase.ChooseColor(BGRAColor::Red()),
304 /* aFuzz = */ 27));
305 });
306 }
307
CheckAnimationDecoderResults(const ImageTestCase & aTestCase,AnimationSurfaceProvider * aProvider,image::Decoder * aDecoder)308 static void CheckAnimationDecoderResults(const ImageTestCase& aTestCase,
309 AnimationSurfaceProvider* aProvider,
310 image::Decoder* aDecoder) {
311 EXPECT_TRUE(aDecoder->GetDecodeDone());
312 EXPECT_EQ(bool(aTestCase.mFlags & TEST_CASE_HAS_ERROR), aDecoder->HasError());
313
314 if (aTestCase.mFlags & TEST_CASE_HAS_ERROR) {
315 return; // That's all we can check for bad images.
316 }
317
318 // The decoder should get the correct size.
319 IntSize size = aDecoder->Size();
320 EXPECT_EQ(aTestCase.mSize.width, size.width);
321 EXPECT_EQ(aTestCase.mSize.height, size.height);
322
323 if (aTestCase.mFlags & TEST_CASE_IGNORE_OUTPUT) {
324 return;
325 }
326
327 // Check the output.
328 AutoTArray<BGRAColor, 2> framePixels;
329 framePixels.AppendElement(aTestCase.ChooseColor(BGRAColor::Green()));
330 framePixels.AppendElement(
331 aTestCase.ChooseColor(BGRAColor(0x7F, 0x7F, 0x7F, 0xFF)));
332
333 DrawableSurface drawableSurface(WrapNotNull(aProvider));
334 for (size_t i = 0; i < framePixels.Length(); ++i) {
335 nsresult rv = drawableSurface.Seek(i);
336 EXPECT_TRUE(NS_SUCCEEDED(rv));
337
338 // Check the first frame, all green.
339 RawAccessFrameRef rawFrame = drawableSurface->RawAccessRef();
340 RefPtr<SourceSurface> surface = rawFrame->GetSourceSurface();
341
342 // Verify that the resulting surfaces matches our expectations.
343 EXPECT_TRUE(surface->IsDataSourceSurface());
344 EXPECT_TRUE(surface->GetFormat() == SurfaceFormat::OS_RGBX ||
345 surface->GetFormat() == SurfaceFormat::OS_RGBA);
346 EXPECT_EQ(aTestCase.mOutputSize, surface->GetSize());
347 EXPECT_TRUE(IsSolidColor(surface, framePixels[i], aTestCase.Fuzz()));
348 }
349
350 // Should be no more frames.
351 nsresult rv = drawableSurface.Seek(framePixels.Length());
352 EXPECT_TRUE(NS_FAILED(rv));
353 }
354
355 template <typename Func>
WithSingleChunkAnimationDecode(const ImageTestCase & aTestCase,Func aResultChecker)356 static void WithSingleChunkAnimationDecode(const ImageTestCase& aTestCase,
357 Func aResultChecker) {
358 // Create an image.
359 RefPtr<Image> image = ImageFactory::CreateAnonymousImage(
360 nsDependentCString(aTestCase.mMimeType));
361 ASSERT_TRUE(!image->HasError());
362
363 NotNull<RefPtr<RasterImage>> rasterImage =
364 WrapNotNull(static_cast<RasterImage*>(image.get()));
365
366 nsCOMPtr<nsIInputStream> inputStream = LoadFile(aTestCase.mPath);
367 ASSERT_TRUE(inputStream != nullptr);
368
369 // Figure out how much data we have.
370 uint64_t length;
371 nsresult rv = inputStream->Available(&length);
372 ASSERT_TRUE(NS_SUCCEEDED(rv));
373
374 // Write the data into a SourceBuffer.
375 NotNull<RefPtr<SourceBuffer>> sourceBuffer = WrapNotNull(new SourceBuffer());
376 sourceBuffer->ExpectLength(length);
377 rv = sourceBuffer->AppendFromInputStream(inputStream, length);
378 ASSERT_TRUE(NS_SUCCEEDED(rv));
379 sourceBuffer->Complete(NS_OK);
380
381 // Create a metadata decoder first, because otherwise RasterImage will get
382 // unhappy about finding out the image is animated during a full decode.
383 DecoderType decoderType = DecoderFactory::GetDecoderType(aTestCase.mMimeType);
384 RefPtr<IDecodingTask> task = DecoderFactory::CreateMetadataDecoder(
385 decoderType, rasterImage, sourceBuffer);
386 ASSERT_TRUE(task != nullptr);
387
388 // Run the metadata decoder synchronously.
389 task->Run();
390
391 // Create a decoder.
392 DecoderFlags decoderFlags = DefaultDecoderFlags();
393 SurfaceFlags surfaceFlags = aTestCase.mSurfaceFlags;
394 RefPtr<image::Decoder> decoder = DecoderFactory::CreateAnonymousDecoder(
395 decoderType, sourceBuffer, Nothing(), decoderFlags, surfaceFlags);
396 ASSERT_TRUE(decoder != nullptr);
397
398 // Create an AnimationSurfaceProvider which will manage the decoding process
399 // and make this decoder's output available in the surface cache.
400 SurfaceKey surfaceKey = RasterSurfaceKey(aTestCase.mOutputSize, surfaceFlags,
401 PlaybackType::eAnimated);
402 RefPtr<AnimationSurfaceProvider> provider = new AnimationSurfaceProvider(
403 rasterImage, surfaceKey, WrapNotNull(decoder),
404 /* aCurrentFrame */ 0);
405
406 // Run the full decoder synchronously.
407 provider->Run();
408
409 // Call the lambda to verify the expected results.
410 aResultChecker(provider, decoder);
411 }
412
CheckAnimationDecoderSingleChunk(const ImageTestCase & aTestCase)413 static void CheckAnimationDecoderSingleChunk(const ImageTestCase& aTestCase) {
414 WithSingleChunkAnimationDecode(
415 aTestCase,
416 [&](AnimationSurfaceProvider* aProvider, image::Decoder* aDecoder) {
417 CheckAnimationDecoderResults(aTestCase, aProvider, aDecoder);
418 });
419 }
420
CheckDecoderFrameFirst(const ImageTestCase & aTestCase)421 static void CheckDecoderFrameFirst(const ImageTestCase& aTestCase) {
422 // Verify that we can decode this test case and retrieve the first frame using
423 // imgIContainer::FRAME_FIRST. This ensures that we correctly trigger a
424 // single-frame decode rather than an animated decode when
425 // imgIContainer::FRAME_FIRST is requested.
426
427 // Create an image.
428 RefPtr<Image> image = ImageFactory::CreateAnonymousImage(
429 nsDependentCString(aTestCase.mMimeType));
430 ASSERT_TRUE(!image->HasError());
431
432 nsCOMPtr<nsIInputStream> inputStream = LoadFile(aTestCase.mPath);
433 ASSERT_TRUE(inputStream);
434
435 // Figure out how much data we have.
436 uint64_t length;
437 nsresult rv = inputStream->Available(&length);
438 ASSERT_TRUE(NS_SUCCEEDED(rv));
439
440 // Write the data into the image.
441 rv = image->OnImageDataAvailable(nullptr, nullptr, inputStream, 0,
442 static_cast<uint32_t>(length));
443 ASSERT_TRUE(NS_SUCCEEDED(rv));
444
445 // Let the image know we've sent all the data.
446 rv = image->OnImageDataComplete(nullptr, nullptr, NS_OK, true);
447 ASSERT_TRUE(NS_SUCCEEDED(rv));
448
449 RefPtr<ProgressTracker> tracker = image->GetProgressTracker();
450 tracker->SyncNotifyProgress(FLAG_LOAD_COMPLETE);
451
452 // Lock the image so its surfaces don't disappear during the test.
453 image->LockImage();
454
455 auto unlock = mozilla::MakeScopeExit([&] { image->UnlockImage(); });
456
457 // Use GetFrame() to force a sync decode of the image, specifying FRAME_FIRST
458 // to ensure that we don't get an animated decode.
459 RefPtr<SourceSurface> surface = image->GetFrame(
460 imgIContainer::FRAME_FIRST, imgIContainer::FLAG_SYNC_DECODE);
461
462 // Ensure that the image's metadata meets our expectations.
463 IntSize imageSize(0, 0);
464 rv = image->GetWidth(&imageSize.width);
465 EXPECT_TRUE(NS_SUCCEEDED(rv));
466 rv = image->GetHeight(&imageSize.height);
467 EXPECT_TRUE(NS_SUCCEEDED(rv));
468
469 EXPECT_EQ(aTestCase.mSize.width, imageSize.width);
470 EXPECT_EQ(aTestCase.mSize.height, imageSize.height);
471
472 Progress imageProgress = tracker->GetProgress();
473
474 EXPECT_TRUE(bool(imageProgress & FLAG_HAS_TRANSPARENCY) == false);
475 EXPECT_TRUE(bool(imageProgress & FLAG_IS_ANIMATED) == true);
476
477 // Ensure that we decoded the static version of the image.
478 {
479 LookupResult result = SurfaceCache::Lookup(
480 ImageKey(image.get()),
481 RasterSurfaceKey(imageSize, aTestCase.mSurfaceFlags,
482 PlaybackType::eStatic),
483 /* aMarkUsed = */ false);
484 ASSERT_EQ(MatchType::EXACT, result.Type());
485 EXPECT_TRUE(bool(result.Surface()));
486 }
487
488 // Ensure that we didn't decode the animated version of the image.
489 {
490 LookupResult result = SurfaceCache::Lookup(
491 ImageKey(image.get()),
492 RasterSurfaceKey(imageSize, aTestCase.mSurfaceFlags,
493 PlaybackType::eAnimated),
494 /* aMarkUsed = */ false);
495 ASSERT_EQ(MatchType::NOT_FOUND, result.Type());
496 }
497
498 // Use GetFrame() to force a sync decode of the image, this time specifying
499 // FRAME_CURRENT to ensure that we get an animated decode.
500 RefPtr<SourceSurface> animatedSurface = image->GetFrame(
501 imgIContainer::FRAME_CURRENT, imgIContainer::FLAG_SYNC_DECODE);
502
503 // Ensure that we decoded both frames of the animated version of the image.
504 {
505 LookupResult result = SurfaceCache::Lookup(
506 ImageKey(image.get()),
507 RasterSurfaceKey(imageSize, aTestCase.mSurfaceFlags,
508 PlaybackType::eAnimated),
509 /* aMarkUsed = */ true);
510 ASSERT_EQ(MatchType::EXACT, result.Type());
511
512 EXPECT_TRUE(NS_SUCCEEDED(result.Surface().Seek(0)));
513 EXPECT_TRUE(bool(result.Surface()));
514
515 RefPtr<imgFrame> partialFrame = result.Surface().GetFrame(1);
516 EXPECT_TRUE(bool(partialFrame));
517 }
518
519 // Ensure that the static version is still around.
520 {
521 LookupResult result = SurfaceCache::Lookup(
522 ImageKey(image.get()),
523 RasterSurfaceKey(imageSize, aTestCase.mSurfaceFlags,
524 PlaybackType::eStatic),
525 /* aMarkUsed = */ true);
526 ASSERT_EQ(MatchType::EXACT, result.Type());
527 EXPECT_TRUE(bool(result.Surface()));
528 }
529 }
530
CheckDecoderFrameCurrent(const ImageTestCase & aTestCase)531 static void CheckDecoderFrameCurrent(const ImageTestCase& aTestCase) {
532 // Verify that we can decode this test case and retrieve the entire sequence
533 // of frames using imgIContainer::FRAME_CURRENT. This ensures that we
534 // correctly trigger an animated decode rather than a single-frame decode when
535 // imgIContainer::FRAME_CURRENT is requested.
536
537 // Create an image.
538 RefPtr<Image> image = ImageFactory::CreateAnonymousImage(
539 nsDependentCString(aTestCase.mMimeType));
540 ASSERT_TRUE(!image->HasError());
541
542 nsCOMPtr<nsIInputStream> inputStream = LoadFile(aTestCase.mPath);
543 ASSERT_TRUE(inputStream);
544
545 // Figure out how much data we have.
546 uint64_t length;
547 nsresult rv = inputStream->Available(&length);
548 ASSERT_TRUE(NS_SUCCEEDED(rv));
549
550 // Write the data into the image.
551 rv = image->OnImageDataAvailable(nullptr, nullptr, inputStream, 0,
552 static_cast<uint32_t>(length));
553 ASSERT_TRUE(NS_SUCCEEDED(rv));
554
555 // Let the image know we've sent all the data.
556 rv = image->OnImageDataComplete(nullptr, nullptr, NS_OK, true);
557 ASSERT_TRUE(NS_SUCCEEDED(rv));
558
559 RefPtr<ProgressTracker> tracker = image->GetProgressTracker();
560 tracker->SyncNotifyProgress(FLAG_LOAD_COMPLETE);
561
562 // Lock the image so its surfaces don't disappear during the test.
563 image->LockImage();
564
565 // Use GetFrame() to force a sync decode of the image, specifying
566 // FRAME_CURRENT to ensure we get an animated decode.
567 RefPtr<SourceSurface> surface = image->GetFrame(
568 imgIContainer::FRAME_CURRENT, imgIContainer::FLAG_SYNC_DECODE);
569
570 // Ensure that the image's metadata meets our expectations.
571 IntSize imageSize(0, 0);
572 rv = image->GetWidth(&imageSize.width);
573 EXPECT_TRUE(NS_SUCCEEDED(rv));
574 rv = image->GetHeight(&imageSize.height);
575 EXPECT_TRUE(NS_SUCCEEDED(rv));
576
577 EXPECT_EQ(aTestCase.mSize.width, imageSize.width);
578 EXPECT_EQ(aTestCase.mSize.height, imageSize.height);
579
580 Progress imageProgress = tracker->GetProgress();
581
582 EXPECT_TRUE(bool(imageProgress & FLAG_HAS_TRANSPARENCY) == false);
583 EXPECT_TRUE(bool(imageProgress & FLAG_IS_ANIMATED) == true);
584
585 // Ensure that we decoded both frames of the animated version of the image.
586 {
587 LookupResult result = SurfaceCache::Lookup(
588 ImageKey(image.get()),
589 RasterSurfaceKey(imageSize, aTestCase.mSurfaceFlags,
590 PlaybackType::eAnimated),
591 /* aMarkUsed = */ true);
592 ASSERT_EQ(MatchType::EXACT, result.Type());
593
594 EXPECT_TRUE(NS_SUCCEEDED(result.Surface().Seek(0)));
595 EXPECT_TRUE(bool(result.Surface()));
596
597 RefPtr<imgFrame> partialFrame = result.Surface().GetFrame(1);
598 EXPECT_TRUE(bool(partialFrame));
599 }
600
601 // Ensure that we didn't decode the static version of the image.
602 {
603 LookupResult result = SurfaceCache::Lookup(
604 ImageKey(image.get()),
605 RasterSurfaceKey(imageSize, aTestCase.mSurfaceFlags,
606 PlaybackType::eStatic),
607 /* aMarkUsed = */ false);
608 ASSERT_EQ(MatchType::NOT_FOUND, result.Type());
609 }
610
611 // Use GetFrame() to force a sync decode of the image, this time specifying
612 // FRAME_FIRST to ensure that we get a single-frame decode.
613 RefPtr<SourceSurface> animatedSurface = image->GetFrame(
614 imgIContainer::FRAME_FIRST, imgIContainer::FLAG_SYNC_DECODE);
615
616 // Ensure that we decoded the static version of the image.
617 {
618 LookupResult result = SurfaceCache::Lookup(
619 ImageKey(image.get()),
620 RasterSurfaceKey(imageSize, aTestCase.mSurfaceFlags,
621 PlaybackType::eStatic),
622 /* aMarkUsed = */ true);
623 ASSERT_EQ(MatchType::EXACT, result.Type());
624 EXPECT_TRUE(bool(result.Surface()));
625 }
626
627 // Ensure that both frames of the animated version are still around.
628 {
629 LookupResult result = SurfaceCache::Lookup(
630 ImageKey(image.get()),
631 RasterSurfaceKey(imageSize, aTestCase.mSurfaceFlags,
632 PlaybackType::eAnimated),
633 /* aMarkUsed = */ true);
634 ASSERT_EQ(MatchType::EXACT, result.Type());
635
636 EXPECT_TRUE(NS_SUCCEEDED(result.Surface().Seek(0)));
637 EXPECT_TRUE(bool(result.Surface()));
638
639 RefPtr<imgFrame> partialFrame = result.Surface().GetFrame(1);
640 EXPECT_TRUE(bool(partialFrame));
641 }
642 }
643
644 class ImageDecoders : public ::testing::Test {
645 protected:
646 AutoInitializeImageLib mInit;
647 };
648
649 #define IMAGE_GTEST_DECODER_BASE_F(test_prefix) \
650 TEST_F(ImageDecoders, test_prefix##SingleChunk) { \
651 CheckDecoderSingleChunk(Green##test_prefix##TestCase()); \
652 } \
653 \
654 TEST_F(ImageDecoders, test_prefix##DelayedChunk) { \
655 CheckDecoderDelayedChunk(Green##test_prefix##TestCase()); \
656 } \
657 \
658 TEST_F(ImageDecoders, test_prefix##MultiChunk) { \
659 CheckDecoderMultiChunk(Green##test_prefix##TestCase()); \
660 } \
661 \
662 TEST_F(ImageDecoders, test_prefix##DownscaleDuringDecode) { \
663 CheckDownscaleDuringDecode(Downscaled##test_prefix##TestCase()); \
664 } \
665 \
666 TEST_F(ImageDecoders, test_prefix##ForceSRGB) { \
667 CheckDecoderSingleChunk(Green##test_prefix##TestCase().WithSurfaceFlags( \
668 SurfaceFlags::TO_SRGB_COLORSPACE)); \
669 } \
670 \
671 TEST_F(ImageDecoders, test_prefix##BadBuffer) { \
672 CheckDecoderBadBuffer(Green##test_prefix##TestCase().WithFlags( \
673 TEST_CASE_HAS_ERROR | TEST_CASE_IGNORE_OUTPUT)); \
674 }
675
676 IMAGE_GTEST_DECODER_BASE_F(PNG)
IMAGE_GTEST_DECODER_BASE_F(GIF)677 IMAGE_GTEST_DECODER_BASE_F(GIF)
678 IMAGE_GTEST_DECODER_BASE_F(JPG)
679 IMAGE_GTEST_DECODER_BASE_F(BMP)
680 IMAGE_GTEST_DECODER_BASE_F(ICO)
681 IMAGE_GTEST_DECODER_BASE_F(Icon)
682 IMAGE_GTEST_DECODER_BASE_F(WebP)
683 #ifdef MOZ_JXL
684 IMAGE_GTEST_DECODER_BASE_F(JXL)
685 #endif
686
687 TEST_F(ImageDecoders, ICOWithANDMaskDownscaleDuringDecode) {
688 CheckDownscaleDuringDecode(DownscaledTransparentICOWithANDMaskTestCase());
689 }
690
TEST_F(ImageDecoders,WebPLargeMultiChunk)691 TEST_F(ImageDecoders, WebPLargeMultiChunk) {
692 CheckDecoderMultiChunk(LargeWebPTestCase(), /* aChunkSize */ 64);
693 }
694
TEST_F(ImageDecoders,WebPIccSrgbMultiChunk)695 TEST_F(ImageDecoders, WebPIccSrgbMultiChunk) {
696 CheckDecoderMultiChunk(GreenWebPIccSrgbTestCase());
697 }
698
TEST_F(ImageDecoders,WebPTransparentSingleChunk)699 TEST_F(ImageDecoders, WebPTransparentSingleChunk) {
700 CheckDecoderSingleChunk(TransparentWebPTestCase());
701 }
702
TEST_F(ImageDecoders,WebPTransparentNoAlphaHeaderSingleChunk)703 TEST_F(ImageDecoders, WebPTransparentNoAlphaHeaderSingleChunk) {
704 CheckDecoderSingleChunk(TransparentNoAlphaHeaderWebPTestCase());
705 }
706
TEST_F(ImageDecoders,AVIFSingleChunk)707 TEST_F(ImageDecoders, AVIFSingleChunk) {
708 CheckDecoderSingleChunk(GreenAVIFTestCase());
709 }
710
TEST_F(ImageDecoders,AVIFSingleChunkTransparent10bit420)711 TEST_F(ImageDecoders, AVIFSingleChunkTransparent10bit420) {
712 CheckDecoderSingleChunk(Transparent10bit420AVIFTestCase());
713 }
714
TEST_F(ImageDecoders,AVIFSingleChunkTransparent10bit422)715 TEST_F(ImageDecoders, AVIFSingleChunkTransparent10bit422) {
716 CheckDecoderSingleChunk(Transparent10bit422AVIFTestCase());
717 }
718
TEST_F(ImageDecoders,AVIFSingleChunkTransparent10bit444)719 TEST_F(ImageDecoders, AVIFSingleChunkTransparent10bit444) {
720 CheckDecoderSingleChunk(Transparent10bit444AVIFTestCase());
721 }
722
TEST_F(ImageDecoders,AVIFSingleChunkTransparent12bit420)723 TEST_F(ImageDecoders, AVIFSingleChunkTransparent12bit420) {
724 CheckDecoderSingleChunk(Transparent12bit420AVIFTestCase());
725 }
726
TEST_F(ImageDecoders,AVIFSingleChunkTransparent12bit422)727 TEST_F(ImageDecoders, AVIFSingleChunkTransparent12bit422) {
728 CheckDecoderSingleChunk(Transparent12bit422AVIFTestCase());
729 }
730
TEST_F(ImageDecoders,AVIFSingleChunkTransparent12bit444)731 TEST_F(ImageDecoders, AVIFSingleChunkTransparent12bit444) {
732 CheckDecoderSingleChunk(Transparent12bit444AVIFTestCase());
733 }
734
TEST_F(ImageDecoders,AVIFSingleChunkTransparent8bit420)735 TEST_F(ImageDecoders, AVIFSingleChunkTransparent8bit420) {
736 CheckDecoderSingleChunk(Transparent8bit420AVIFTestCase());
737 }
738
TEST_F(ImageDecoders,AVIFSingleChunkTransparent8bit422)739 TEST_F(ImageDecoders, AVIFSingleChunkTransparent8bit422) {
740 CheckDecoderSingleChunk(Transparent8bit422AVIFTestCase());
741 }
742
TEST_F(ImageDecoders,AVIFSingleChunkTransparent8bit444)743 TEST_F(ImageDecoders, AVIFSingleChunkTransparent8bit444) {
744 CheckDecoderSingleChunk(Transparent8bit444AVIFTestCase());
745 }
746
TEST_F(ImageDecoders,AVIFSingleChunkGray8bitLimitedRangeBT601)747 TEST_F(ImageDecoders, AVIFSingleChunkGray8bitLimitedRangeBT601) {
748 CheckDecoderSingleChunk(Gray8bitLimitedRangeBT601AVIFTestCase());
749 }
750
TEST_F(ImageDecoders,AVIFSingleChunkGray8bitLimitedRangeBT709)751 TEST_F(ImageDecoders, AVIFSingleChunkGray8bitLimitedRangeBT709) {
752 CheckDecoderSingleChunk(Gray8bitLimitedRangeBT709AVIFTestCase());
753 }
754
TEST_F(ImageDecoders,AVIFSingleChunkGray8bitLimitedRangeBT2020)755 TEST_F(ImageDecoders, AVIFSingleChunkGray8bitLimitedRangeBT2020) {
756 CheckDecoderSingleChunk(Gray8bitLimitedRangeBT2020AVIFTestCase());
757 }
758
TEST_F(ImageDecoders,AVIFSingleChunkGray8bitFullRangeBT601)759 TEST_F(ImageDecoders, AVIFSingleChunkGray8bitFullRangeBT601) {
760 CheckDecoderSingleChunk(Gray8bitFullRangeBT601AVIFTestCase());
761 }
762
TEST_F(ImageDecoders,AVIFSingleChunkGray8bitFullRangeBT709)763 TEST_F(ImageDecoders, AVIFSingleChunkGray8bitFullRangeBT709) {
764 CheckDecoderSingleChunk(Gray8bitFullRangeBT709AVIFTestCase());
765 }
766
TEST_F(ImageDecoders,AVIFSingleChunkGray8bitFullRangeBT2020)767 TEST_F(ImageDecoders, AVIFSingleChunkGray8bitFullRangeBT2020) {
768 CheckDecoderSingleChunk(Gray8bitFullRangeBT2020AVIFTestCase());
769 }
770
TEST_F(ImageDecoders,AVIFSingleChunkGray10bitLimitedRangeBT601)771 TEST_F(ImageDecoders, AVIFSingleChunkGray10bitLimitedRangeBT601) {
772 CheckDecoderSingleChunk(Gray10bitLimitedRangeBT601AVIFTestCase());
773 }
774
TEST_F(ImageDecoders,AVIFSingleChunkGray10bitLimitedRangeBT709)775 TEST_F(ImageDecoders, AVIFSingleChunkGray10bitLimitedRangeBT709) {
776 CheckDecoderSingleChunk(Gray10bitLimitedRangeBT709AVIFTestCase());
777 }
778
TEST_F(ImageDecoders,AVIFSingleChunkGray10bitLimitedRangeBT2020)779 TEST_F(ImageDecoders, AVIFSingleChunkGray10bitLimitedRangeBT2020) {
780 CheckDecoderSingleChunk(Gray10bitLimitedRangeBT2020AVIFTestCase());
781 }
782
TEST_F(ImageDecoders,AVIFSingleChunkGray10bitFullRangeBT601)783 TEST_F(ImageDecoders, AVIFSingleChunkGray10bitFullRangeBT601) {
784 CheckDecoderSingleChunk(Gray10bitFullRangeBT601AVIFTestCase());
785 }
786
TEST_F(ImageDecoders,AVIFSingleChunkGray10bitFullRangeBT709)787 TEST_F(ImageDecoders, AVIFSingleChunkGray10bitFullRangeBT709) {
788 CheckDecoderSingleChunk(Gray10bitFullRangeBT709AVIFTestCase());
789 }
790
TEST_F(ImageDecoders,AVIFSingleChunkGray10bitFullRangeBT2020)791 TEST_F(ImageDecoders, AVIFSingleChunkGray10bitFullRangeBT2020) {
792 CheckDecoderSingleChunk(Gray10bitFullRangeBT2020AVIFTestCase());
793 }
794
TEST_F(ImageDecoders,AVIFSingleChunkGray12bitLimitedRangeBT601)795 TEST_F(ImageDecoders, AVIFSingleChunkGray12bitLimitedRangeBT601) {
796 CheckDecoderSingleChunk(Gray12bitLimitedRangeBT601AVIFTestCase());
797 }
798
TEST_F(ImageDecoders,AVIFSingleChunkGray12bitLimitedRangeBT709)799 TEST_F(ImageDecoders, AVIFSingleChunkGray12bitLimitedRangeBT709) {
800 CheckDecoderSingleChunk(Gray12bitLimitedRangeBT709AVIFTestCase());
801 }
802
TEST_F(ImageDecoders,AVIFSingleChunkGray12bitLimitedRangeBT2020)803 TEST_F(ImageDecoders, AVIFSingleChunkGray12bitLimitedRangeBT2020) {
804 CheckDecoderSingleChunk(Gray12bitLimitedRangeBT2020AVIFTestCase());
805 }
806
TEST_F(ImageDecoders,AVIFSingleChunkGray12bitFullRangeBT601)807 TEST_F(ImageDecoders, AVIFSingleChunkGray12bitFullRangeBT601) {
808 CheckDecoderSingleChunk(Gray12bitFullRangeBT601AVIFTestCase());
809 }
810
TEST_F(ImageDecoders,AVIFSingleChunkGray12bitFullRangeBT709)811 TEST_F(ImageDecoders, AVIFSingleChunkGray12bitFullRangeBT709) {
812 CheckDecoderSingleChunk(Gray12bitFullRangeBT709AVIFTestCase());
813 }
814
TEST_F(ImageDecoders,AVIFSingleChunkGray12bitFullRangeBT2020)815 TEST_F(ImageDecoders, AVIFSingleChunkGray12bitFullRangeBT2020) {
816 CheckDecoderSingleChunk(Gray12bitFullRangeBT2020AVIFTestCase());
817 }
818
TEST_F(ImageDecoders,AVIFSingleChunkGray8bitLimitedRangeGrayscale)819 TEST_F(ImageDecoders, AVIFSingleChunkGray8bitLimitedRangeGrayscale) {
820 CheckDecoderSingleChunk(Gray8bitLimitedRangeGrayscaleAVIFTestCase());
821 }
822
TEST_F(ImageDecoders,AVIFSingleChunkGray8bitFullRangeGrayscale)823 TEST_F(ImageDecoders, AVIFSingleChunkGray8bitFullRangeGrayscale) {
824 CheckDecoderSingleChunk(Gray8bitFullRangeGrayscaleAVIFTestCase());
825 }
826
TEST_F(ImageDecoders,AVIFSingleChunkGray10bitLimitedRangeGrayscale)827 TEST_F(ImageDecoders, AVIFSingleChunkGray10bitLimitedRangeGrayscale) {
828 CheckDecoderSingleChunk(Gray10bitLimitedRangeGrayscaleAVIFTestCase());
829 }
830
TEST_F(ImageDecoders,AVIFSingleChunkGray10bitFullRangeGrayscale)831 TEST_F(ImageDecoders, AVIFSingleChunkGray10bitFullRangeGrayscale) {
832 CheckDecoderSingleChunk(Gray10bitFullRangeGrayscaleAVIFTestCase());
833 }
834
TEST_F(ImageDecoders,AVIFSingleChunkGray12bitLimitedRangeGrayscale)835 TEST_F(ImageDecoders, AVIFSingleChunkGray12bitLimitedRangeGrayscale) {
836 CheckDecoderSingleChunk(Gray12bitLimitedRangeGrayscaleAVIFTestCase());
837 }
838
TEST_F(ImageDecoders,AVIFSingleChunkGray12bitFullRangeGrayscale)839 TEST_F(ImageDecoders, AVIFSingleChunkGray12bitFullRangeGrayscale) {
840 CheckDecoderSingleChunk(Gray12bitFullRangeGrayscaleAVIFTestCase());
841 }
842
TEST_F(ImageDecoders,AVIFMultiLayerSingleChunk)843 TEST_F(ImageDecoders, AVIFMultiLayerSingleChunk) {
844 CheckDecoderSingleChunk(MultiLayerAVIFTestCase());
845 }
846
847 // This test must use the decode pool in order to check for regressions
848 // of crashing the dav1d decoder when the ImgDecoder threads have a standard-
849 // sized stack.
TEST_F(ImageDecoders,AVIFStackCheck)850 TEST_F(ImageDecoders, AVIFStackCheck) {
851 CheckDecoderSingleChunk(StackCheckAVIFTestCase(), /* aUseDecodePool */ true);
852 }
853
TEST_F(ImageDecoders,AVIFDelayedChunk)854 TEST_F(ImageDecoders, AVIFDelayedChunk) {
855 CheckDecoderDelayedChunk(GreenAVIFTestCase());
856 }
857
TEST_F(ImageDecoders,AVIFMultiChunk)858 TEST_F(ImageDecoders, AVIFMultiChunk) {
859 CheckDecoderMultiChunk(GreenAVIFTestCase());
860 }
861
TEST_F(ImageDecoders,AVIFLargeMultiChunk)862 TEST_F(ImageDecoders, AVIFLargeMultiChunk) {
863 CheckDecoderMultiChunk(LargeAVIFTestCase(), /* aChunkSize */ 64);
864 }
865
TEST_F(ImageDecoders,AVIFDownscaleDuringDecode)866 TEST_F(ImageDecoders, AVIFDownscaleDuringDecode) {
867 CheckDownscaleDuringDecode(DownscaledAVIFTestCase());
868 }
869
870 #ifdef MOZ_JXL
TEST_F(ImageDecoders,JXLLargeMultiChunk)871 TEST_F(ImageDecoders, JXLLargeMultiChunk) {
872 CheckDecoderMultiChunk(LargeJXLTestCase(), /* aChunkSize */ 64);
873 }
874 #endif
875
TEST_F(ImageDecoders,AnimatedGIFSingleChunk)876 TEST_F(ImageDecoders, AnimatedGIFSingleChunk) {
877 CheckDecoderSingleChunk(GreenFirstFrameAnimatedGIFTestCase());
878 }
879
TEST_F(ImageDecoders,AnimatedGIFMultiChunk)880 TEST_F(ImageDecoders, AnimatedGIFMultiChunk) {
881 CheckDecoderMultiChunk(GreenFirstFrameAnimatedGIFTestCase());
882 }
883
TEST_F(ImageDecoders,AnimatedGIFWithBlendedFrames)884 TEST_F(ImageDecoders, AnimatedGIFWithBlendedFrames) {
885 CheckAnimationDecoderSingleChunk(GreenFirstFrameAnimatedGIFTestCase());
886 }
887
TEST_F(ImageDecoders,AnimatedPNGSingleChunk)888 TEST_F(ImageDecoders, AnimatedPNGSingleChunk) {
889 CheckDecoderSingleChunk(GreenFirstFrameAnimatedPNGTestCase());
890 }
891
TEST_F(ImageDecoders,AnimatedPNGMultiChunk)892 TEST_F(ImageDecoders, AnimatedPNGMultiChunk) {
893 CheckDecoderMultiChunk(GreenFirstFrameAnimatedPNGTestCase());
894 }
895
TEST_F(ImageDecoders,AnimatedPNGWithBlendedFrames)896 TEST_F(ImageDecoders, AnimatedPNGWithBlendedFrames) {
897 CheckAnimationDecoderSingleChunk(GreenFirstFrameAnimatedPNGTestCase());
898 }
899
TEST_F(ImageDecoders,AnimatedWebPSingleChunk)900 TEST_F(ImageDecoders, AnimatedWebPSingleChunk) {
901 CheckDecoderSingleChunk(GreenFirstFrameAnimatedWebPTestCase());
902 }
903
TEST_F(ImageDecoders,AnimatedWebPMultiChunk)904 TEST_F(ImageDecoders, AnimatedWebPMultiChunk) {
905 CheckDecoderMultiChunk(GreenFirstFrameAnimatedWebPTestCase());
906 }
907
TEST_F(ImageDecoders,AnimatedWebPWithBlendedFrames)908 TEST_F(ImageDecoders, AnimatedWebPWithBlendedFrames) {
909 CheckAnimationDecoderSingleChunk(GreenFirstFrameAnimatedWebPTestCase());
910 }
911
TEST_F(ImageDecoders,CorruptSingleChunk)912 TEST_F(ImageDecoders, CorruptSingleChunk) {
913 CheckDecoderSingleChunk(CorruptTestCase());
914 }
915
TEST_F(ImageDecoders,CorruptMultiChunk)916 TEST_F(ImageDecoders, CorruptMultiChunk) {
917 CheckDecoderMultiChunk(CorruptTestCase());
918 }
919
TEST_F(ImageDecoders,CorruptBMPWithTruncatedHeaderSingleChunk)920 TEST_F(ImageDecoders, CorruptBMPWithTruncatedHeaderSingleChunk) {
921 CheckDecoderSingleChunk(CorruptBMPWithTruncatedHeader());
922 }
923
TEST_F(ImageDecoders,CorruptBMPWithTruncatedHeaderMultiChunk)924 TEST_F(ImageDecoders, CorruptBMPWithTruncatedHeaderMultiChunk) {
925 CheckDecoderMultiChunk(CorruptBMPWithTruncatedHeader());
926 }
927
TEST_F(ImageDecoders,CorruptICOWithBadBMPWidthSingleChunk)928 TEST_F(ImageDecoders, CorruptICOWithBadBMPWidthSingleChunk) {
929 CheckDecoderSingleChunk(CorruptICOWithBadBMPWidthTestCase());
930 }
931
TEST_F(ImageDecoders,CorruptICOWithBadBMPWidthMultiChunk)932 TEST_F(ImageDecoders, CorruptICOWithBadBMPWidthMultiChunk) {
933 CheckDecoderMultiChunk(CorruptICOWithBadBMPWidthTestCase());
934 }
935
TEST_F(ImageDecoders,CorruptICOWithBadBMPHeightSingleChunk)936 TEST_F(ImageDecoders, CorruptICOWithBadBMPHeightSingleChunk) {
937 CheckDecoderSingleChunk(CorruptICOWithBadBMPHeightTestCase());
938 }
939
TEST_F(ImageDecoders,CorruptICOWithBadBMPHeightMultiChunk)940 TEST_F(ImageDecoders, CorruptICOWithBadBMPHeightMultiChunk) {
941 CheckDecoderMultiChunk(CorruptICOWithBadBMPHeightTestCase());
942 }
943
TEST_F(ImageDecoders,CorruptICOWithBadBppSingleChunk)944 TEST_F(ImageDecoders, CorruptICOWithBadBppSingleChunk) {
945 CheckDecoderSingleChunk(CorruptICOWithBadBppTestCase());
946 }
947
948 // Running this test under emulation for Android 7 on x86_64 seems to result
949 // in the large allocation succeeding, but leaving so little memory left the
950 // system falls over and it kills the test run, so we skip it instead.
951 // See bug 1655846 for more details.
952 #ifndef ANDROID
TEST_F(ImageDecoders,CorruptAVIFSingleChunk)953 TEST_F(ImageDecoders, CorruptAVIFSingleChunk) {
954 CheckDecoderSingleChunk(CorruptAVIFTestCase());
955 }
956 #endif
957
TEST_F(ImageDecoders,AnimatedGIFWithFRAME_FIRST)958 TEST_F(ImageDecoders, AnimatedGIFWithFRAME_FIRST) {
959 CheckDecoderFrameFirst(GreenFirstFrameAnimatedGIFTestCase());
960 }
961
TEST_F(ImageDecoders,AnimatedGIFWithFRAME_CURRENT)962 TEST_F(ImageDecoders, AnimatedGIFWithFRAME_CURRENT) {
963 CheckDecoderFrameCurrent(GreenFirstFrameAnimatedGIFTestCase());
964 }
965
TEST_F(ImageDecoders,AnimatedGIFWithExtraImageSubBlocks)966 TEST_F(ImageDecoders, AnimatedGIFWithExtraImageSubBlocks) {
967 ImageTestCase testCase = ExtraImageSubBlocksAnimatedGIFTestCase();
968
969 // Verify that we can decode this test case and get two frames, even though
970 // there are extra image sub blocks between the first and second frame. The
971 // extra data shouldn't confuse the decoder or cause the decode to fail.
972
973 // Create an image.
974 RefPtr<Image> image = TestCaseToDecodedImage(testCase);
975
976 // Ensure that the image's metadata meets our expectations.
977 IntSize imageSize(0, 0);
978 nsresult rv = image->GetWidth(&imageSize.width);
979 EXPECT_TRUE(NS_SUCCEEDED(rv));
980 rv = image->GetHeight(&imageSize.height);
981 EXPECT_TRUE(NS_SUCCEEDED(rv));
982
983 EXPECT_EQ(testCase.mSize.width, imageSize.width);
984 EXPECT_EQ(testCase.mSize.height, imageSize.height);
985
986 RefPtr<ProgressTracker> tracker = image->GetProgressTracker();
987 Progress imageProgress = tracker->GetProgress();
988
989 EXPECT_TRUE(bool(imageProgress & FLAG_HAS_TRANSPARENCY) == false);
990 EXPECT_TRUE(bool(imageProgress & FLAG_IS_ANIMATED) == true);
991
992 // Ensure that we decoded both frames of the image.
993 LookupResult result =
994 SurfaceCache::Lookup(ImageKey(image.get()),
995 RasterSurfaceKey(imageSize, testCase.mSurfaceFlags,
996 PlaybackType::eAnimated),
997 /* aMarkUsed = */ true);
998 ASSERT_EQ(MatchType::EXACT, result.Type());
999
1000 EXPECT_TRUE(NS_SUCCEEDED(result.Surface().Seek(0)));
1001 EXPECT_TRUE(bool(result.Surface()));
1002
1003 RefPtr<imgFrame> partialFrame = result.Surface().GetFrame(1);
1004 EXPECT_TRUE(bool(partialFrame));
1005 }
1006
TEST_F(ImageDecoders,AnimatedWebPWithFRAME_FIRST)1007 TEST_F(ImageDecoders, AnimatedWebPWithFRAME_FIRST) {
1008 CheckDecoderFrameFirst(GreenFirstFrameAnimatedWebPTestCase());
1009 }
1010
TEST_F(ImageDecoders,AnimatedWebPWithFRAME_CURRENT)1011 TEST_F(ImageDecoders, AnimatedWebPWithFRAME_CURRENT) {
1012 CheckDecoderFrameCurrent(GreenFirstFrameAnimatedWebPTestCase());
1013 }
1014
TEST_F(ImageDecoders,TruncatedSmallGIFSingleChunk)1015 TEST_F(ImageDecoders, TruncatedSmallGIFSingleChunk) {
1016 CheckDecoderSingleChunk(TruncatedSmallGIFTestCase());
1017 }
1018
TEST_F(ImageDecoders,LargeICOWithBMPSingleChunk)1019 TEST_F(ImageDecoders, LargeICOWithBMPSingleChunk) {
1020 CheckDecoderSingleChunk(LargeICOWithBMPTestCase());
1021 }
1022
TEST_F(ImageDecoders,LargeICOWithBMPMultiChunk)1023 TEST_F(ImageDecoders, LargeICOWithBMPMultiChunk) {
1024 CheckDecoderMultiChunk(LargeICOWithBMPTestCase(), /* aChunkSize */ 64);
1025 }
1026
TEST_F(ImageDecoders,LargeICOWithPNGSingleChunk)1027 TEST_F(ImageDecoders, LargeICOWithPNGSingleChunk) {
1028 CheckDecoderSingleChunk(LargeICOWithPNGTestCase());
1029 }
1030
TEST_F(ImageDecoders,LargeICOWithPNGMultiChunk)1031 TEST_F(ImageDecoders, LargeICOWithPNGMultiChunk) {
1032 CheckDecoderMultiChunk(LargeICOWithPNGTestCase());
1033 }
1034
TEST_F(ImageDecoders,MultipleSizesICOSingleChunk)1035 TEST_F(ImageDecoders, MultipleSizesICOSingleChunk) {
1036 ImageTestCase testCase = GreenMultipleSizesICOTestCase();
1037
1038 // Create an image.
1039 RefPtr<Image> image = ImageFactory::CreateAnonymousImage(
1040 nsDependentCString(testCase.mMimeType));
1041 ASSERT_TRUE(!image->HasError());
1042
1043 nsCOMPtr<nsIInputStream> inputStream = LoadFile(testCase.mPath);
1044 ASSERT_TRUE(inputStream);
1045
1046 // Figure out how much data we have.
1047 uint64_t length;
1048 nsresult rv = inputStream->Available(&length);
1049 ASSERT_TRUE(NS_SUCCEEDED(rv));
1050
1051 // Write the data into the image.
1052 rv = image->OnImageDataAvailable(nullptr, nullptr, inputStream, 0,
1053 static_cast<uint32_t>(length));
1054 ASSERT_TRUE(NS_SUCCEEDED(rv));
1055
1056 // Let the image know we've sent all the data.
1057 rv = image->OnImageDataComplete(nullptr, nullptr, NS_OK, true);
1058 ASSERT_TRUE(NS_SUCCEEDED(rv));
1059
1060 RefPtr<ProgressTracker> tracker = image->GetProgressTracker();
1061 tracker->SyncNotifyProgress(FLAG_LOAD_COMPLETE);
1062
1063 // Use GetFrame() to force a sync decode of the image.
1064 RefPtr<SourceSurface> surface = image->GetFrame(
1065 imgIContainer::FRAME_CURRENT, imgIContainer::FLAG_SYNC_DECODE);
1066
1067 // Ensure that the image's metadata meets our expectations.
1068 IntSize imageSize(0, 0);
1069 rv = image->GetWidth(&imageSize.width);
1070 EXPECT_TRUE(NS_SUCCEEDED(rv));
1071 rv = image->GetHeight(&imageSize.height);
1072 EXPECT_TRUE(NS_SUCCEEDED(rv));
1073
1074 EXPECT_EQ(testCase.mSize.width, imageSize.width);
1075 EXPECT_EQ(testCase.mSize.height, imageSize.height);
1076
1077 nsTArray<IntSize> nativeSizes;
1078 rv = image->GetNativeSizes(nativeSizes);
1079 EXPECT_TRUE(NS_SUCCEEDED(rv));
1080 ASSERT_EQ(6u, nativeSizes.Length());
1081
1082 IntSize expectedSizes[] = {IntSize(16, 16), IntSize(32, 32),
1083 IntSize(64, 64), IntSize(128, 128),
1084 IntSize(256, 256), IntSize(256, 128)};
1085
1086 for (int i = 0; i < 6; ++i) {
1087 EXPECT_EQ(expectedSizes[i], nativeSizes[i]);
1088 }
1089
1090 RefPtr<Image> image90 =
1091 ImageOps::Orient(image, Orientation(Angle::D90, Flip::Unflipped));
1092 rv = image90->GetNativeSizes(nativeSizes);
1093 EXPECT_TRUE(NS_SUCCEEDED(rv));
1094 ASSERT_EQ(6u, nativeSizes.Length());
1095
1096 for (int i = 0; i < 5; ++i) {
1097 EXPECT_EQ(expectedSizes[i], nativeSizes[i]);
1098 }
1099 EXPECT_EQ(IntSize(128, 256), nativeSizes[5]);
1100
1101 RefPtr<Image> image180 =
1102 ImageOps::Orient(image, Orientation(Angle::D180, Flip::Unflipped));
1103 rv = image180->GetNativeSizes(nativeSizes);
1104 EXPECT_TRUE(NS_SUCCEEDED(rv));
1105 ASSERT_EQ(6u, nativeSizes.Length());
1106
1107 for (int i = 0; i < 6; ++i) {
1108 EXPECT_EQ(expectedSizes[i], nativeSizes[i]);
1109 }
1110 }
1111
TEST_F(ImageDecoders,ExifResolutionEven)1112 TEST_F(ImageDecoders, ExifResolutionEven) {
1113 RefPtr<Image> image = TestCaseToDecodedImage(ExifResolutionTestCase());
1114 EXPECT_EQ(image->GetResolution(), Resolution(2.0, 2.0));
1115 }
1116