Bug 1293472 (Part 4) - Test that single-frame and animated decodes can coexist for the same image. r=edwin

This commit is contained in:
Seth Fowler 2016-08-18 01:00:23 -07:00
parent 1f92f3a7b9
commit 90008b4d20

View File

@ -365,6 +365,237 @@ TEST_F(ImageDecoders, CorruptICOWithBadBMPHeightMultiChunk)
CheckDecoderMultiChunk(CorruptICOWithBadBMPHeightTestCase());
}
TEST_F(ImageDecoders, AnimatedGIFWithFRAME_FIRST)
{
ImageTestCase testCase = GreenFirstFrameAnimatedGIFTestCase();
// Verify that we can decode this test case and retrieve the first frame using
// imgIContainer::FRAME_FIRST. This ensures that we correctly trigger a
// single-frame decode rather than an animated decode when
// imgIContainer::FRAME_FIRST is requested.
// Create an image.
RefPtr<Image> image =
ImageFactory::CreateAnonymousImage(nsDependentCString(testCase.mMimeType));
ASSERT_TRUE(!image->HasError());
nsCOMPtr<nsIInputStream> inputStream = LoadFile(testCase.mPath);
ASSERT_TRUE(inputStream);
// Figure out how much data we have.
uint64_t length;
nsresult rv = inputStream->Available(&length);
ASSERT_TRUE(NS_SUCCEEDED(rv));
// Write the data into the image.
rv = image->OnImageDataAvailable(nullptr, nullptr, inputStream, 0,
static_cast<uint32_t>(length));
ASSERT_TRUE(NS_SUCCEEDED(rv));
// Let the image know we've sent all the data.
rv = image->OnImageDataComplete(nullptr, nullptr, NS_OK, true);
ASSERT_TRUE(NS_SUCCEEDED(rv));
RefPtr<ProgressTracker> tracker = image->GetProgressTracker();
tracker->SyncNotifyProgress(FLAG_LOAD_COMPLETE);
// Lock the image so its surfaces don't disappear during the test.
image->LockImage();
// Use GetFrame() to force a sync decode of the image, specifying FRAME_FIRST
// to ensure that we don't get an animated decode.
RefPtr<SourceSurface> surface =
image->GetFrame(imgIContainer::FRAME_FIRST,
imgIContainer::FLAG_SYNC_DECODE);
// Ensure that the image's metadata meets our expectations.
IntSize imageSize(0, 0);
rv = image->GetWidth(&imageSize.width);
EXPECT_TRUE(NS_SUCCEEDED(rv));
rv = image->GetHeight(&imageSize.height);
EXPECT_TRUE(NS_SUCCEEDED(rv));
EXPECT_EQ(testCase.mSize.width, imageSize.width);
EXPECT_EQ(testCase.mSize.height, imageSize.height);
Progress imageProgress = tracker->GetProgress();
EXPECT_TRUE(bool(imageProgress & FLAG_HAS_TRANSPARENCY) == false);
EXPECT_TRUE(bool(imageProgress & FLAG_IS_ANIMATED) == true);
// Ensure that we decoded the static version of the image.
{
LookupResult result =
SurfaceCache::Lookup(ImageKey(image.get()),
RasterSurfaceKey(imageSize,
DefaultSurfaceFlags(),
PlaybackType::eStatic));
ASSERT_EQ(MatchType::EXACT, result.Type());
EXPECT_TRUE(bool(result.Surface()));
}
// Ensure that we didn't decode the animated version of the image.
{
LookupResult result =
SurfaceCache::Lookup(ImageKey(image.get()),
RasterSurfaceKey(imageSize,
DefaultSurfaceFlags(),
PlaybackType::eAnimated));
ASSERT_EQ(MatchType::NOT_FOUND, result.Type());
}
// Use GetFrame() to force a sync decode of the image, this time specifying
// FRAME_CURRENT to ensure that we get an animated decode.
RefPtr<SourceSurface> animatedSurface =
image->GetFrame(imgIContainer::FRAME_CURRENT,
imgIContainer::FLAG_SYNC_DECODE);
// Ensure that we decoded both frames of the animated version of the image.
{
LookupResult result =
SurfaceCache::Lookup(ImageKey(image.get()),
RasterSurfaceKey(imageSize,
DefaultSurfaceFlags(),
PlaybackType::eAnimated));
ASSERT_EQ(MatchType::EXACT, result.Type());
EXPECT_TRUE(NS_SUCCEEDED(result.Surface().Seek(0)));
EXPECT_TRUE(bool(result.Surface()));
EXPECT_TRUE(NS_SUCCEEDED(result.Surface().Seek(1)));
EXPECT_TRUE(bool(result.Surface()));
}
// Ensure that the static version is still around.
{
LookupResult result =
SurfaceCache::Lookup(ImageKey(image.get()),
RasterSurfaceKey(imageSize,
DefaultSurfaceFlags(),
PlaybackType::eStatic));
ASSERT_EQ(MatchType::EXACT, result.Type());
EXPECT_TRUE(bool(result.Surface()));
}
}
TEST_F(ImageDecoders, AnimatedGIFWithFRAME_CURRENT)
{
ImageTestCase testCase = GreenFirstFrameAnimatedGIFTestCase();
// Verify that we can decode this test case and retrieve the entire sequence
// of frames using imgIContainer::FRAME_CURRENT. This ensures that we
// correctly trigger an animated decode rather than a single-frame decode when
// imgIContainer::FRAME_CURRENT is requested.
// Create an image.
RefPtr<Image> image =
ImageFactory::CreateAnonymousImage(nsDependentCString(testCase.mMimeType));
ASSERT_TRUE(!image->HasError());
nsCOMPtr<nsIInputStream> inputStream = LoadFile(testCase.mPath);
ASSERT_TRUE(inputStream);
// Figure out how much data we have.
uint64_t length;
nsresult rv = inputStream->Available(&length);
ASSERT_TRUE(NS_SUCCEEDED(rv));
// Write the data into the image.
rv = image->OnImageDataAvailable(nullptr, nullptr, inputStream, 0,
static_cast<uint32_t>(length));
ASSERT_TRUE(NS_SUCCEEDED(rv));
// Let the image know we've sent all the data.
rv = image->OnImageDataComplete(nullptr, nullptr, NS_OK, true);
ASSERT_TRUE(NS_SUCCEEDED(rv));
RefPtr<ProgressTracker> tracker = image->GetProgressTracker();
tracker->SyncNotifyProgress(FLAG_LOAD_COMPLETE);
// Lock the image so its surfaces don't disappear during the test.
image->LockImage();
// Use GetFrame() to force a sync decode of the image, specifying
// FRAME_CURRENT to ensure we get an animated decode.
RefPtr<SourceSurface> surface =
image->GetFrame(imgIContainer::FRAME_CURRENT,
imgIContainer::FLAG_SYNC_DECODE);
// Ensure that the image's metadata meets our expectations.
IntSize imageSize(0, 0);
rv = image->GetWidth(&imageSize.width);
EXPECT_TRUE(NS_SUCCEEDED(rv));
rv = image->GetHeight(&imageSize.height);
EXPECT_TRUE(NS_SUCCEEDED(rv));
EXPECT_EQ(testCase.mSize.width, imageSize.width);
EXPECT_EQ(testCase.mSize.height, imageSize.height);
Progress imageProgress = tracker->GetProgress();
EXPECT_TRUE(bool(imageProgress & FLAG_HAS_TRANSPARENCY) == false);
EXPECT_TRUE(bool(imageProgress & FLAG_IS_ANIMATED) == true);
// Ensure that we decoded both frames of the animated version of the image.
{
LookupResult result =
SurfaceCache::Lookup(ImageKey(image.get()),
RasterSurfaceKey(imageSize,
DefaultSurfaceFlags(),
PlaybackType::eAnimated));
ASSERT_EQ(MatchType::EXACT, result.Type());
EXPECT_TRUE(NS_SUCCEEDED(result.Surface().Seek(0)));
EXPECT_TRUE(bool(result.Surface()));
EXPECT_TRUE(NS_SUCCEEDED(result.Surface().Seek(1)));
EXPECT_TRUE(bool(result.Surface()));
}
// Ensure that we didn't decode the static version of the image.
{
LookupResult result =
SurfaceCache::Lookup(ImageKey(image.get()),
RasterSurfaceKey(imageSize,
DefaultSurfaceFlags(),
PlaybackType::eStatic));
ASSERT_EQ(MatchType::NOT_FOUND, result.Type());
}
// Use GetFrame() to force a sync decode of the image, this time specifying
// FRAME_FIRST to ensure that we get a single-frame decode.
RefPtr<SourceSurface> animatedSurface =
image->GetFrame(imgIContainer::FRAME_FIRST,
imgIContainer::FLAG_SYNC_DECODE);
// Ensure that we decoded the static version of the image.
{
LookupResult result =
SurfaceCache::Lookup(ImageKey(image.get()),
RasterSurfaceKey(imageSize,
DefaultSurfaceFlags(),
PlaybackType::eStatic));
ASSERT_EQ(MatchType::EXACT, result.Type());
EXPECT_TRUE(bool(result.Surface()));
}
// Ensure that both frames of the animated version are still around.
{
LookupResult result =
SurfaceCache::Lookup(ImageKey(image.get()),
RasterSurfaceKey(imageSize,
DefaultSurfaceFlags(),
PlaybackType::eAnimated));
ASSERT_EQ(MatchType::EXACT, result.Type());
EXPECT_TRUE(NS_SUCCEEDED(result.Surface().Seek(0)));
EXPECT_TRUE(bool(result.Surface()));
EXPECT_TRUE(NS_SUCCEEDED(result.Surface().Seek(1)));
EXPECT_TRUE(bool(result.Surface()));
}
}
TEST_F(ImageDecoders, AnimatedGIFWithExtraImageSubBlocks)
{
ImageTestCase testCase = ExtraImageSubBlocksAnimatedGIFTestCase();