mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 13:21:05 +00:00
Bug 1246851 (Part 4) - Add a test suite for SurfacePipes and SurfaceFilters. r=njn
This commit is contained in:
parent
d58e9fda35
commit
618f960cdd
@ -32,9 +32,15 @@ UNIFIED_SOURCES += [
|
||||
'nsPNGDecoder.cpp',
|
||||
]
|
||||
|
||||
# Decoders need RasterImage.h
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
# Access to Skia headers for Downscaler.
|
||||
'/gfx/2d',
|
||||
# Decoders need ImageLib headers.
|
||||
'/image',
|
||||
]
|
||||
|
||||
LOCAL_INCLUDES += CONFIG['SKIA_INCLUDES']
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
@ -6,7 +6,6 @@
|
||||
#include "Common.h"
|
||||
|
||||
#include <cstdlib>
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "nsDirectoryServiceDefs.h"
|
||||
#include "nsIDirectoryService.h"
|
||||
@ -19,13 +18,14 @@
|
||||
#include "nsString.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace image {
|
||||
|
||||
using namespace gfx;
|
||||
|
||||
using std::abs;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Helpers
|
||||
// General Helpers
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// These macros work like gtest's ASSERT_* macros, except that they can be used
|
||||
@ -85,13 +85,41 @@ LoadFile(const char* aRelativePath)
|
||||
}
|
||||
|
||||
bool
|
||||
IsSolidColor(SourceSurface* aSurface, BGRAColor aColor, bool aFuzzy)
|
||||
IsSolidColor(SourceSurface* aSurface,
|
||||
BGRAColor aColor,
|
||||
uint8_t aFuzz /* = 0 */)
|
||||
{
|
||||
IntSize size = aSurface->GetSize();
|
||||
return RectIsSolidColor(aSurface, IntRect(0, 0, size.width, size.height),
|
||||
aColor, aFuzz);
|
||||
}
|
||||
|
||||
bool
|
||||
RowsAreSolidColor(SourceSurface* aSurface,
|
||||
int32_t aStartRow,
|
||||
int32_t aRowCount,
|
||||
BGRAColor aColor,
|
||||
uint8_t aFuzz /* = 0 */)
|
||||
{
|
||||
IntSize size = aSurface->GetSize();
|
||||
return RectIsSolidColor(aSurface, IntRect(0, aStartRow, size.width, aRowCount),
|
||||
aColor, aFuzz);
|
||||
}
|
||||
|
||||
bool
|
||||
RectIsSolidColor(SourceSurface* aSurface,
|
||||
const IntRect& aRect,
|
||||
BGRAColor aColor,
|
||||
uint8_t aFuzz /* = 0 */)
|
||||
{
|
||||
IntSize surfaceSize = aSurface->GetSize();
|
||||
IntRect rect =
|
||||
aRect.Intersect(IntRect(0, 0, surfaceSize.width, surfaceSize.height));
|
||||
|
||||
RefPtr<DataSourceSurface> dataSurface = aSurface->GetDataSurface();
|
||||
ASSERT_TRUE_OR_RETURN(dataSurface != nullptr, false);
|
||||
|
||||
ASSERT_EQ_OR_RETURN(dataSurface->Stride(), aSurface->GetSize().width * 4,
|
||||
false);
|
||||
ASSERT_EQ_OR_RETURN(dataSurface->Stride(), surfaceSize.width * 4, false);
|
||||
|
||||
DataSourceSurface::ScopedMap mapping(dataSurface,
|
||||
DataSourceSurface::MapType::READ);
|
||||
@ -100,18 +128,21 @@ IsSolidColor(SourceSurface* aSurface, BGRAColor aColor, bool aFuzzy)
|
||||
uint8_t* data = dataSurface->GetData();
|
||||
ASSERT_TRUE_OR_RETURN(data != nullptr, false);
|
||||
|
||||
int32_t length = dataSurface->Stride() * aSurface->GetSize().height;
|
||||
for (int32_t i = 0 ; i < length ; i += 4) {
|
||||
if (aFuzzy) {
|
||||
ASSERT_LE_OR_RETURN(abs(aColor.mBlue - data[i + 0]), 1, false);
|
||||
ASSERT_LE_OR_RETURN(abs(aColor.mGreen - data[i + 1]), 1, false);
|
||||
ASSERT_LE_OR_RETURN(abs(aColor.mRed - data[i + 2]), 1, false);
|
||||
ASSERT_LE_OR_RETURN(abs(aColor.mAlpha - data[i + 3]), 1, false);
|
||||
} else {
|
||||
ASSERT_EQ_OR_RETURN(aColor.mBlue, data[i + 0], false);
|
||||
ASSERT_EQ_OR_RETURN(aColor.mGreen, data[i + 1], false);
|
||||
ASSERT_EQ_OR_RETURN(aColor.mRed, data[i + 2], false);
|
||||
ASSERT_EQ_OR_RETURN(aColor.mAlpha, data[i + 3], false);
|
||||
int32_t rowLength = dataSurface->Stride();
|
||||
for (int32_t row = rect.y; row < rect.YMost(); ++row) {
|
||||
for (int32_t col = rect.x; col < rect.XMost(); ++col) {
|
||||
int32_t i = row * rowLength + col * 4;
|
||||
if (aFuzz != 0) {
|
||||
ASSERT_LE_OR_RETURN(abs(aColor.mBlue - data[i + 0]), aFuzz, false);
|
||||
ASSERT_LE_OR_RETURN(abs(aColor.mGreen - data[i + 1]), aFuzz, false);
|
||||
ASSERT_LE_OR_RETURN(abs(aColor.mRed - data[i + 2]), aFuzz, false);
|
||||
ASSERT_LE_OR_RETURN(abs(aColor.mAlpha - data[i + 3]), aFuzz, false);
|
||||
} else {
|
||||
ASSERT_EQ_OR_RETURN(aColor.mBlue, data[i + 0], false);
|
||||
ASSERT_EQ_OR_RETURN(aColor.mGreen, data[i + 1], false);
|
||||
ASSERT_EQ_OR_RETURN(aColor.mRed, data[i + 2], false);
|
||||
ASSERT_EQ_OR_RETURN(aColor.mAlpha, data[i + 3], false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -119,6 +150,261 @@ IsSolidColor(SourceSurface* aSurface, BGRAColor aColor, bool aFuzzy)
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// SurfacePipe Helpers
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
already_AddRefed<Decoder>
|
||||
CreateTrivialDecoder()
|
||||
{
|
||||
gfxPrefs::GetSingleton();
|
||||
DecoderType decoderType = DecoderFactory::GetDecoderType("image/gif");
|
||||
RefPtr<SourceBuffer> sourceBuffer = new SourceBuffer();
|
||||
RefPtr<Decoder> decoder =
|
||||
DecoderFactory::CreateAnonymousDecoder(decoderType, sourceBuffer,
|
||||
DefaultSurfaceFlags());
|
||||
return decoder.forget();
|
||||
}
|
||||
|
||||
void AssertCorrectPipelineFinalState(SurfaceFilter* aFilter,
|
||||
const gfx::IntRect& aInputSpaceRect,
|
||||
const gfx::IntRect& aOutputSpaceRect)
|
||||
{
|
||||
EXPECT_TRUE(aFilter->IsSurfaceFinished());
|
||||
Maybe<SurfaceInvalidRect> invalidRect = aFilter->TakeInvalidRect();
|
||||
EXPECT_TRUE(invalidRect.isSome());
|
||||
EXPECT_EQ(aInputSpaceRect, invalidRect->mInputSpaceRect);
|
||||
EXPECT_EQ(aOutputSpaceRect, invalidRect->mOutputSpaceRect);
|
||||
}
|
||||
|
||||
void
|
||||
CheckGeneratedImage(Decoder* aDecoder,
|
||||
const IntRect& aRect,
|
||||
uint8_t aFuzz /* = 0 */)
|
||||
{
|
||||
RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef();
|
||||
RefPtr<SourceSurface> surface = currentFrame->GetSurface();
|
||||
const IntSize surfaceSize = surface->GetSize();
|
||||
|
||||
// This diagram shows how the surface is divided into regions that the code
|
||||
// below tests for the correct content. The output rect is the bounds of the
|
||||
// region labeled 'C'.
|
||||
//
|
||||
// +---------------------------+
|
||||
// | A |
|
||||
// +---------+--------+--------+
|
||||
// | B | C | D |
|
||||
// +---------+--------+--------+
|
||||
// | E |
|
||||
// +---------------------------+
|
||||
|
||||
// Check that the output rect itself is green. (Region 'C'.)
|
||||
EXPECT_TRUE(RectIsSolidColor(surface, aRect, BGRAColor::Green(), aFuzz));
|
||||
|
||||
// Check that the area above the output rect is transparent. (Region 'A'.)
|
||||
EXPECT_TRUE(RectIsSolidColor(surface,
|
||||
IntRect(0, 0, surfaceSize.width, aRect.y),
|
||||
BGRAColor::Transparent(), aFuzz));
|
||||
|
||||
// Check that the area to the left of the output rect is transparent. (Region 'B'.)
|
||||
EXPECT_TRUE(RectIsSolidColor(surface,
|
||||
IntRect(0, aRect.y, aRect.x, aRect.YMost()),
|
||||
BGRAColor::Transparent(), aFuzz));
|
||||
|
||||
// Check that the area to the right of the output rect is transparent. (Region 'D'.)
|
||||
const int32_t widthOnRight = surfaceSize.width - aRect.XMost();
|
||||
EXPECT_TRUE(RectIsSolidColor(surface,
|
||||
IntRect(aRect.XMost(), aRect.y, widthOnRight, aRect.YMost()),
|
||||
BGRAColor::Transparent(), aFuzz));
|
||||
|
||||
// Check that the area below the output rect is transparent. (Region 'E'.)
|
||||
const int32_t heightBelow = surfaceSize.height - aRect.YMost();
|
||||
EXPECT_TRUE(RectIsSolidColor(surface,
|
||||
IntRect(0, aRect.YMost(), surfaceSize.width, heightBelow),
|
||||
BGRAColor::Transparent(), aFuzz));
|
||||
}
|
||||
|
||||
template <typename Func> void
|
||||
CheckSurfacePipeWrite(Decoder* aDecoder,
|
||||
SurfaceFilter* aFilter,
|
||||
Maybe<IntRect> aOutputRect,
|
||||
Maybe<IntRect> aInputRect,
|
||||
Maybe<IntRect> aInputWriteRect,
|
||||
Maybe<IntRect> aOutputWriteRect,
|
||||
uint8_t aFuzz,
|
||||
Func aFunc)
|
||||
{
|
||||
IntRect outputRect = aOutputRect.valueOr(IntRect(0, 0, 100, 100));
|
||||
IntRect inputRect = aInputRect.valueOr(IntRect(0, 0, 100, 100));
|
||||
IntRect inputWriteRect = aInputWriteRect.valueOr(inputRect);
|
||||
IntRect outputWriteRect = aOutputWriteRect.valueOr(outputRect);
|
||||
|
||||
// Fill the image.
|
||||
int32_t count = 0;
|
||||
auto result = aFunc(count);
|
||||
EXPECT_EQ(WriteState::FINISHED, result);
|
||||
EXPECT_EQ(inputWriteRect.width * inputWriteRect.height, count);
|
||||
|
||||
AssertCorrectPipelineFinalState(aFilter, inputRect, outputRect);
|
||||
|
||||
// Attempt to write more data and make sure nothing changes.
|
||||
const int32_t oldCount = count;
|
||||
result = aFunc(count);
|
||||
EXPECT_EQ(oldCount, count);
|
||||
EXPECT_EQ(WriteState::FINISHED, result);
|
||||
EXPECT_TRUE(aFilter->IsSurfaceFinished());
|
||||
Maybe<SurfaceInvalidRect> invalidRect = aFilter->TakeInvalidRect();
|
||||
EXPECT_TRUE(invalidRect.isNothing());
|
||||
|
||||
// Attempt to advance to the next row and make sure nothing changes.
|
||||
aFilter->AdvanceRow();
|
||||
EXPECT_TRUE(aFilter->IsSurfaceFinished());
|
||||
invalidRect = aFilter->TakeInvalidRect();
|
||||
EXPECT_TRUE(invalidRect.isNothing());
|
||||
|
||||
// Check that the generated image is correct.
|
||||
CheckGeneratedImage(aDecoder, outputWriteRect, aFuzz);
|
||||
}
|
||||
|
||||
void
|
||||
CheckWritePixels(Decoder* aDecoder,
|
||||
SurfaceFilter* aFilter,
|
||||
Maybe<IntRect> aOutputRect /* = Nothing() */,
|
||||
Maybe<IntRect> aInputRect /* = Nothing() */,
|
||||
Maybe<IntRect> aInputWriteRect /* = Nothing() */,
|
||||
Maybe<IntRect> aOutputWriteRect /* = Nothing() */,
|
||||
uint8_t aFuzz /* = 0 */)
|
||||
{
|
||||
CheckSurfacePipeWrite(aDecoder, aFilter,
|
||||
aOutputRect, aInputRect,
|
||||
aInputWriteRect, aOutputWriteRect,
|
||||
aFuzz,
|
||||
[&](int32_t& aCount) {
|
||||
return aFilter->WritePixels<uint32_t>([&] {
|
||||
++aCount;
|
||||
return AsVariant(BGRAColor::Green().AsPixel());
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
CheckWriteRows(Decoder* aDecoder,
|
||||
SurfaceFilter* aFilter,
|
||||
Maybe<IntRect> aOutputRect /* = Nothing() */,
|
||||
Maybe<IntRect> aInputRect /* = Nothing() */,
|
||||
Maybe<IntRect> aInputWriteRect /* = Nothing() */,
|
||||
Maybe<IntRect> aOutputWriteRect /* = Nothing() */,
|
||||
uint8_t aFuzz /* = 0 */)
|
||||
{
|
||||
CheckSurfacePipeWrite(aDecoder, aFilter,
|
||||
aOutputRect, aInputRect,
|
||||
aInputWriteRect, aOutputWriteRect,
|
||||
aFuzz,
|
||||
[&](int32_t& aCount) {
|
||||
return aFilter->WriteRows<uint32_t>([&](uint32_t* aRow, uint32_t aLength) {
|
||||
for (; aLength > 0; --aLength, ++aRow, ++aCount) {
|
||||
*aRow = BGRAColor::Green().AsPixel();
|
||||
}
|
||||
return Nothing();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
template <typename Func> void
|
||||
CheckPalettedSurfacePipeWrite(Decoder* aDecoder,
|
||||
SurfaceFilter* aFilter,
|
||||
Maybe<IntRect> aOutputRect,
|
||||
Maybe<IntRect> aInputRect,
|
||||
Maybe<IntRect> aInputWriteRect,
|
||||
Maybe<IntRect> aOutputWriteRect,
|
||||
uint8_t aFuzz,
|
||||
Func aFunc)
|
||||
{
|
||||
IntRect outputRect = aOutputRect.valueOr(IntRect(0, 0, 100, 100));
|
||||
IntRect inputRect = aInputRect.valueOr(IntRect(0, 0, 100, 100));
|
||||
IntRect inputWriteRect = aInputWriteRect.valueOr(inputRect);
|
||||
IntRect outputWriteRect = aOutputWriteRect.valueOr(outputRect);
|
||||
|
||||
// Fill the image.
|
||||
int32_t count = 0;
|
||||
auto result = aFunc(count);
|
||||
EXPECT_EQ(WriteState::FINISHED, result);
|
||||
EXPECT_EQ(inputWriteRect.width * inputWriteRect.height, count);
|
||||
|
||||
AssertCorrectPipelineFinalState(aFilter, inputRect, outputRect);
|
||||
|
||||
// Attempt to write more data and make sure nothing changes.
|
||||
const int32_t oldCount = count;
|
||||
result = aFunc(count);
|
||||
EXPECT_EQ(oldCount, count);
|
||||
EXPECT_EQ(WriteState::FINISHED, result);
|
||||
EXPECT_TRUE(aFilter->IsSurfaceFinished());
|
||||
Maybe<SurfaceInvalidRect> invalidRect = aFilter->TakeInvalidRect();
|
||||
EXPECT_TRUE(invalidRect.isNothing());
|
||||
|
||||
// Attempt to advance to the next row and make sure nothing changes.
|
||||
aFilter->AdvanceRow();
|
||||
EXPECT_TRUE(aFilter->IsSurfaceFinished());
|
||||
invalidRect = aFilter->TakeInvalidRect();
|
||||
EXPECT_TRUE(invalidRect.isNothing());
|
||||
|
||||
// Check that the generated image is correct.
|
||||
RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef();
|
||||
uint8_t* imageData;
|
||||
uint32_t imageLength;
|
||||
currentFrame->GetImageData(&imageData, &imageLength);
|
||||
ASSERT_TRUE(imageData != nullptr);
|
||||
ASSERT_EQ(outputWriteRect.width * outputWriteRect.height, int32_t(imageLength));
|
||||
for (uint32_t i = 0; i < imageLength; ++i) {
|
||||
ASSERT_EQ(uint8_t(255), imageData[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CheckPalettedWritePixels(Decoder* aDecoder,
|
||||
SurfaceFilter* aFilter,
|
||||
Maybe<IntRect> aOutputRect /* = Nothing() */,
|
||||
Maybe<IntRect> aInputRect /* = Nothing() */,
|
||||
Maybe<IntRect> aInputWriteRect /* = Nothing() */,
|
||||
Maybe<IntRect> aOutputWriteRect /* = Nothing() */,
|
||||
uint8_t aFuzz /* = 0 */)
|
||||
{
|
||||
CheckPalettedSurfacePipeWrite(aDecoder, aFilter,
|
||||
aOutputRect, aInputRect,
|
||||
aInputWriteRect, aOutputWriteRect,
|
||||
aFuzz,
|
||||
[&](int32_t& aCount) {
|
||||
return aFilter->WritePixels<uint8_t>([&] {
|
||||
++aCount;
|
||||
return AsVariant(uint8_t(255));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
CheckPalettedWriteRows(Decoder* aDecoder,
|
||||
SurfaceFilter* aFilter,
|
||||
Maybe<IntRect> aOutputRect /* = Nothing() */,
|
||||
Maybe<IntRect> aInputRect /* = Nothing() */,
|
||||
Maybe<IntRect> aInputWriteRect /* = Nothing() */,
|
||||
Maybe<IntRect> aOutputWriteRect /* = Nothing() */,
|
||||
uint8_t aFuzz /* = 0*/)
|
||||
{
|
||||
CheckPalettedSurfacePipeWrite(aDecoder, aFilter,
|
||||
aOutputRect, aInputRect,
|
||||
aInputWriteRect, aOutputWriteRect,
|
||||
aFuzz,
|
||||
[&](int32_t& aCount) {
|
||||
return aFilter->WriteRows<uint8_t>([&](uint8_t* aRow, uint32_t aLength) {
|
||||
for (; aLength > 0; --aLength, ++aRow, ++aCount) {
|
||||
*aRow = uint8_t(255);
|
||||
}
|
||||
return Nothing();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Test Data
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -224,4 +510,5 @@ ImageTestCase NoFrameDelayGIFTestCase()
|
||||
return ImageTestCase("no-frame-delay.gif", "image/gif", IntSize(100, 100));
|
||||
}
|
||||
|
||||
} // namespace image
|
||||
} // namespace mozilla
|
||||
|
@ -6,12 +6,21 @@
|
||||
#ifndef mozilla_image_test_gtest_Common_h
|
||||
#define mozilla_image_test_gtest_Common_h
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "Decoder.h"
|
||||
#include "gfxColor.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "SurfacePipe.h"
|
||||
#include "SurfacePipeFactory.h"
|
||||
|
||||
class nsIInputStream;
|
||||
|
||||
namespace mozilla {
|
||||
namespace image {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Types
|
||||
@ -54,6 +63,10 @@ struct BGRAColor
|
||||
{ }
|
||||
|
||||
static BGRAColor Green() { return BGRAColor(0x00, 0xFF, 0x00, 0xFF); }
|
||||
static BGRAColor Red() { return BGRAColor(0x00, 0x00, 0xFF, 0xFF); }
|
||||
static BGRAColor Transparent() { return BGRAColor(0x00, 0x00, 0x00, 0x00); }
|
||||
|
||||
uint32_t AsPixel() const { return gfxPackedPixel(mAlpha, mRed, mGreen, mBlue); }
|
||||
|
||||
uint8_t mBlue;
|
||||
uint8_t mGreen;
|
||||
@ -63,7 +76,7 @@ struct BGRAColor
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Helpers
|
||||
// General Helpers
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// Loads a file from the current directory. @return an nsIInputStream for it.
|
||||
@ -72,12 +85,206 @@ already_AddRefed<nsIInputStream> LoadFile(const char* aRelativePath);
|
||||
/**
|
||||
* @returns true if every pixel of @aSurface is @aColor.
|
||||
*
|
||||
* If @aFuzzy is true, a tolerance of 1 is allowed in each color component. This
|
||||
* may be necessary for tests that involve JPEG images.
|
||||
* If @aFuzz is nonzero, a tolerance of @aFuzz is allowed in each color
|
||||
* component. This may be necessary for tests that involve JPEG images or
|
||||
* downscaling.
|
||||
*/
|
||||
bool IsSolidColor(gfx::SourceSurface* aSurface,
|
||||
BGRAColor aColor,
|
||||
bool aFuzzy = false);
|
||||
uint8_t aFuzz = 0);
|
||||
|
||||
/**
|
||||
* @returns true if every pixel in the range of rows specified by @aStartRow and
|
||||
* @aRowCount of @aSurface is @aColor.
|
||||
*
|
||||
* If @aFuzz is nonzero, a tolerance of @aFuzz is allowed in each color
|
||||
* component. This may be necessary for tests that involve JPEG images or
|
||||
* downscaling.
|
||||
*/
|
||||
bool RowsAreSolidColor(gfx::SourceSurface* aSurface,
|
||||
int32_t aStartRow,
|
||||
int32_t aRowCount,
|
||||
BGRAColor aColor,
|
||||
uint8_t aFuzz = 0);
|
||||
|
||||
/**
|
||||
* @returns true if every pixel in the rect specified by @aRect is @aColor.
|
||||
*
|
||||
* If @aFuzz is nonzero, a tolerance of @aFuzz is allowed in each color
|
||||
* component. This may be necessary for tests that involve JPEG images or
|
||||
* downscaling.
|
||||
*/
|
||||
bool RectIsSolidColor(gfx::SourceSurface* aSurface,
|
||||
const gfx::IntRect& aRect,
|
||||
BGRAColor aColor,
|
||||
uint8_t aFuzz = 0);
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// SurfacePipe Helpers
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Creates a decoder with no data associated with, suitable for testing code
|
||||
* that requires a decoder to initialize or to allocate surfaces but doesn't
|
||||
* actually need the decoder to do any decoding.
|
||||
*
|
||||
* XXX(seth): We only need this because SurfaceSink and PalettedSurfaceSink
|
||||
* defer to the decoder for surface allocation. Once all decoders use
|
||||
* SurfacePipe we won't need to do that anymore and we can remove this function.
|
||||
*/
|
||||
already_AddRefed<Decoder> CreateTrivialDecoder();
|
||||
|
||||
/**
|
||||
* Creates a pipeline of SurfaceFilters from a list of Config structs and passes
|
||||
* it to the provided lambda @aFunc. Assertions that the pipeline is constructly
|
||||
* correctly and cleanup of any allocated surfaces is handled automatically.
|
||||
*
|
||||
* @param aDecoder The decoder to use for allocating surfaces.
|
||||
* @param aFunc The lambda function to pass the filter pipeline to.
|
||||
* @param aConfigs The configuration for the pipeline.
|
||||
*/
|
||||
template <typename Func, typename... Configs>
|
||||
void WithFilterPipeline(Decoder* aDecoder, Func aFunc, Configs... aConfigs)
|
||||
{
|
||||
auto pipe = MakeUnique<typename detail::FilterPipeline<Configs...>::Type>();
|
||||
nsresult rv = pipe->Configure(aConfigs...);
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
|
||||
aFunc(aDecoder, pipe.get());
|
||||
|
||||
RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef();
|
||||
if (currentFrame) {
|
||||
currentFrame->Finish();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a pipeline of SurfaceFilters from a list of Config structs and
|
||||
* asserts that configuring it fails. Cleanup of any allocated surfaces is
|
||||
* handled automatically.
|
||||
*
|
||||
* @param aDecoder The decoder to use for allocating surfaces.
|
||||
* @param aConfigs The configuration for the pipeline.
|
||||
*/
|
||||
template <typename... Configs>
|
||||
void AssertConfiguringPipelineFails(Decoder* aDecoder, Configs... aConfigs)
|
||||
{
|
||||
auto pipe = MakeUnique<typename detail::FilterPipeline<Configs...>::Type>();
|
||||
nsresult rv = pipe->Configure(aConfigs...);
|
||||
|
||||
// Callers expect configuring the pipeline to fail.
|
||||
ASSERT_TRUE(NS_FAILED(rv));
|
||||
|
||||
RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef();
|
||||
if (currentFrame) {
|
||||
currentFrame->Finish();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the provided filter pipeline is in the correct final state,
|
||||
* which is to say, the entire surface has been written to (IsSurfaceFinished()
|
||||
* returns true) and the invalid rects are as expected.
|
||||
*
|
||||
* @param aFilter The filter pipeline to check.
|
||||
* @param aInputSpaceRect The expect invalid rect, in input space.
|
||||
* @param aoutputSpaceRect The expect invalid rect, in output space.
|
||||
*/
|
||||
void AssertCorrectPipelineFinalState(SurfaceFilter* aFilter,
|
||||
const gfx::IntRect& aInputSpaceRect,
|
||||
const gfx::IntRect& aOutputSpaceRect);
|
||||
|
||||
/**
|
||||
* Checks a generated image for correctness. Reports any unexpected deviation
|
||||
* from the expected image as GTest failures.
|
||||
*
|
||||
* @param aDecoder The decoder which contains the image. The decoder's current
|
||||
* frame will be checked.
|
||||
* @param aRect The region in the space of the output surface that the filter
|
||||
* pipeline will actually write to. It's expected that pixels in
|
||||
* this region are green, while pixels outside this region are
|
||||
* transparent. Defaults to the entire output rect.
|
||||
* @param aFuzz The amount of fuzz to use in pixel comparisons.
|
||||
*/
|
||||
void CheckGeneratedImage(Decoder* aDecoder,
|
||||
const gfx::IntRect& aRect,
|
||||
uint8_t aFuzz = 0);
|
||||
|
||||
/**
|
||||
* Tests the result of calling WritePixels() using the provided SurfaceFilter
|
||||
* pipeline. The pipeline must be a normal (i.e., non-paletted) pipeline.
|
||||
*
|
||||
* The arguments are specified in the an order intended to minimize the number
|
||||
* of arguments that most test cases need to pass.
|
||||
*
|
||||
* @param aDecoder The decoder whose current frame will be written to.
|
||||
* @param aFilter The SurfaceFilter pipeline to use.
|
||||
* @param aOutputRect The region in the space of the output surface that will be
|
||||
* invalidated by the filter pipeline. Defaults to
|
||||
* (0, 0, 100, 100).
|
||||
* @param aInputRect The region in the space of the input image that will be
|
||||
* invalidated by the filter pipeline. Defaults to
|
||||
* (0, 0, 100, 100).
|
||||
* @param aInputWriteRect The region in the space of the input image that the
|
||||
* filter pipeline will allow writes to. Note the
|
||||
* difference from @aInputRect: @aInputRect is the actual
|
||||
* region invalidated, while @aInputWriteRect is the
|
||||
* region that is written to. These can differ in cases
|
||||
* where the input is not clipped to the size of the image.
|
||||
* Defaults to the entire input rect.
|
||||
* @param aOutputWriteRect The region in the space of the output surface that
|
||||
* the filter pipeline will actually write to. It's
|
||||
* expected that pixels in this region are green, while
|
||||
* pixels outside this region are transparent. Defaults
|
||||
* to the entire output rect.
|
||||
*/
|
||||
void CheckWritePixels(Decoder* aDecoder,
|
||||
SurfaceFilter* aFilter,
|
||||
Maybe<gfx::IntRect> aOutputRect = Nothing(),
|
||||
Maybe<gfx::IntRect> aInputRect = Nothing(),
|
||||
Maybe<gfx::IntRect> aInputWriteRect = Nothing(),
|
||||
Maybe<gfx::IntRect> aOutputWriteRect = Nothing(),
|
||||
uint8_t aFuzz = 0);
|
||||
|
||||
/**
|
||||
* Tests the result of calling WriteRows() using the provided SurfaceFilter
|
||||
* pipeline. The pipeline must be a normal (i.e., non-paletted) pipeline.
|
||||
* @see CheckWritePixels() for documentation of the arguments.
|
||||
*/
|
||||
void CheckWriteRows(Decoder* aDecoder,
|
||||
SurfaceFilter* aFilter,
|
||||
Maybe<gfx::IntRect> aOutputRect = Nothing(),
|
||||
Maybe<gfx::IntRect> aInputRect = Nothing(),
|
||||
Maybe<gfx::IntRect> aInputWriteRect = Nothing(),
|
||||
Maybe<gfx::IntRect> aOutputWriteRect = Nothing(),
|
||||
uint8_t aFuzz = 0);
|
||||
|
||||
/**
|
||||
* Tests the result of calling WritePixels() using the provided SurfaceFilter
|
||||
* pipeline. The pipeline must be a paletted pipeline.
|
||||
* @see CheckWritePixels() for documentation of the arguments.
|
||||
*/
|
||||
void CheckPalettedWritePixels(Decoder* aDecoder,
|
||||
SurfaceFilter* aFilter,
|
||||
Maybe<gfx::IntRect> aOutputRect = Nothing(),
|
||||
Maybe<gfx::IntRect> aInputRect = Nothing(),
|
||||
Maybe<gfx::IntRect> aInputWriteRect = Nothing(),
|
||||
Maybe<gfx::IntRect> aOutputWriteRect = Nothing(),
|
||||
uint8_t aFuzz = 0);
|
||||
|
||||
/**
|
||||
* Tests the result of calling WriteRows() using the provided SurfaceFilter
|
||||
* pipeline. The pipeline must be a paletted pipeline.
|
||||
* @see CheckWritePixels() for documentation of the arguments.
|
||||
*/
|
||||
void CheckPalettedWriteRows(Decoder* aDecoder,
|
||||
SurfaceFilter* aFilter,
|
||||
Maybe<gfx::IntRect> aOutputRect = Nothing(),
|
||||
Maybe<gfx::IntRect> aInputRect = Nothing(),
|
||||
Maybe<gfx::IntRect> aInputWriteRect = Nothing(),
|
||||
Maybe<gfx::IntRect> aOutputWriteRect = Nothing(),
|
||||
uint8_t aFuzz = 0);
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -105,6 +312,7 @@ ImageTestCase TransparentBMPWhenBMPAlphaEnabledTestCase();
|
||||
ImageTestCase RLE4BMPTestCase();
|
||||
ImageTestCase RLE8BMPTestCase();
|
||||
|
||||
} // namespace image
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_image_test_gtest_Common_h
|
||||
|
@ -63,7 +63,7 @@ public:
|
||||
EXPECT_EQ(mTestCase.mSize, mSurface->GetSize());
|
||||
|
||||
EXPECT_TRUE(IsSolidColor(mSurface, BGRAColor::Green(),
|
||||
mTestCase.mFlags & TEST_CASE_IS_FUZZY));
|
||||
mTestCase.mFlags & TEST_CASE_IS_FUZZY ? 1 : 0));
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -79,7 +79,7 @@ CheckDecoderResults(const ImageTestCase& aTestCase, Decoder* aDecoder)
|
||||
surface->GetFormat() == SurfaceFormat::B8G8R8A8);
|
||||
EXPECT_EQ(aTestCase.mSize, surface->GetSize());
|
||||
EXPECT_TRUE(IsSolidColor(surface, BGRAColor::Green(),
|
||||
aTestCase.mFlags & TEST_CASE_IS_FUZZY));
|
||||
aTestCase.mFlags & TEST_CASE_IS_FUZZY ? 1 : 0));
|
||||
}
|
||||
|
||||
static void
|
||||
|
636
image/test/gtest/TestDeinterlacingFilter.cpp
Normal file
636
image/test/gtest/TestDeinterlacingFilter.cpp
Normal file
@ -0,0 +1,636 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "Common.h"
|
||||
#include "Decoder.h"
|
||||
#include "DecoderFactory.h"
|
||||
#include "SourceBuffer.h"
|
||||
#include "SurfaceFilters.h"
|
||||
#include "SurfacePipe.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::gfx;
|
||||
using namespace mozilla::image;
|
||||
|
||||
template <typename Func> void
|
||||
WithDeinterlacingFilter(const IntSize& aSize,
|
||||
bool aProgressiveDisplay,
|
||||
Func aFunc)
|
||||
{
|
||||
RefPtr<Decoder> decoder = CreateTrivialDecoder();
|
||||
ASSERT_TRUE(bool(decoder));
|
||||
|
||||
WithFilterPipeline(decoder, Forward<Func>(aFunc),
|
||||
DeinterlacingConfig<uint32_t> { aProgressiveDisplay },
|
||||
SurfaceConfig { decoder, 0, aSize,
|
||||
SurfaceFormat::B8G8R8A8, false });
|
||||
}
|
||||
|
||||
template <typename Func> void
|
||||
WithPalettedDeinterlacingFilter(const IntSize& aSize,
|
||||
Func aFunc)
|
||||
{
|
||||
RefPtr<Decoder> decoder = CreateTrivialDecoder();
|
||||
ASSERT_TRUE(decoder != nullptr);
|
||||
|
||||
WithFilterPipeline(decoder, Forward<Func>(aFunc),
|
||||
DeinterlacingConfig<uint8_t> { /* mProgressiveDisplay = */ true },
|
||||
PalettedSurfaceConfig { decoder, 0, aSize,
|
||||
IntRect(0, 0, 100, 100),
|
||||
SurfaceFormat::B8G8R8A8, 8,
|
||||
false });
|
||||
}
|
||||
|
||||
void
|
||||
AssertConfiguringDeinterlacingFilterFails(const IntSize& aSize)
|
||||
{
|
||||
RefPtr<Decoder> decoder = CreateTrivialDecoder();
|
||||
ASSERT_TRUE(decoder != nullptr);
|
||||
|
||||
AssertConfiguringPipelineFails(decoder,
|
||||
DeinterlacingConfig<uint32_t> { /* mProgressiveDisplay = */ true},
|
||||
SurfaceConfig { decoder, 0, aSize,
|
||||
SurfaceFormat::B8G8R8A8, false });
|
||||
}
|
||||
|
||||
TEST(ImageDeinterlacingFilter, WritePixels100_100)
|
||||
{
|
||||
WithDeinterlacingFilter(IntSize(100, 100), /* aProgressiveDisplay = */ true,
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckWritePixels(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 100, 100)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageDeinterlacingFilter, WriteRows100_100)
|
||||
{
|
||||
WithDeinterlacingFilter(IntSize(100, 100), /* aProgressiveDisplay = */ true,
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckWriteRows(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 100, 100)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageDeinterlacingFilter, WritePixels99_99)
|
||||
{
|
||||
WithDeinterlacingFilter(IntSize(99, 99), /* aProgressiveDisplay = */ true,
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckWritePixels(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 99, 99)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 99, 99)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageDeinterlacingFilter, WriteRows99_99)
|
||||
{
|
||||
WithDeinterlacingFilter(IntSize(99, 99), /* aProgressiveDisplay = */ true,
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckWriteRows(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 99, 99)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 99, 99)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageDeinterlacingFilter, WritePixels8_8)
|
||||
{
|
||||
WithDeinterlacingFilter(IntSize(8, 8), /* aProgressiveDisplay = */ true,
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckWritePixels(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 8, 8)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 8, 8)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageDeinterlacingFilter, WriteRows8_8)
|
||||
{
|
||||
WithDeinterlacingFilter(IntSize(8, 8), /* aProgressiveDisplay = */ true,
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckWriteRows(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 8, 8)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 8, 8)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageDeinterlacingFilter, WritePixels7_7)
|
||||
{
|
||||
WithDeinterlacingFilter(IntSize(7, 7), /* aProgressiveDisplay = */ true,
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckWritePixels(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 7, 7)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 7, 7)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageDeinterlacingFilter, WriteRows7_7)
|
||||
{
|
||||
WithDeinterlacingFilter(IntSize(7, 7), /* aProgressiveDisplay = */ true,
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckWriteRows(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 7, 7)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 7, 7)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageDeinterlacingFilter, WritePixels3_3)
|
||||
{
|
||||
WithDeinterlacingFilter(IntSize(3, 3), /* aProgressiveDisplay = */ true,
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckWritePixels(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 3, 3)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 3, 3)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageDeinterlacingFilter, WriteRows3_3)
|
||||
{
|
||||
WithDeinterlacingFilter(IntSize(3, 3), /* aProgressiveDisplay = */ true,
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckWriteRows(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 3, 3)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 3, 3)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageDeinterlacingFilter, WritePixels1_1)
|
||||
{
|
||||
WithDeinterlacingFilter(IntSize(1, 1), /* aProgressiveDisplay = */ true,
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckWritePixels(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 1, 1)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 1, 1)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageDeinterlacingFilter, WriteRows1_1)
|
||||
{
|
||||
WithDeinterlacingFilter(IntSize(1, 1), /* aProgressiveDisplay = */ true,
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckWriteRows(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 1, 1)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 1, 1)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageDeinterlacingFilter, PalettedWritePixels)
|
||||
{
|
||||
WithPalettedDeinterlacingFilter(IntSize(100, 100),
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckPalettedWritePixels(aDecoder, aFilter);
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageDeinterlacingFilter, PalettedWriteRows)
|
||||
{
|
||||
WithPalettedDeinterlacingFilter(IntSize(100, 100),
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckPalettedWriteRows(aDecoder, aFilter);
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageDeinterlacingFilter, WritePixelsOutput20_20)
|
||||
{
|
||||
WithDeinterlacingFilter(IntSize(20, 20), /* aProgressiveDisplay = */ true,
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
// Fill the image. The output should be green for even rows and red for odd
|
||||
// rows but we need to write the rows in the order that the deinterlacer
|
||||
// expects them.
|
||||
uint32_t count = 0;
|
||||
auto result = aFilter->WritePixels<uint32_t>([&]() {
|
||||
uint32_t row = count / 20; // Integer division.
|
||||
++count;
|
||||
|
||||
switch (row) {
|
||||
// First pass. Output rows are positioned at 8n + 0.
|
||||
case 0: // Output row 0.
|
||||
case 1: // Output row 8.
|
||||
case 2: // Output row 16.
|
||||
return AsVariant(BGRAColor::Green().AsPixel());
|
||||
|
||||
// Second pass. Rows are positioned at 8n + 4.
|
||||
case 3: // Output row 4.
|
||||
case 4: // Output row 12.
|
||||
return AsVariant(BGRAColor::Green().AsPixel());
|
||||
|
||||
// Third pass. Rows are positioned at 4n + 2.
|
||||
case 5: // Output row 2.
|
||||
case 6: // Output row 6.
|
||||
case 7: // Output row 10.
|
||||
case 8: // Output row 14.
|
||||
case 9: // Output row 18.
|
||||
return AsVariant(BGRAColor::Green().AsPixel());
|
||||
|
||||
// Fourth pass. Rows are positioned at 2n + 1.
|
||||
case 10: // Output row 1.
|
||||
case 11: // Output row 3.
|
||||
case 12: // Output row 5.
|
||||
case 13: // Output row 7.
|
||||
case 14: // Output row 9.
|
||||
case 15: // Output row 11.
|
||||
case 16: // Output row 13.
|
||||
case 17: // Output row 15.
|
||||
case 18: // Output row 17.
|
||||
case 19: // Output row 19.
|
||||
return AsVariant(BGRAColor::Red().AsPixel());
|
||||
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("Unexpected row");
|
||||
return AsVariant(BGRAColor::Transparent().AsPixel());
|
||||
}
|
||||
});
|
||||
EXPECT_EQ(WriteState::FINISHED, result);
|
||||
EXPECT_EQ(20u * 20u, count);
|
||||
|
||||
AssertCorrectPipelineFinalState(aFilter,
|
||||
IntRect(0, 0, 20, 20),
|
||||
IntRect(0, 0, 20, 20));
|
||||
|
||||
// Check that the generated image is correct. As mentioned above, we expect
|
||||
// even rows to be green and odd rows to be red.
|
||||
RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef();
|
||||
RefPtr<SourceSurface> surface = currentFrame->GetSurface();
|
||||
|
||||
for (uint32_t row = 0; row < 20; ++row) {
|
||||
EXPECT_TRUE(RowsAreSolidColor(surface, row, 1,
|
||||
row % 2 == 0 ? BGRAColor::Green()
|
||||
: BGRAColor::Red()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageDeinterlacingFilter, WriteRowsOutput7_7)
|
||||
{
|
||||
WithDeinterlacingFilter(IntSize(7, 7), /* aProgressiveDisplay = */ true,
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
// Fill the image. The output should be a repeating pattern of two green
|
||||
// rows followed by two red rows but we need to write the rows in the order
|
||||
// that the deinterlacer expects them.
|
||||
uint32_t count = 0;
|
||||
uint32_t row = 0;
|
||||
auto result = aFilter->WriteRows<uint32_t>([&](uint32_t* aRow, uint32_t aLength) {
|
||||
uint32_t color = 0;
|
||||
switch (row) {
|
||||
// First pass. Output rows are positioned at 8n + 0.
|
||||
case 0: // Output row 0.
|
||||
color = BGRAColor::Green().AsPixel();
|
||||
break;
|
||||
|
||||
// Second pass. Rows are positioned at 8n + 4.
|
||||
case 1: // Output row 4.
|
||||
color = BGRAColor::Green().AsPixel();
|
||||
break;
|
||||
|
||||
// Third pass. Rows are positioned at 4n + 2.
|
||||
case 2: // Output row 2.
|
||||
case 3: // Output row 6.
|
||||
color = BGRAColor::Red().AsPixel();
|
||||
break;
|
||||
|
||||
// Fourth pass. Rows are positioned at 2n + 1.
|
||||
case 4: // Output row 1.
|
||||
color = BGRAColor::Green().AsPixel();
|
||||
break;
|
||||
|
||||
case 5: // Output row 3.
|
||||
color = BGRAColor::Red().AsPixel();
|
||||
break;
|
||||
|
||||
case 6: // Output row 5.
|
||||
color = BGRAColor::Green().AsPixel();
|
||||
break;
|
||||
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("Unexpected row");
|
||||
}
|
||||
|
||||
++row;
|
||||
|
||||
for (; aLength > 0; --aLength, ++aRow, ++count) {
|
||||
*aRow = color;
|
||||
}
|
||||
|
||||
return Nothing();
|
||||
});
|
||||
EXPECT_EQ(WriteState::FINISHED, result);
|
||||
EXPECT_EQ(7u * 7u, count);
|
||||
EXPECT_EQ(7u, row);
|
||||
|
||||
AssertCorrectPipelineFinalState(aFilter,
|
||||
IntRect(0, 0, 7, 7),
|
||||
IntRect(0, 0, 7, 7));
|
||||
|
||||
// Check that the generated image is correct. As mentioned above, we expect
|
||||
// two green rows, followed by two red rows, then two green rows, etc.
|
||||
RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef();
|
||||
RefPtr<SourceSurface> surface = currentFrame->GetSurface();
|
||||
|
||||
for (uint32_t row = 0; row < 7; ++row) {
|
||||
BGRAColor color = row == 0 || row == 1 || row == 4 || row == 5
|
||||
? BGRAColor::Green()
|
||||
: BGRAColor::Red();
|
||||
EXPECT_TRUE(RowsAreSolidColor(surface, row, 1, color));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageDeinterlacingFilter, WritePixelsOutput3_3)
|
||||
{
|
||||
WithDeinterlacingFilter(IntSize(3, 3), /* aProgressiveDisplay = */ true,
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
// Fill the image. The output should be green, red, green in that order, but
|
||||
// we need to write the rows in the order that the deinterlacer expects
|
||||
// them.
|
||||
uint32_t count = 0;
|
||||
auto result = aFilter->WritePixels<uint32_t>([&]() {
|
||||
uint32_t row = count / 3; // Integer division.
|
||||
++count;
|
||||
|
||||
switch (row) {
|
||||
// First pass. Output rows are positioned at 8n + 0.
|
||||
case 0: // Output row 0.
|
||||
return AsVariant(BGRAColor::Green().AsPixel());
|
||||
|
||||
// Second pass. Rows are positioned at 8n + 4.
|
||||
// No rows for this pass.
|
||||
|
||||
// Third pass. Rows are positioned at 4n + 2.
|
||||
case 1: // Output row 2.
|
||||
return AsVariant(BGRAColor::Green().AsPixel());
|
||||
|
||||
// Fourth pass. Rows are positioned at 2n + 1.
|
||||
case 2: // Output row 1.
|
||||
return AsVariant(BGRAColor::Red().AsPixel());
|
||||
|
||||
default:
|
||||
MOZ_ASSERT_UNREACHABLE("Unexpected row");
|
||||
return AsVariant(BGRAColor::Transparent().AsPixel());
|
||||
}
|
||||
});
|
||||
EXPECT_EQ(WriteState::FINISHED, result);
|
||||
EXPECT_EQ(3u * 3u, count);
|
||||
|
||||
AssertCorrectPipelineFinalState(aFilter,
|
||||
IntRect(0, 0, 3, 3),
|
||||
IntRect(0, 0, 3, 3));
|
||||
|
||||
// Check that the generated image is correct. As mentioned above, we expect
|
||||
// green, red, green in that order.
|
||||
RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef();
|
||||
RefPtr<SourceSurface> surface = currentFrame->GetSurface();
|
||||
|
||||
for (uint32_t row = 0; row < 3; ++row) {
|
||||
EXPECT_TRUE(RowsAreSolidColor(surface, row, 1,
|
||||
row == 0 || row == 2 ? BGRAColor::Green()
|
||||
: BGRAColor::Red()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageDeinterlacingFilter, WritePixelsOutput1_1)
|
||||
{
|
||||
WithDeinterlacingFilter(IntSize(1, 1), /* aProgressiveDisplay = */ true,
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
// Fill the image. The output should be a single red row.
|
||||
uint32_t count = 0;
|
||||
auto result = aFilter->WritePixels<uint32_t>([&]() {
|
||||
++count;
|
||||
return AsVariant(BGRAColor::Red().AsPixel());
|
||||
});
|
||||
EXPECT_EQ(WriteState::FINISHED, result);
|
||||
EXPECT_EQ(1u, count);
|
||||
|
||||
AssertCorrectPipelineFinalState(aFilter,
|
||||
IntRect(0, 0, 1, 1),
|
||||
IntRect(0, 0, 1, 1));
|
||||
|
||||
// Check that the generated image is correct. As mentioned above, we expect
|
||||
// a single red row.
|
||||
RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef();
|
||||
RefPtr<SourceSurface> surface = currentFrame->GetSurface();
|
||||
|
||||
EXPECT_TRUE(RowsAreSolidColor(surface, 0, 1, BGRAColor::Red()));
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
WriteRowAndCheckInterlacerOutput(Decoder* aDecoder,
|
||||
SurfaceFilter* aFilter,
|
||||
BGRAColor aColor,
|
||||
WriteState aNextState,
|
||||
IntRect aInvalidRect,
|
||||
uint32_t aFirstHaeberliRow,
|
||||
uint32_t aLastHaeberliRow)
|
||||
{
|
||||
uint32_t count = 0;
|
||||
|
||||
auto result = aFilter->WriteRows<uint32_t>([&](uint32_t* aRow, uint32_t aLength) {
|
||||
for (; aLength > 0; --aLength, ++aRow, ++count) {
|
||||
*aRow = aColor.AsPixel();
|
||||
}
|
||||
return Some(WriteState::NEED_MORE_DATA);
|
||||
});
|
||||
|
||||
EXPECT_EQ(aNextState, result);
|
||||
EXPECT_EQ(7u, count);
|
||||
|
||||
// Assert that we got the expected invalidation region.
|
||||
Maybe<SurfaceInvalidRect> invalidRect = aFilter->TakeInvalidRect();
|
||||
EXPECT_TRUE(invalidRect.isSome());
|
||||
EXPECT_EQ(aInvalidRect, invalidRect->mInputSpaceRect);
|
||||
EXPECT_EQ(aInvalidRect, invalidRect->mOutputSpaceRect);
|
||||
|
||||
// Check that the portion of the image generated so far is correct. The rows
|
||||
// from aFirstHaeberliRow to aLastHaeberliRow should be filled with aColor.
|
||||
// Note that this is not the same as the set of rows in aInvalidRect, because
|
||||
// after writing a row the deinterlacer seeks to the next row to write, which
|
||||
// may involve copying previously-written rows in the buffer to the output
|
||||
// even though they don't change in this pass.
|
||||
RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef();
|
||||
RefPtr<SourceSurface> surface = currentFrame->GetSurface();
|
||||
|
||||
for (uint32_t row = aFirstHaeberliRow; row <= aLastHaeberliRow; ++row) {
|
||||
EXPECT_TRUE(RowsAreSolidColor(surface, row, 1, aColor));
|
||||
}
|
||||
}
|
||||
|
||||
TEST(ImageDeinterlacingFilter, WriteRowsIntermediateOutput7_7)
|
||||
{
|
||||
WithDeinterlacingFilter(IntSize(7, 7), /* aProgressiveDisplay = */ true,
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
// Fill the image. The output should be a repeating pattern of two green
|
||||
// rows followed by two red rows but we need to write the rows in the order
|
||||
// that the deinterlacer expects them.
|
||||
|
||||
// First pass. Output rows are positioned at 8n + 0.
|
||||
|
||||
// Output row 0. The invalid rect is the entire image because this is the
|
||||
// end of the first pass.
|
||||
WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Green(),
|
||||
WriteState::NEED_MORE_DATA,
|
||||
IntRect(0, 0, 7, 7), 0, 4);
|
||||
|
||||
// Second pass. Rows are positioned at 8n + 4.
|
||||
|
||||
// Output row 4. The invalid rect is the entire image because this is the
|
||||
// end of the second pass.
|
||||
WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Green(),
|
||||
WriteState::NEED_MORE_DATA,
|
||||
IntRect(0, 0, 7, 7), 1, 4);
|
||||
|
||||
// Third pass. Rows are positioned at 4n + 2.
|
||||
|
||||
// Output row 2. The invalid rect contains the Haeberli rows for this output
|
||||
// row (rows 2 and 3) as well as the rows that we copy from previous passes
|
||||
// when seeking to the next output row (rows 4 and 5).
|
||||
WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Red(),
|
||||
WriteState::NEED_MORE_DATA,
|
||||
IntRect(0, 2, 7, 4), 2, 3);
|
||||
|
||||
// Output row 6. The invalid rect is the entire image because this is the
|
||||
// end of the third pass.
|
||||
WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Red(),
|
||||
WriteState::NEED_MORE_DATA,
|
||||
IntRect(0, 0, 7, 7), 6, 6);
|
||||
|
||||
// Fourth pass. Rows are positioned at 2n + 1.
|
||||
|
||||
// Output row 1. The invalid rect contains the Haeberli rows for this output
|
||||
// row (just row 1) as well as the rows that we copy from previous passes
|
||||
// when seeking to the next output row (row 2).
|
||||
WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Green(),
|
||||
WriteState::NEED_MORE_DATA,
|
||||
IntRect(0, 1, 7, 2), 1, 1);
|
||||
|
||||
// Output row 3. The invalid rect contains the Haeberli rows for this output
|
||||
// row (just row 3) as well as the rows that we copy from previous passes
|
||||
// when seeking to the next output row (row 4).
|
||||
WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Red(),
|
||||
WriteState::NEED_MORE_DATA,
|
||||
IntRect(0, 3, 7, 2), 3, 3);
|
||||
|
||||
// Output row 5. The invalid rect contains the Haeberli rows for this output
|
||||
// row (just row 5) as well as the rows that we copy from previous passes
|
||||
// when seeking to the next output row (row 6).
|
||||
WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Green(),
|
||||
WriteState::FINISHED,
|
||||
IntRect(0, 5, 7, 2), 5, 5);
|
||||
|
||||
// Assert that we're in the expected final state.
|
||||
EXPECT_TRUE(aFilter->IsSurfaceFinished());
|
||||
Maybe<SurfaceInvalidRect> invalidRect = aFilter->TakeInvalidRect();
|
||||
EXPECT_TRUE(invalidRect.isNothing());
|
||||
|
||||
// Check that the generated image is correct. As mentioned above, we expect
|
||||
// two green rows, followed by two red rows, then two green rows, etc.
|
||||
RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef();
|
||||
RefPtr<SourceSurface> surface = currentFrame->GetSurface();
|
||||
|
||||
for (uint32_t row = 0; row < 7; ++row) {
|
||||
BGRAColor color = row == 0 || row == 1 || row == 4 || row == 5
|
||||
? BGRAColor::Green()
|
||||
: BGRAColor::Red();
|
||||
EXPECT_TRUE(RowsAreSolidColor(surface, row, 1, color));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageDeinterlacingFilter, WriteRowsNonProgressiveIntermediateOutput7_7)
|
||||
{
|
||||
WithDeinterlacingFilter(IntSize(7, 7), /* aProgressiveDisplay = */ false,
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
// Fill the image. The output should be a repeating pattern of two green
|
||||
// rows followed by two red rows but we need to write the rows in the order
|
||||
// that the deinterlacer expects them.
|
||||
|
||||
// First pass. Output rows are positioned at 8n + 0.
|
||||
|
||||
// Output row 0. The invalid rect is the entire image because this is the
|
||||
// end of the first pass.
|
||||
WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Green(),
|
||||
WriteState::NEED_MORE_DATA,
|
||||
IntRect(0, 0, 7, 7), 0, 0);
|
||||
|
||||
// Second pass. Rows are positioned at 8n + 4.
|
||||
|
||||
// Output row 4. The invalid rect is the entire image because this is the
|
||||
// end of the second pass.
|
||||
WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Green(),
|
||||
WriteState::NEED_MORE_DATA,
|
||||
IntRect(0, 0, 7, 7), 4, 4);
|
||||
|
||||
// Third pass. Rows are positioned at 4n + 2.
|
||||
|
||||
// Output row 2. The invalid rect contains the Haeberli rows for this output
|
||||
// row (rows 2 and 3) as well as the rows that we copy from previous passes
|
||||
// when seeking to the next output row (rows 4 and 5).
|
||||
WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Red(),
|
||||
WriteState::NEED_MORE_DATA,
|
||||
IntRect(0, 2, 7, 4), 2, 2);
|
||||
|
||||
// Output row 6. The invalid rect is the entire image because this is the
|
||||
// end of the third pass.
|
||||
WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Red(),
|
||||
WriteState::NEED_MORE_DATA,
|
||||
IntRect(0, 0, 7, 7), 6, 6);
|
||||
|
||||
// Fourth pass. Rows are positioned at 2n + 1.
|
||||
|
||||
// Output row 1. The invalid rect contains the Haeberli rows for this output
|
||||
// row (just row 1) as well as the rows that we copy from previous passes
|
||||
// when seeking to the next output row (row 2).
|
||||
WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Green(),
|
||||
WriteState::NEED_MORE_DATA,
|
||||
IntRect(0, 1, 7, 2), 1, 1);
|
||||
|
||||
// Output row 3. The invalid rect contains the Haeberli rows for this output
|
||||
// row (just row 3) as well as the rows that we copy from previous passes
|
||||
// when seeking to the next output row (row 4).
|
||||
WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Red(),
|
||||
WriteState::NEED_MORE_DATA,
|
||||
IntRect(0, 3, 7, 2), 3, 3);
|
||||
|
||||
// Output row 5. The invalid rect contains the Haeberli rows for this output
|
||||
// row (just row 5) as well as the rows that we copy from previous passes
|
||||
// when seeking to the next output row (row 6).
|
||||
WriteRowAndCheckInterlacerOutput(aDecoder, aFilter, BGRAColor::Green(),
|
||||
WriteState::FINISHED,
|
||||
IntRect(0, 5, 7, 2), 5, 5);
|
||||
|
||||
// Assert that we're in the expected final state.
|
||||
EXPECT_TRUE(aFilter->IsSurfaceFinished());
|
||||
Maybe<SurfaceInvalidRect> invalidRect = aFilter->TakeInvalidRect();
|
||||
EXPECT_TRUE(invalidRect.isNothing());
|
||||
|
||||
// Check that the generated image is correct. As mentioned above, we expect
|
||||
// two green rows, followed by two red rows, then two green rows, etc.
|
||||
RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef();
|
||||
RefPtr<SourceSurface> surface = currentFrame->GetSurface();
|
||||
|
||||
for (uint32_t row = 0; row < 7; ++row) {
|
||||
BGRAColor color = row == 0 || row == 1 || row == 4 || row == 5
|
||||
? BGRAColor::Green()
|
||||
: BGRAColor::Red();
|
||||
EXPECT_TRUE(RowsAreSolidColor(surface, row, 1, color));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
TEST(ImageDeinterlacingFilter, DeinterlacingFailsFor0_0)
|
||||
{
|
||||
// A 0x0 input size is invalid, so configuration should fail.
|
||||
AssertConfiguringDeinterlacingFilterFails(IntSize(0, 0));
|
||||
}
|
||||
|
||||
TEST(ImageDeinterlacingFilter, DeinterlacingFailsForMinus1_Minus1)
|
||||
{
|
||||
// A negative input size is invalid, so configuration should fail.
|
||||
AssertConfiguringDeinterlacingFilterFails(IntSize(-1, -1));
|
||||
}
|
364
image/test/gtest/TestDownscalingFilter.cpp
Normal file
364
image/test/gtest/TestDownscalingFilter.cpp
Normal file
@ -0,0 +1,364 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "Common.h"
|
||||
#include "Decoder.h"
|
||||
#include "DecoderFactory.h"
|
||||
#include "SourceBuffer.h"
|
||||
#include "SurfaceFilters.h"
|
||||
#include "SurfacePipe.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::gfx;
|
||||
using namespace mozilla::image;
|
||||
|
||||
template <typename Func> void
|
||||
WithDownscalingFilter(const IntSize& aInputSize,
|
||||
const IntSize& aOutputSize,
|
||||
Func aFunc)
|
||||
{
|
||||
RefPtr<Decoder> decoder = CreateTrivialDecoder();
|
||||
ASSERT_TRUE(decoder != nullptr);
|
||||
|
||||
WithFilterPipeline(decoder, Forward<Func>(aFunc),
|
||||
DownscalingConfig { aInputSize,
|
||||
SurfaceFormat::B8G8R8A8 },
|
||||
SurfaceConfig { decoder, 0, aOutputSize,
|
||||
SurfaceFormat::B8G8R8A8, false });
|
||||
}
|
||||
|
||||
void
|
||||
AssertConfiguringDownscalingFilterFails(const IntSize& aInputSize,
|
||||
const IntSize& aOutputSize)
|
||||
{
|
||||
RefPtr<Decoder> decoder = CreateTrivialDecoder();
|
||||
ASSERT_TRUE(decoder != nullptr);
|
||||
|
||||
AssertConfiguringPipelineFails(decoder,
|
||||
DownscalingConfig { aInputSize,
|
||||
SurfaceFormat::B8G8R8A8 },
|
||||
SurfaceConfig { decoder, 0, aOutputSize,
|
||||
SurfaceFormat::B8G8R8A8, false });
|
||||
}
|
||||
|
||||
TEST(ImageDownscalingFilter, WritePixels100_100to99_99)
|
||||
{
|
||||
WithDownscalingFilter(IntSize(100, 100), IntSize(99, 99),
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckWritePixels(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 99, 99)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageDownscalingFilter, WriteRows100_100to99_99)
|
||||
{
|
||||
WithDownscalingFilter(IntSize(100, 100), IntSize(99, 99),
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckWriteRows(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 99, 99)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageDownscalingFilter, WritePixels100_100to33_33)
|
||||
{
|
||||
WithDownscalingFilter(IntSize(100, 100), IntSize(33, 33),
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckWritePixels(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 33, 33)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageDownscalingFilter, WriteRows100_100to33_33)
|
||||
{
|
||||
WithDownscalingFilter(IntSize(100, 100), IntSize(33, 33),
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckWriteRows(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 33, 33)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageDownscalingFilter, WritePixels100_100to1_1)
|
||||
{
|
||||
WithDownscalingFilter(IntSize(100, 100), IntSize(1, 1),
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckWritePixels(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 1, 1)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageDownscalingFilter, WriteRows100_100to1_1)
|
||||
{
|
||||
WithDownscalingFilter(IntSize(100, 100), IntSize(1, 1),
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckWriteRows(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 1, 1)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageDownscalingFilter, WritePixels100_100to33_99)
|
||||
{
|
||||
WithDownscalingFilter(IntSize(100, 100), IntSize(33, 99),
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckWritePixels(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 33, 99)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageDownscalingFilter, WriteRows100_100to33_99)
|
||||
{
|
||||
WithDownscalingFilter(IntSize(100, 100), IntSize(33, 99),
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckWriteRows(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 33, 99)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageDownscalingFilter, WritePixels100_100to99_33)
|
||||
{
|
||||
WithDownscalingFilter(IntSize(100, 100), IntSize(99, 33),
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckWritePixels(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 99, 33)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageDownscalingFilter, WriteRows100_100to99_33)
|
||||
{
|
||||
WithDownscalingFilter(IntSize(100, 100), IntSize(99, 33),
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckWriteRows(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 99, 33)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageDownscalingFilter, WritePixels100_100to99_1)
|
||||
{
|
||||
WithDownscalingFilter(IntSize(100, 100), IntSize(99, 1),
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckWritePixels(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 99, 1)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageDownscalingFilter, WriteRows100_100to99_1)
|
||||
{
|
||||
WithDownscalingFilter(IntSize(100, 100), IntSize(99, 1),
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckWriteRows(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 99, 1)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageDownscalingFilter, WritePixels100_100to1_99)
|
||||
{
|
||||
WithDownscalingFilter(IntSize(100, 100), IntSize(1, 99),
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckWritePixels(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 1, 99)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageDownscalingFilter, WriteRows100_100to1_99)
|
||||
{
|
||||
WithDownscalingFilter(IntSize(100, 100), IntSize(1, 99),
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckWriteRows(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 1, 99)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageDownscalingFilter, DownscalingFailsFor100_100to101_101)
|
||||
{
|
||||
// Upscaling is disallowed.
|
||||
AssertConfiguringDownscalingFilterFails(IntSize(100, 100), IntSize(101, 101));
|
||||
}
|
||||
|
||||
TEST(ImageDownscalingFilter, DownscalingFailsFor100_100to100_100)
|
||||
{
|
||||
// "Scaling" to the same size is disallowed.
|
||||
AssertConfiguringDownscalingFilterFails(IntSize(100, 100), IntSize(100, 100));
|
||||
}
|
||||
|
||||
TEST(ImageDownscalingFilter, DownscalingFailsFor0_0toMinus1_Minus1)
|
||||
{
|
||||
// A 0x0 input size is disallowed.
|
||||
AssertConfiguringDownscalingFilterFails(IntSize(0, 0), IntSize(-1, -1));
|
||||
}
|
||||
|
||||
TEST(ImageDownscalingFilter, DownscalingFailsForMinus1_Minus1toMinus2_Minus2)
|
||||
{
|
||||
// A negative input size is disallowed.
|
||||
AssertConfiguringDownscalingFilterFails(IntSize(-1, -1), IntSize(-2, -2));
|
||||
}
|
||||
|
||||
TEST(ImageDownscalingFilter, DownscalingFailsFor100_100to0_0)
|
||||
{
|
||||
// A 0x0 output size is disallowed.
|
||||
AssertConfiguringDownscalingFilterFails(IntSize(100, 100), IntSize(0, 0));
|
||||
}
|
||||
|
||||
TEST(ImageDownscalingFilter, DownscalingFailsFor100_100toMinus1_Minus1)
|
||||
{
|
||||
// A negative output size is disallowed.
|
||||
AssertConfiguringDownscalingFilterFails(IntSize(100, 100), IntSize(-1, -1));
|
||||
}
|
||||
|
||||
TEST(ImageDownscalingFilter, WritePixelsOutput100_100to20_20)
|
||||
{
|
||||
WithDownscalingFilter(IntSize(100, 100), IntSize(20, 20),
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
// Fill the image. It consists of 25 lines of green, followed by 25 lines of
|
||||
// red, followed by 25 lines of green, followed by 25 more lines of red.
|
||||
uint32_t count = 0;
|
||||
auto result = aFilter->WritePixels<uint32_t>([&]() -> NextPixel<uint32_t> {
|
||||
uint32_t color = (count <= 25 * 100) || (count > 50 * 100 && count <= 75 * 100)
|
||||
? BGRAColor::Green().AsPixel()
|
||||
: BGRAColor::Red().AsPixel();
|
||||
++count;
|
||||
return AsVariant(color);
|
||||
});
|
||||
EXPECT_EQ(WriteState::FINISHED, result);
|
||||
EXPECT_EQ(100u * 100u, count);
|
||||
|
||||
AssertCorrectPipelineFinalState(aFilter,
|
||||
IntRect(0, 0, 100, 100),
|
||||
IntRect(0, 0, 20, 20));
|
||||
|
||||
// Check that the generated image is correct. Note that we skip rows near
|
||||
// the transitions between colors, since the downscaler does not produce a
|
||||
// sharp boundary at these points. Even some of the rows we test need a
|
||||
// small amount of fuzz; this is just the nature of Lanczos downscaling.
|
||||
RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef();
|
||||
RefPtr<SourceSurface> surface = currentFrame->GetSurface();
|
||||
EXPECT_TRUE(RowsAreSolidColor(surface, 0, 4, BGRAColor::Green(), /* aFuzz = */ 2));
|
||||
EXPECT_TRUE(RowsAreSolidColor(surface, 6, 3, BGRAColor::Red(), /* aFuzz = */ 3));
|
||||
EXPECT_TRUE(RowsAreSolidColor(surface, 11, 3, BGRAColor::Green(), /* aFuzz = */ 3));
|
||||
EXPECT_TRUE(RowsAreSolidColor(surface, 16, 4, BGRAColor::Red(), /* aFuzz = */ 3));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageDownscalingFilter, WriteRowsOutput100_100to20_20)
|
||||
{
|
||||
WithDownscalingFilter(IntSize(100, 100), IntSize(20, 20),
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
// Fill the image. It consists of 25 lines of green, followed by 25 lines of
|
||||
// red, followed by 25 lines of green, followed by 25 more lines of red.
|
||||
uint32_t count = 0;
|
||||
auto result = aFilter->WriteRows<uint32_t>([&](uint32_t* aRow, uint32_t aLength) {
|
||||
uint32_t color = (count <= 25 * 100) || (count > 50 * 100 && count <= 75 * 100)
|
||||
? BGRAColor::Green().AsPixel()
|
||||
: BGRAColor::Red().AsPixel();
|
||||
for (; aLength > 0; --aLength, ++aRow, ++count) {
|
||||
*aRow = color;
|
||||
}
|
||||
return Nothing();
|
||||
});
|
||||
EXPECT_EQ(WriteState::FINISHED, result);
|
||||
EXPECT_EQ(100u * 100u, count);
|
||||
|
||||
AssertCorrectPipelineFinalState(aFilter,
|
||||
IntRect(0, 0, 100, 100),
|
||||
IntRect(0, 0, 20, 20));
|
||||
|
||||
// Check that the generated image is correct. (Note that we skip rows near
|
||||
// the transitions between colors, since the downscaler does not produce a
|
||||
// sharp boundary at these points.)
|
||||
RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef();
|
||||
RefPtr<SourceSurface> surface = currentFrame->GetSurface();
|
||||
EXPECT_TRUE(RowsAreSolidColor(surface, 0, 4, BGRAColor::Green(), /* aFuzz = */ 2));
|
||||
EXPECT_TRUE(RowsAreSolidColor(surface, 6, 3, BGRAColor::Red(), /* aFuzz = */ 3));
|
||||
EXPECT_TRUE(RowsAreSolidColor(surface, 11, 3, BGRAColor::Green(), /* aFuzz = */ 3));
|
||||
EXPECT_TRUE(RowsAreSolidColor(surface, 16, 4, BGRAColor::Red(), /* aFuzz = */ 3));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageDownscalingFilter, WritePixelsOutput100_100to10_20)
|
||||
{
|
||||
WithDownscalingFilter(IntSize(100, 100), IntSize(10, 20),
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
// Fill the image. It consists of 25 lines of green, followed by 25 lines of
|
||||
// red, followed by 25 lines of green, followed by 25 more lines of red.
|
||||
uint32_t count = 0;
|
||||
auto result = aFilter->WritePixels<uint32_t>([&]() -> NextPixel<uint32_t> {
|
||||
uint32_t color = (count <= 25 * 100) || (count > 50 * 100 && count <= 75 * 100)
|
||||
? BGRAColor::Green().AsPixel()
|
||||
: BGRAColor::Red().AsPixel();
|
||||
++count;
|
||||
return AsVariant(color);
|
||||
});
|
||||
EXPECT_EQ(WriteState::FINISHED, result);
|
||||
EXPECT_EQ(100u * 100u, count);
|
||||
|
||||
AssertCorrectPipelineFinalState(aFilter,
|
||||
IntRect(0, 0, 100, 100),
|
||||
IntRect(0, 0, 10, 20));
|
||||
|
||||
// Check that the generated image is correct. Note that we skip rows near
|
||||
// the transitions between colors, since the downscaler does not produce a
|
||||
// sharp boundary at these points. Even some of the rows we test need a
|
||||
// small amount of fuzz; this is just the nature of Lanczos downscaling.
|
||||
RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef();
|
||||
RefPtr<SourceSurface> surface = currentFrame->GetSurface();
|
||||
EXPECT_TRUE(RowsAreSolidColor(surface, 0, 4, BGRAColor::Green(), /* aFuzz = */ 2));
|
||||
EXPECT_TRUE(RowsAreSolidColor(surface, 6, 3, BGRAColor::Red(), /* aFuzz = */ 3));
|
||||
EXPECT_TRUE(RowsAreSolidColor(surface, 11, 3, BGRAColor::Green(), /* aFuzz = */ 3));
|
||||
EXPECT_TRUE(RowsAreSolidColor(surface, 16, 4, BGRAColor::Red(), /* aFuzz = */ 3));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageDownscalingFilter, WriteRowsOutput100_100to10_20)
|
||||
{
|
||||
WithDownscalingFilter(IntSize(100, 100), IntSize(10, 20),
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
// Fill the image. It consists of 25 lines of green, followed by 25 lines of
|
||||
// red, followed by 25 lines of green, followed by 25 more lines of red.
|
||||
uint32_t count = 0;
|
||||
auto result = aFilter->WriteRows<uint32_t>([&](uint32_t* aRow, uint32_t aLength) {
|
||||
uint32_t color = (count <= 25 * 100) || (count > 50 * 100 && count <= 75 * 100)
|
||||
? BGRAColor::Green().AsPixel()
|
||||
: BGRAColor::Red().AsPixel();
|
||||
for (; aLength > 0; --aLength, ++aRow, ++count) {
|
||||
*aRow = color;
|
||||
}
|
||||
return Nothing();
|
||||
});
|
||||
EXPECT_EQ(WriteState::FINISHED, result);
|
||||
EXPECT_EQ(100u * 100u, count);
|
||||
|
||||
AssertCorrectPipelineFinalState(aFilter,
|
||||
IntRect(0, 0, 100, 100),
|
||||
IntRect(0, 0, 10, 20));
|
||||
|
||||
// Check that the generated image is correct. (Note that we skip rows near
|
||||
// the transitions between colors, since the downscaler does not produce a
|
||||
// sharp boundary at these points.)
|
||||
RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef();
|
||||
RefPtr<SourceSurface> surface = currentFrame->GetSurface();
|
||||
EXPECT_TRUE(RowsAreSolidColor(surface, 0, 4, BGRAColor::Green(), /* aFuzz = */ 2));
|
||||
EXPECT_TRUE(RowsAreSolidColor(surface, 6, 3, BGRAColor::Red(), /* aFuzz = */ 3));
|
||||
EXPECT_TRUE(RowsAreSolidColor(surface, 11, 3, BGRAColor::Green(), /* aFuzz = */ 3));
|
||||
EXPECT_TRUE(RowsAreSolidColor(surface, 16, 4, BGRAColor::Red(), /* aFuzz = */ 3));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageDownscalingFilter, ConfiguringPalettedDownscaleFails)
|
||||
{
|
||||
RefPtr<Decoder> decoder = CreateTrivialDecoder();
|
||||
ASSERT_TRUE(decoder != nullptr);
|
||||
|
||||
// DownscalingFilter does not support paletted images, so configuration should
|
||||
// fail.
|
||||
AssertConfiguringPipelineFails(decoder,
|
||||
DownscalingConfig { IntSize(100, 100),
|
||||
SurfaceFormat::B8G8R8A8 },
|
||||
PalettedSurfaceConfig { decoder, 0, IntSize(20, 20),
|
||||
IntRect(0, 0, 20, 20),
|
||||
SurfaceFormat::B8G8R8A8, 8,
|
||||
false });
|
||||
}
|
57
image/test/gtest/TestDownscalingFilterNoSkia.cpp
Normal file
57
image/test/gtest/TestDownscalingFilterNoSkia.cpp
Normal file
@ -0,0 +1,57 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "Decoder.h"
|
||||
#include "DecoderFactory.h"
|
||||
#include "SourceBuffer.h"
|
||||
#include "SurfacePipe.h"
|
||||
|
||||
// We want to ensure that we're testing the non-Skia fallback version of
|
||||
// DownscalingFilter, but there are two issues:
|
||||
// (1) We don't know whether Skia is currently enabled.
|
||||
// (2) If we force disable it, the disabled version will get linked into the
|
||||
// binary and will cause the tests in TestDownscalingFilter to fail.
|
||||
// To avoid these problems, we ensure that MOZ_ENABLE_SKIA is defined when
|
||||
// including DownscalingFilter.h, and we use the preprocessor to redefine the
|
||||
// DownscalingFilter class to DownscalingFilterNoSkia.
|
||||
|
||||
#define DownscalingFilter DownscalingFilterNoSkia
|
||||
|
||||
#ifdef MOZ_ENABLE_SKIA
|
||||
|
||||
#undef MOZ_ENABLE_SKIA
|
||||
#include "Common.h"
|
||||
#include "DownscalingFilter.h"
|
||||
#define MOZ_ENABLE_SKIA
|
||||
|
||||
#else
|
||||
|
||||
#include "Common.h"
|
||||
#include "DownscalingFilter.h"
|
||||
|
||||
#endif
|
||||
|
||||
#undef DownscalingFilter
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::gfx;
|
||||
using namespace mozilla::image;
|
||||
|
||||
TEST(ImageDownscalingFilter, NoSkia)
|
||||
{
|
||||
RefPtr<Decoder> decoder = CreateTrivialDecoder();
|
||||
ASSERT_TRUE(bool(decoder));
|
||||
|
||||
// Configuring a DownscalingFilter should fail without Skia.
|
||||
AssertConfiguringPipelineFails(decoder,
|
||||
DownscalingConfig { IntSize(100, 100),
|
||||
SurfaceFormat::B8G8R8A8 },
|
||||
SurfaceConfig { decoder, 0, IntSize(50, 50),
|
||||
SurfaceFormat::B8G8R8A8, false });
|
||||
}
|
565
image/test/gtest/TestRemoveFrameRectFilter.cpp
Normal file
565
image/test/gtest/TestRemoveFrameRectFilter.cpp
Normal file
@ -0,0 +1,565 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "Common.h"
|
||||
#include "Decoder.h"
|
||||
#include "DecoderFactory.h"
|
||||
#include "SourceBuffer.h"
|
||||
#include "SurfaceFilters.h"
|
||||
#include "SurfacePipe.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::gfx;
|
||||
using namespace mozilla::image;
|
||||
|
||||
template <typename Func> void
|
||||
WithRemoveFrameRectFilter(const IntSize& aSize,
|
||||
const IntRect& aFrameRect,
|
||||
Func aFunc)
|
||||
{
|
||||
RefPtr<Decoder> decoder = CreateTrivialDecoder();
|
||||
ASSERT_TRUE(decoder != nullptr);
|
||||
|
||||
WithFilterPipeline(decoder, Forward<Func>(aFunc),
|
||||
RemoveFrameRectConfig { aFrameRect },
|
||||
SurfaceConfig { decoder, 0, aSize,
|
||||
SurfaceFormat::B8G8R8A8, false });
|
||||
}
|
||||
|
||||
void
|
||||
AssertConfiguringRemoveFrameRectFilterFails(const IntSize& aSize,
|
||||
const IntRect& aFrameRect)
|
||||
{
|
||||
RefPtr<Decoder> decoder = CreateTrivialDecoder();
|
||||
ASSERT_TRUE(decoder != nullptr);
|
||||
|
||||
AssertConfiguringPipelineFails(decoder,
|
||||
RemoveFrameRectConfig { aFrameRect },
|
||||
SurfaceConfig { decoder, 0, aSize,
|
||||
SurfaceFormat::B8G8R8A8, false });
|
||||
}
|
||||
|
||||
TEST(ImageRemoveFrameRectFilter, WritePixels100_100_to_0_0_100_100)
|
||||
{
|
||||
WithRemoveFrameRectFilter(IntSize(100, 100),
|
||||
IntRect(0, 0, 100, 100),
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckWritePixels(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputWriteRect = */ Some(IntRect(0, 0, 100, 100)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageRemoveFrameRectFilter, WriteRows100_100_to_0_0_100_100)
|
||||
{
|
||||
WithRemoveFrameRectFilter(IntSize(100, 100),
|
||||
IntRect(0, 0, 100, 100),
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckWriteRows(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputWriteRect = */ Some(IntRect(0, 0, 100, 100)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageRemoveFrameRectFilter, WritePixels100_100_to_0_0_0_0)
|
||||
{
|
||||
WithRemoveFrameRectFilter(IntSize(100, 100),
|
||||
IntRect(0, 0, 0, 0),
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckWritePixels(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputWriteRect = */ Some(IntRect(0, 0, 0, 0)),
|
||||
/* aOutputWriteRect = */ Some(IntRect(0, 0, 0, 0)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageRemoveFrameRectFilter, WriteRows100_100_to_0_0_0_0)
|
||||
{
|
||||
WithRemoveFrameRectFilter(IntSize(100, 100),
|
||||
IntRect(0, 0, 0, 0),
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckWriteRows(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputWriteRect = */ Some(IntRect(0, 0, 0, 0)),
|
||||
/* aOutputWriteRect = */ Some(IntRect(0, 0, 0, 0)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageRemoveFrameRectFilter, WritePixels100_100_to_Minus50_50_0_0)
|
||||
{
|
||||
WithRemoveFrameRectFilter(IntSize(100, 100),
|
||||
IntRect(-50, 50, 0, 0),
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckWritePixels(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputWriteRect = */ Some(IntRect(0, 0, 0, 0)),
|
||||
/* aOutputWriteRect = */ Some(IntRect(0, 0, 0, 0)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageRemoveFrameRectFilter, WriteRows100_100_to_Minus50_50_0_0)
|
||||
{
|
||||
WithRemoveFrameRectFilter(IntSize(100, 100),
|
||||
IntRect(-50, 50, 0, 0),
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckWriteRows(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputWriteRect = */ Some(IntRect(0, 0, 0, 0)),
|
||||
/* aOutputWriteRect = */ Some(IntRect(0, 0, 0, 0)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageRemoveFrameRectFilter, WritePixels100_100_to_50_Minus50_0_0)
|
||||
{
|
||||
WithRemoveFrameRectFilter(IntSize(100, 100),
|
||||
IntRect(50, -50, 0, 0),
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckWritePixels(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputWriteRect = */ Some(IntRect(0, 0, 0, 0)),
|
||||
/* aOutputWriteRect = */ Some(IntRect(0, 0, 0, 0)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageRemoveFrameRectFilter, WriteRows100_100_to_50_Minus50_0_0)
|
||||
{
|
||||
WithRemoveFrameRectFilter(IntSize(100, 100),
|
||||
IntRect(50, -50, 0, 0),
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckWriteRows(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputWriteRect = */ Some(IntRect(0, 0, 0, 0)),
|
||||
/* aOutputWriteRect = */ Some(IntRect(0, 0, 0, 0)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageRemoveFrameRectFilter, WritePixels100_100_to_150_50_0_0)
|
||||
{
|
||||
WithRemoveFrameRectFilter(IntSize(100, 100),
|
||||
IntRect(150, 50, 0, 0),
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckWritePixels(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputWriteRect = */ Some(IntRect(0, 0, 0, 0)),
|
||||
/* aOutputWriteRect = */ Some(IntRect(0, 0, 0, 0)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageRemoveFrameRectFilter, WriteRows100_100_to_150_50_0_0)
|
||||
{
|
||||
WithRemoveFrameRectFilter(IntSize(100, 100),
|
||||
IntRect(150, 50, 0, 0),
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckWriteRows(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputWriteRect = */ Some(IntRect(0, 0, 0, 0)),
|
||||
/* aOutputWriteRect = */ Some(IntRect(0, 0, 0, 0)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageRemoveFrameRectFilter, WritePixels100_100_to_50_150_0_0)
|
||||
{
|
||||
WithRemoveFrameRectFilter(IntSize(100, 100),
|
||||
IntRect(50, 150, 0, 0),
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckWritePixels(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputWriteRect = */ Some(IntRect(0, 0, 0, 0)),
|
||||
/* aOutputWriteRect = */ Some(IntRect(0, 0, 0, 0)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageRemoveFrameRectFilter, WriteRows100_100_to_50_150_0_0)
|
||||
{
|
||||
WithRemoveFrameRectFilter(IntSize(100, 100),
|
||||
IntRect(50, 150, 0, 0),
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckWriteRows(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputWriteRect = */ Some(IntRect(0, 0, 0, 0)),
|
||||
/* aOutputWriteRect = */ Some(IntRect(0, 0, 0, 0)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageRemoveFrameRectFilter, WritePixels100_100_to_200_200_100_100)
|
||||
{
|
||||
WithRemoveFrameRectFilter(IntSize(100, 100),
|
||||
IntRect(200, 200, 100, 100),
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
// Note that aInputRect is zero-size because RemoveFrameRectFilter ignores
|
||||
// trailing rows that don't show up in the output. (Leading rows
|
||||
// unfortunately can't be ignored.)
|
||||
CheckWritePixels(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputWriteRect = */ Some(IntRect(0, 0, 0, 0)),
|
||||
/* aOutputWriteRect = */ Some(IntRect(0, 0, 0, 0)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageRemoveFrameRectFilter, WriteRows100_100_to_200_200_100_100)
|
||||
{
|
||||
WithRemoveFrameRectFilter(IntSize(100, 100),
|
||||
IntRect(200, 200, 100, 100),
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
// Note that aInputRect is zero-size because RemoveFrameRectFilter ignores
|
||||
// trailing rows that don't show up in the output. (Leading rows
|
||||
// unfortunately can't be ignored.)
|
||||
CheckWriteRows(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputWriteRect = */ Some(IntRect(0, 0, 0, 0)),
|
||||
/* aOutputWriteRect = */ Some(IntRect(0, 0, 0, 0)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageRemoveFrameRectFilter, WritePixels100_100_to_Minus200_25_100_100)
|
||||
{
|
||||
WithRemoveFrameRectFilter(IntSize(100, 100),
|
||||
IntRect(-200, 25, 100, 100),
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
// Note that aInputRect is zero-size because RemoveFrameRectFilter ignores
|
||||
// trailing rows that don't show up in the output. (Leading rows
|
||||
// unfortunately can't be ignored.)
|
||||
CheckWritePixels(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputWriteRect = */ Some(IntRect(0, 0, 0, 0)),
|
||||
/* aOutputWriteRect = */ Some(IntRect(0, 0, 0, 0)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageRemoveFrameRectFilter, WriteRows100_100_to_Minus200_25_100_100)
|
||||
{
|
||||
WithRemoveFrameRectFilter(IntSize(100, 100),
|
||||
IntRect(-200, 25, 100, 100),
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
// Note that aInputRect is zero-size because RemoveFrameRectFilter ignores
|
||||
// trailing rows that don't show up in the output. (Leading rows
|
||||
// unfortunately can't be ignored.)
|
||||
CheckWriteRows(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputWriteRect = */ Some(IntRect(0, 0, 0, 0)),
|
||||
/* aOutputWriteRect = */ Some(IntRect(0, 0, 0, 0)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageRemoveFrameRectFilter, WritePixels100_100_to_25_Minus200_100_100)
|
||||
{
|
||||
WithRemoveFrameRectFilter(IntSize(100, 100),
|
||||
IntRect(25, -200, 100, 100),
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
// Note that aInputRect is zero-size because RemoveFrameRectFilter ignores
|
||||
// trailing rows that don't show up in the output. (Leading rows
|
||||
// unfortunately can't be ignored.)
|
||||
CheckWritePixels(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputWriteRect = */ Some(IntRect(0, 0, 0, 0)),
|
||||
/* aOutputWriteRect = */ Some(IntRect(0, 0, 0, 0)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageRemoveFrameRectFilter, WriteRows100_100_to_25_Minus200_100_100)
|
||||
{
|
||||
WithRemoveFrameRectFilter(IntSize(100, 100),
|
||||
IntRect(25, -200, 100, 100),
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
// Note that aInputRect is zero-size because RemoveFrameRectFilter ignores
|
||||
// trailing rows that don't show up in the output. (Leading rows
|
||||
// unfortunately can't be ignored.)
|
||||
CheckWriteRows(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputWriteRect = */ Some(IntRect(0, 0, 0, 0)),
|
||||
/* aOutputWriteRect = */ Some(IntRect(0, 0, 0, 0)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageRemoveFrameRectFilter, WritePixels100_100_to_200_25_100_100)
|
||||
{
|
||||
WithRemoveFrameRectFilter(IntSize(100, 100),
|
||||
IntRect(200, 25, 100, 100),
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
// Note that aInputRect is zero-size because RemoveFrameRectFilter ignores
|
||||
// trailing rows that don't show up in the output. (Leading rows
|
||||
// unfortunately can't be ignored.)
|
||||
CheckWritePixels(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputWriteRect = */ Some(IntRect(0, 0, 0, 0)),
|
||||
/* aOutputWriteRect = */ Some(IntRect(0, 0, 0, 0)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageRemoveFrameRectFilter, WriteRows100_100_to_200_25_100_100)
|
||||
{
|
||||
WithRemoveFrameRectFilter(IntSize(100, 100),
|
||||
IntRect(200, 25, 100, 100),
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
// Note that aInputRect is zero-size because RemoveFrameRectFilter ignores
|
||||
// trailing rows that don't show up in the output. (Leading rows
|
||||
// unfortunately can't be ignored.)
|
||||
CheckWriteRows(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputWriteRect = */ Some(IntRect(0, 0, 0, 0)),
|
||||
/* aOutputWriteRect = */ Some(IntRect(0, 0, 0, 0)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageRemoveFrameRectFilter, WritePixels100_100_to_25_200_100_100)
|
||||
{
|
||||
WithRemoveFrameRectFilter(IntSize(100, 100),
|
||||
IntRect(25, 200, 100, 100),
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
// Note that aInputRect is zero-size because RemoveFrameRectFilter ignores
|
||||
// trailing rows that don't show up in the output. (Leading rows
|
||||
// unfortunately can't be ignored.)
|
||||
CheckWritePixels(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputWriteRect = */ Some(IntRect(0, 0, 0, 0)),
|
||||
/* aOutputWriteRect = */ Some(IntRect(0, 0, 0, 0)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageRemoveFrameRectFilter, WriteRows100_100_to_25_200_100_100)
|
||||
{
|
||||
WithRemoveFrameRectFilter(IntSize(100, 100),
|
||||
IntRect(25, 200, 100, 100),
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
// Note that aInputRect is zero-size because RemoveFrameRectFilter ignores
|
||||
// trailing rows that don't show up in the output. (Leading rows
|
||||
// unfortunately can't be ignored.)
|
||||
CheckWriteRows(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputWriteRect = */ Some(IntRect(0, 0, 0, 0)),
|
||||
/* aOutputWriteRect = */ Some(IntRect(0, 0, 0, 0)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageRemoveFrameRectFilter, WritePixels100_100_to_Minus200_Minus200_100_100)
|
||||
{
|
||||
WithRemoveFrameRectFilter(IntSize(100, 100),
|
||||
IntRect(-200, -200, 100, 100),
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckWritePixels(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputWriteRect = */ Some(IntRect(0, 0, 0, 0)),
|
||||
/* aOutputWriteRect = */ Some(IntRect(0, 0, 0, 0)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageRemoveFrameRectFilter, WriteRows100_100_to_Minus200_Minus200_100_100)
|
||||
{
|
||||
WithRemoveFrameRectFilter(IntSize(100, 100),
|
||||
IntRect(-200, -200, 100, 100),
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckWriteRows(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputWriteRect = */ Some(IntRect(0, 0, 0, 0)),
|
||||
/* aOutputWriteRect = */ Some(IntRect(0, 0, 0, 0)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageRemoveFrameRectFilter, WritePixels100_100_to_Minus50_Minus50_100_100)
|
||||
{
|
||||
WithRemoveFrameRectFilter(IntSize(100, 100),
|
||||
IntRect(-50, -50, 100, 100),
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckWritePixels(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputWriteRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aOutputWriteRect = */ Some(IntRect(0, 0, 50, 50)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageRemoveFrameRectFilter, WriteRows100_100_to_Minus50_Minus50_100_100)
|
||||
{
|
||||
WithRemoveFrameRectFilter(IntSize(100, 100),
|
||||
IntRect(-50, -50, 100, 100),
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckWriteRows(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputWriteRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aOutputWriteRect = */ Some(IntRect(0, 0, 50, 50)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageRemoveFrameRectFilter, WritePixels100_100_to_Minus50_25_100_50)
|
||||
{
|
||||
WithRemoveFrameRectFilter(IntSize(100, 100),
|
||||
IntRect(-50, 25, 100, 50),
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckWritePixels(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputWriteRect = */ Some(IntRect(0, 0, 100, 50)),
|
||||
/* aOutputWriteRect = */ Some(IntRect(0, 25, 50, 50)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageRemoveFrameRectFilter, WriteRows100_100_to_Minus50_25_100_50)
|
||||
{
|
||||
WithRemoveFrameRectFilter(IntSize(100, 100),
|
||||
IntRect(-50, 25, 100, 50),
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckWriteRows(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputWriteRect = */ Some(IntRect(0, 0, 100, 50)),
|
||||
/* aOutputWriteRect = */ Some(IntRect(0, 25, 50, 50)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageRemoveFrameRectFilter, WritePixels100_100_to_25_Minus50_50_100)
|
||||
{
|
||||
WithRemoveFrameRectFilter(IntSize(100, 100),
|
||||
IntRect(25, -50, 50, 100),
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckWritePixels(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputWriteRect = */ Some(IntRect(0, 0, 50, 100)),
|
||||
/* aOutputWriteRect = */ Some(IntRect(25, 0, 50, 50)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageRemoveFrameRectFilter, WriteRows100_100_to_25_Minus50_50_100)
|
||||
{
|
||||
WithRemoveFrameRectFilter(IntSize(100, 100),
|
||||
IntRect(25, -50, 50, 100),
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckWriteRows(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputWriteRect = */ Some(IntRect(0, 0, 50, 100)),
|
||||
/* aOutputWriteRect = */ Some(IntRect(25, 0, 50, 50)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageRemoveFrameRectFilter, WritePixels100_100_to_50_25_100_50)
|
||||
{
|
||||
WithRemoveFrameRectFilter(IntSize(100, 100),
|
||||
IntRect(50, 25, 100, 50),
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckWritePixels(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputWriteRect = */ Some(IntRect(0, 0, 100, 50)),
|
||||
/* aOutputWriteRect = */ Some(IntRect(50, 25, 50, 50)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageRemoveFrameRectFilter, WriteRows100_100_to_50_25_100_50)
|
||||
{
|
||||
WithRemoveFrameRectFilter(IntSize(100, 100),
|
||||
IntRect(50, 25, 100, 50),
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckWriteRows(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputWriteRect = */ Some(IntRect(0, 0, 100, 50)),
|
||||
/* aOutputWriteRect = */ Some(IntRect(50, 25, 50, 50)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageRemoveFrameRectFilter, WritePixels100_100_to_25_50_50_100)
|
||||
{
|
||||
WithRemoveFrameRectFilter(IntSize(100, 100),
|
||||
IntRect(25, 50, 50, 100),
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
// Note that aInputRect is 50x50 because RemoveFrameRectFilter ignores
|
||||
// trailing rows that don't show up in the output. (Leading rows
|
||||
// unfortunately can't be ignored.)
|
||||
CheckWritePixels(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputWriteRect = */ Some(IntRect(0, 0, 50, 50)),
|
||||
/* aOutputWriteRect = */ Some(IntRect(25, 50, 50, 100)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageRemoveFrameRectFilter, WriteRows100_100_to_25_50_50_100)
|
||||
{
|
||||
WithRemoveFrameRectFilter(IntSize(100, 100),
|
||||
IntRect(25, 50, 50, 100),
|
||||
[](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
// Note that aInputRect is 50x50 because RemoveFrameRectFilter ignores
|
||||
// trailing rows that don't show up in the output. (Leading rows
|
||||
// unfortunately can't be ignored.)
|
||||
CheckWriteRows(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputWriteRect = */ Some(IntRect(0, 0, 50, 50)),
|
||||
/* aOutputWriteRect = */ Some(IntRect(25, 50, 50, 100)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageRemoveFrameRectFilter, RemoveFrameRectFailsFor0_0_to_0_0_100_100)
|
||||
{
|
||||
// A zero-size image is disallowed.
|
||||
AssertConfiguringRemoveFrameRectFilterFails(IntSize(0, 0),
|
||||
IntRect(0, 0, 100, 100));
|
||||
}
|
||||
|
||||
TEST(ImageRemoveFrameRectFilter, RemoveFrameRectFailsForMinus1_Minus1_to_0_0_100_100)
|
||||
{
|
||||
// A negative-size image is disallowed.
|
||||
AssertConfiguringRemoveFrameRectFilterFails(IntSize(-1, -1),
|
||||
IntRect(0, 0, 100, 100));
|
||||
}
|
||||
|
||||
TEST(ImageRemoveFrameRectFilter, RemoveFrameRectFailsFor100_100_to_0_0_0_0)
|
||||
{
|
||||
// A zero size frame rect is disallowed.
|
||||
AssertConfiguringRemoveFrameRectFilterFails(IntSize(100, 100),
|
||||
IntRect(0, 0, -1, -1));
|
||||
}
|
||||
|
||||
TEST(ImageRemoveFrameRectFilter, RemoveFrameRectFailsFor100_100_to_0_0_Minus1_Minus1)
|
||||
{
|
||||
// A negative size frame rect is disallowed.
|
||||
AssertConfiguringRemoveFrameRectFilterFails(IntSize(100, 100),
|
||||
IntRect(0, 0, -1, -1));
|
||||
}
|
||||
|
||||
TEST(ImageRemoveFrameRectFilter, ConfiguringPalettedRemoveFrameRectFails)
|
||||
{
|
||||
RefPtr<Decoder> decoder = CreateTrivialDecoder();
|
||||
ASSERT_TRUE(decoder != nullptr);
|
||||
|
||||
// RemoveFrameRectFilter does not support paletted images, so configuration
|
||||
// should fail.
|
||||
AssertConfiguringPipelineFails(decoder,
|
||||
RemoveFrameRectConfig { IntRect(0, 0, 50, 50) },
|
||||
PalettedSurfaceConfig { decoder, 0, IntSize(100, 100),
|
||||
IntRect(0, 0, 50, 50),
|
||||
SurfaceFormat::B8G8R8A8, 8,
|
||||
false });
|
||||
}
|
322
image/test/gtest/TestSurfacePipeIntegration.cpp
Normal file
322
image/test/gtest/TestSurfacePipeIntegration.cpp
Normal file
@ -0,0 +1,322 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "Common.h"
|
||||
#include "Decoder.h"
|
||||
#include "DecoderFactory.h"
|
||||
#include "SourceBuffer.h"
|
||||
#include "SurfacePipe.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::gfx;
|
||||
using namespace mozilla::image;
|
||||
|
||||
namespace mozilla {
|
||||
namespace image {
|
||||
|
||||
class TestSurfacePipeFactory
|
||||
{
|
||||
public:
|
||||
static SurfacePipe SimpleSurfacePipe()
|
||||
{
|
||||
SurfacePipe pipe;
|
||||
return Move(pipe);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static SurfacePipe SurfacePipeFromPipeline(T&& aPipeline)
|
||||
{
|
||||
return SurfacePipe { Move(aPipeline) };
|
||||
}
|
||||
|
||||
private:
|
||||
TestSurfacePipeFactory() { }
|
||||
};
|
||||
|
||||
} // namespace image
|
||||
} // namespace mozilla
|
||||
|
||||
TEST(ImageSurfacePipeIntegration, SurfacePipe)
|
||||
{
|
||||
// Test that SurfacePipe objects can be initialized and move constructed.
|
||||
SurfacePipe pipe = TestSurfacePipeFactory::SimpleSurfacePipe();
|
||||
|
||||
// Test that SurfacePipe objects can be move assigned.
|
||||
pipe = TestSurfacePipeFactory::SimpleSurfacePipe();
|
||||
|
||||
// Test that SurfacePipe objects can be initialized with a pipeline.
|
||||
RefPtr<Decoder> decoder = CreateTrivialDecoder();
|
||||
ASSERT_TRUE(decoder != nullptr);
|
||||
|
||||
auto sink = MakeUnique<SurfaceSink>();
|
||||
nsresult rv =
|
||||
sink->Configure(SurfaceConfig { decoder.get(), 0, IntSize(100, 100),
|
||||
SurfaceFormat::B8G8R8A8, false });
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
|
||||
pipe = TestSurfacePipeFactory::SurfacePipeFromPipeline(sink);
|
||||
|
||||
// Test that SurfacePipe passes through method calls to the underlying pipeline.
|
||||
int32_t count = 0;
|
||||
auto result = pipe.WritePixels<uint32_t>([&]() {
|
||||
++count;
|
||||
return AsVariant(BGRAColor::Green().AsPixel());
|
||||
});
|
||||
EXPECT_EQ(WriteState::FINISHED, result);
|
||||
EXPECT_EQ(100 * 100, count);
|
||||
|
||||
// Note that we're explicitly testing the SurfacePipe versions of these
|
||||
// methods, so we don't want to use AssertCorrectPipelineFinalState() here.
|
||||
EXPECT_TRUE(pipe.IsSurfaceFinished());
|
||||
Maybe<SurfaceInvalidRect> invalidRect = pipe.TakeInvalidRect();
|
||||
EXPECT_TRUE(invalidRect.isSome());
|
||||
EXPECT_EQ(IntRect(0, 0, 100, 100), invalidRect->mInputSpaceRect);
|
||||
EXPECT_EQ(IntRect(0, 0, 100, 100), invalidRect->mOutputSpaceRect);
|
||||
|
||||
CheckGeneratedImage(decoder, IntRect(0, 0, 100, 100));
|
||||
|
||||
pipe.ResetToFirstRow();
|
||||
EXPECT_FALSE(pipe.IsSurfaceFinished());
|
||||
|
||||
RawAccessFrameRef currentFrame = decoder->GetCurrentFrameRef();
|
||||
currentFrame->Finish();
|
||||
}
|
||||
|
||||
TEST(ImageSurfacePipeIntegration, DeinterlaceDownscaleWritePixels)
|
||||
{
|
||||
RefPtr<Decoder> decoder = CreateTrivialDecoder();
|
||||
ASSERT_TRUE(decoder != nullptr);
|
||||
|
||||
auto test = [](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckWritePixels(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 25, 25)));
|
||||
};
|
||||
|
||||
WithFilterPipeline(decoder, test,
|
||||
DeinterlacingConfig<uint32_t> { /* mProgressiveDisplay = */ true },
|
||||
DownscalingConfig { IntSize(100, 100),
|
||||
SurfaceFormat::B8G8R8A8 },
|
||||
SurfaceConfig { decoder, 0, IntSize(25, 25),
|
||||
SurfaceFormat::B8G8R8A8, false });
|
||||
}
|
||||
|
||||
TEST(ImageSurfacePipeIntegration, DeinterlaceDownscaleWriteRows)
|
||||
{
|
||||
RefPtr<Decoder> decoder = CreateTrivialDecoder();
|
||||
ASSERT_TRUE(decoder != nullptr);
|
||||
|
||||
auto test = [](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckWriteRows(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 25, 25)));
|
||||
};
|
||||
|
||||
WithFilterPipeline(decoder, test,
|
||||
DeinterlacingConfig<uint32_t> { /* mProgressiveDisplay = */ true },
|
||||
DownscalingConfig { IntSize(100, 100),
|
||||
SurfaceFormat::B8G8R8A8 },
|
||||
SurfaceConfig { decoder, 0, IntSize(25, 25),
|
||||
SurfaceFormat::B8G8R8A8, false });
|
||||
}
|
||||
|
||||
TEST(ImageSurfacePipeIntegration, RemoveFrameRectDownscaleWritePixels)
|
||||
{
|
||||
RefPtr<Decoder> decoder = CreateTrivialDecoder();
|
||||
ASSERT_TRUE(decoder != nullptr);
|
||||
|
||||
// Note that aInputWriteRect is 100x50 because RemoveFrameRectFilter ignores
|
||||
// trailing rows that don't show up in the output. (Leading rows unfortunately
|
||||
// can't be ignored.) So the action of the pipeline is as follows:
|
||||
//
|
||||
// (1) RemoveFrameRectFilter reads a 100x50 region of the input.
|
||||
// (aInputWriteRect captures this fact.) The remaining 50 rows are ignored
|
||||
// because they extend off the bottom of the image due to the frame rect's
|
||||
// (50, 50) offset. The 50 columns on the right also don't end up in the
|
||||
// output, so ultimately only a 50x50 region in the output contains data
|
||||
// from the input. The filter's output is not 50x50, though, but 100x100,
|
||||
// because what RemoveFrameRectFilter does is introduce blank rows or
|
||||
// columns as necessary to transform an image that needs a frame rect into
|
||||
// an image that doesn't.
|
||||
//
|
||||
// (2) DownscalingFilter reads the output of RemoveFrameRectFilter (100x100)
|
||||
// and downscales it to 20x20.
|
||||
//
|
||||
// (3) The surface owned by SurfaceSink logically has only a 10x10 region
|
||||
// region in it that's non-blank; this is the downscaled version of the
|
||||
// 50x50 region discussed in (1). (aOutputWriteRect captures this fact.)
|
||||
// Some fuzz, as usual, is necessary when dealing with Lanczos downscaling.
|
||||
|
||||
auto test = [](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckWritePixels(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 20, 20)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputWriteRect = */ Some(IntRect(50, 50, 100, 50)),
|
||||
/* aOutputWriteRect = */ Some(IntRect(10, 10, 10, 10)),
|
||||
/* aFuzz = */ 0x33);
|
||||
};
|
||||
|
||||
WithFilterPipeline(decoder, test,
|
||||
RemoveFrameRectConfig { IntRect(50, 50, 100, 100) },
|
||||
DownscalingConfig { IntSize(100, 100),
|
||||
SurfaceFormat::B8G8R8A8 },
|
||||
SurfaceConfig { decoder, 0, IntSize(20, 20),
|
||||
SurfaceFormat::B8G8R8A8, false });
|
||||
}
|
||||
|
||||
TEST(ImageSurfacePipeIntegration, RemoveFrameRectDownscaleWriteRows)
|
||||
{
|
||||
RefPtr<Decoder> decoder = CreateTrivialDecoder();
|
||||
ASSERT_TRUE(decoder != nullptr);
|
||||
|
||||
// See the WritePixels version of this test for a discussion of where the
|
||||
// numbers below come from.
|
||||
|
||||
auto test = [](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckWriteRows(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 20, 20)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputWriteRect = */ Some(IntRect(50, 50, 100, 50)),
|
||||
/* aOutputWriteRect = */ Some(IntRect(10, 10, 10, 10)),
|
||||
/* aFuzz = */ 0x33);
|
||||
};
|
||||
|
||||
WithFilterPipeline(decoder, test,
|
||||
RemoveFrameRectConfig { IntRect(50, 50, 100, 100) },
|
||||
DownscalingConfig { IntSize(100, 100),
|
||||
SurfaceFormat::B8G8R8A8 },
|
||||
SurfaceConfig { decoder, 0, IntSize(20, 20),
|
||||
SurfaceFormat::B8G8R8A8, false });
|
||||
}
|
||||
|
||||
TEST(ImageSurfacePipeIntegration, DeinterlaceRemoveFrameRectWritePixels)
|
||||
{
|
||||
RefPtr<Decoder> decoder = CreateTrivialDecoder();
|
||||
ASSERT_TRUE(decoder != nullptr);
|
||||
|
||||
// Note that aInputRect is the full 100x100 size even though
|
||||
// RemoveFrameRectFilter is part of this pipeline, because deinterlacing
|
||||
// requires reading every row.
|
||||
|
||||
auto test = [](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckWritePixels(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputWriteRect = */ Some(IntRect(50, 50, 100, 100)),
|
||||
/* aOutputWriteRect = */ Some(IntRect(50, 50, 50, 50)));
|
||||
};
|
||||
|
||||
WithFilterPipeline(decoder, test,
|
||||
DeinterlacingConfig<uint32_t> { /* mProgressiveDisplay = */ true },
|
||||
RemoveFrameRectConfig { IntRect(50, 50, 100, 100) },
|
||||
SurfaceConfig { decoder, 0, IntSize(100, 100),
|
||||
SurfaceFormat::B8G8R8A8, false });
|
||||
}
|
||||
|
||||
TEST(ImageSurfacePipeIntegration, DeinterlaceRemoveFrameRectWriteRows)
|
||||
{
|
||||
RefPtr<Decoder> decoder = CreateTrivialDecoder();
|
||||
ASSERT_TRUE(decoder != nullptr);
|
||||
|
||||
// Note that aInputRect is the full 100x100 size even though
|
||||
// RemoveFrameRectFilter is part of this pipeline, because deinterlacing
|
||||
// requires reading every row.
|
||||
|
||||
auto test = [](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckWriteRows(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputWriteRect = */ Some(IntRect(50, 50, 100, 100)),
|
||||
/* aOutputWriteRect = */ Some(IntRect(50, 50, 50, 50)));
|
||||
};
|
||||
|
||||
WithFilterPipeline(decoder, test,
|
||||
DeinterlacingConfig<uint32_t> { /* mProgressiveDisplay = */ true },
|
||||
RemoveFrameRectConfig { IntRect(50, 50, 100, 100) },
|
||||
SurfaceConfig { decoder, 0, IntSize(100, 100),
|
||||
SurfaceFormat::B8G8R8A8, false });
|
||||
}
|
||||
|
||||
TEST(ImageSurfacePipeIntegration, DeinterlaceRemoveFrameRectDownscaleWritePixels)
|
||||
{
|
||||
RefPtr<Decoder> decoder = CreateTrivialDecoder();
|
||||
ASSERT_TRUE(decoder != nullptr);
|
||||
|
||||
auto test = [](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckWritePixels(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 20, 20)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputWriteRect = */ Some(IntRect(50, 50, 100, 100)),
|
||||
/* aOutputWriteRect = */ Some(IntRect(10, 10, 10, 10)),
|
||||
/* aFuzz = */ 33);
|
||||
};
|
||||
|
||||
WithFilterPipeline(decoder, test,
|
||||
DeinterlacingConfig<uint32_t> { /* mProgressiveDisplay = */ true },
|
||||
RemoveFrameRectConfig { IntRect(50, 50, 100, 100) },
|
||||
DownscalingConfig { IntSize(100, 100),
|
||||
SurfaceFormat::B8G8R8A8 },
|
||||
SurfaceConfig { decoder, 0, IntSize(20, 20),
|
||||
SurfaceFormat::B8G8R8A8, false });
|
||||
}
|
||||
|
||||
TEST(ImageSurfacePipeIntegration, DeinterlaceRemoveFrameRectDownscaleWriteRows)
|
||||
{
|
||||
RefPtr<Decoder> decoder = CreateTrivialDecoder();
|
||||
ASSERT_TRUE(decoder != nullptr);
|
||||
|
||||
auto test = [](Decoder* aDecoder, SurfaceFilter* aFilter) {
|
||||
CheckWriteRows(aDecoder, aFilter,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 20, 20)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 100, 100)),
|
||||
/* aInputWriteRect = */ Some(IntRect(50, 50, 100, 100)),
|
||||
/* aOutputWriteRect = */ Some(IntRect(10, 10, 10, 10)),
|
||||
/* aFuzz = */ 33);
|
||||
};
|
||||
|
||||
WithFilterPipeline(decoder, test,
|
||||
DeinterlacingConfig<uint32_t> { /* mProgressiveDisplay = */ true },
|
||||
RemoveFrameRectConfig { IntRect(50, 50, 100, 100) },
|
||||
DownscalingConfig { IntSize(100, 100),
|
||||
SurfaceFormat::B8G8R8A8 },
|
||||
SurfaceConfig { decoder, 0, IntSize(20, 20),
|
||||
SurfaceFormat::B8G8R8A8, false });
|
||||
}
|
||||
|
||||
TEST(ImageSurfacePipeIntegration, ConfiguringPalettedRemoveFrameRectDownscaleFails)
|
||||
{
|
||||
RefPtr<Decoder> decoder = CreateTrivialDecoder();
|
||||
ASSERT_TRUE(decoder != nullptr);
|
||||
|
||||
// This is an invalid pipeline for paletted images, so configuration should
|
||||
// fail.
|
||||
AssertConfiguringPipelineFails(decoder,
|
||||
RemoveFrameRectConfig { IntRect(0, 0, 50, 50) },
|
||||
DownscalingConfig { IntSize(100, 100),
|
||||
SurfaceFormat::B8G8R8A8 },
|
||||
PalettedSurfaceConfig { decoder, 0, IntSize(100, 100),
|
||||
IntRect(0, 0, 50, 50),
|
||||
SurfaceFormat::B8G8R8A8, 8,
|
||||
false });
|
||||
}
|
||||
|
||||
TEST(ImageSurfacePipeIntegration, ConfiguringPalettedDeinterlaceDownscaleFails)
|
||||
{
|
||||
RefPtr<Decoder> decoder = CreateTrivialDecoder();
|
||||
ASSERT_TRUE(decoder != nullptr);
|
||||
|
||||
// This is an invalid pipeline for paletted images, so configuration should
|
||||
// fail.
|
||||
AssertConfiguringPipelineFails(decoder,
|
||||
DeinterlacingConfig<uint8_t> { /* mProgressiveDisplay = */ true},
|
||||
DownscalingConfig { IntSize(100, 100),
|
||||
SurfaceFormat::B8G8R8A8 },
|
||||
PalettedSurfaceConfig { decoder, 0, IntSize(100, 100),
|
||||
IntRect(0, 0, 20, 20),
|
||||
SurfaceFormat::B8G8R8A8, 8,
|
||||
false });
|
||||
}
|
578
image/test/gtest/TestSurfaceSink.cpp
Normal file
578
image/test/gtest/TestSurfaceSink.cpp
Normal file
@ -0,0 +1,578 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "Common.h"
|
||||
#include "Decoder.h"
|
||||
#include "DecoderFactory.h"
|
||||
#include "SourceBuffer.h"
|
||||
#include "SurfacePipe.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::gfx;
|
||||
using namespace mozilla::image;
|
||||
|
||||
enum class Orient
|
||||
{
|
||||
NORMAL,
|
||||
FLIP_VERTICALLY
|
||||
};
|
||||
|
||||
template <Orient Orientation, typename Func> void
|
||||
WithSurfaceSink(Func aFunc)
|
||||
{
|
||||
RefPtr<Decoder> decoder = CreateTrivialDecoder();
|
||||
ASSERT_TRUE(decoder != nullptr);
|
||||
|
||||
const bool flipVertically = Orientation == Orient::FLIP_VERTICALLY;
|
||||
|
||||
WithFilterPipeline(decoder, Forward<Func>(aFunc),
|
||||
SurfaceConfig { decoder, 0, IntSize(100, 100),
|
||||
SurfaceFormat::B8G8R8A8, flipVertically });
|
||||
}
|
||||
|
||||
template <typename Func> void
|
||||
WithPalettedSurfaceSink(const IntRect& aFrameRect, Func aFunc)
|
||||
{
|
||||
RefPtr<Decoder> decoder = CreateTrivialDecoder();
|
||||
ASSERT_TRUE(decoder != nullptr);
|
||||
|
||||
WithFilterPipeline(decoder, Forward<Func>(aFunc),
|
||||
PalettedSurfaceConfig { decoder, 0, IntSize(100, 100),
|
||||
aFrameRect, SurfaceFormat::B8G8R8A8,
|
||||
8, false });
|
||||
}
|
||||
|
||||
TEST(ImageSurfaceSink, NullSurfaceSink)
|
||||
{
|
||||
// Create the NullSurfaceSink.
|
||||
NullSurfaceSink sink;
|
||||
nsresult rv = sink.Configure(NullSurfaceConfig { });
|
||||
ASSERT_TRUE(NS_SUCCEEDED(rv));
|
||||
EXPECT_TRUE(!sink.IsValidPalettedPipe());
|
||||
|
||||
// Ensure that we can't write anything.
|
||||
bool gotCalled = false;
|
||||
auto result = sink.WritePixels<uint32_t>([&]() {
|
||||
gotCalled = true;
|
||||
return AsVariant(BGRAColor::Green().AsPixel());
|
||||
});
|
||||
EXPECT_FALSE(gotCalled);
|
||||
EXPECT_EQ(WriteState::FINISHED, result);
|
||||
EXPECT_TRUE(sink.IsSurfaceFinished());
|
||||
Maybe<SurfaceInvalidRect> invalidRect = sink.TakeInvalidRect();
|
||||
EXPECT_TRUE(invalidRect.isNothing());
|
||||
|
||||
result = sink.WriteRows<uint32_t>([&](uint32_t* aRow, uint32_t aLength) {
|
||||
gotCalled = true;
|
||||
for (; aLength > 0; --aLength, ++aRow) {
|
||||
*aRow = BGRAColor::Green().AsPixel();
|
||||
}
|
||||
return Nothing();
|
||||
});
|
||||
EXPECT_FALSE(gotCalled);
|
||||
EXPECT_EQ(WriteState::FINISHED, result);
|
||||
EXPECT_TRUE(sink.IsSurfaceFinished());
|
||||
invalidRect = sink.TakeInvalidRect();
|
||||
EXPECT_TRUE(invalidRect.isNothing());
|
||||
|
||||
// Attempt to advance to the next row and make sure nothing changes.
|
||||
sink.AdvanceRow();
|
||||
EXPECT_TRUE(sink.IsSurfaceFinished());
|
||||
invalidRect = sink.TakeInvalidRect();
|
||||
EXPECT_TRUE(invalidRect.isNothing());
|
||||
|
||||
// Attempt to advance to the next pass and make sure nothing changes.
|
||||
sink.ResetToFirstRow();
|
||||
EXPECT_TRUE(sink.IsSurfaceFinished());
|
||||
invalidRect = sink.TakeInvalidRect();
|
||||
EXPECT_TRUE(invalidRect.isNothing());
|
||||
}
|
||||
|
||||
TEST(ImageSurfaceSink, SurfaceSinkWritePixels)
|
||||
{
|
||||
WithSurfaceSink<Orient::NORMAL>([](Decoder* aDecoder, SurfaceSink* aSink) {
|
||||
CheckWritePixels(aDecoder, aSink);
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageSurfaceSink, SurfaceSinkWriteRows)
|
||||
{
|
||||
WithSurfaceSink<Orient::NORMAL>([](Decoder* aDecoder, SurfaceSink* aSink) {
|
||||
CheckWriteRows(aDecoder, aSink);
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageSurfaceSink, SurfaceSinkWritePixelsFinish)
|
||||
{
|
||||
WithSurfaceSink<Orient::NORMAL>([](Decoder* aDecoder, SurfaceSink* aSink) {
|
||||
// Write nothing into the surface; just finish immediately.
|
||||
uint32_t count = 0;
|
||||
auto result = aSink->WritePixels<uint32_t>([&]() {
|
||||
count++;
|
||||
return AsVariant(WriteState::FINISHED);
|
||||
});
|
||||
EXPECT_EQ(WriteState::FINISHED, result);
|
||||
EXPECT_EQ(1u, count);
|
||||
EXPECT_TRUE(aSink->IsSurfaceFinished());
|
||||
|
||||
// Attempt to write more and make sure that nothing gets written.
|
||||
count = 0;
|
||||
result = aSink->WritePixels<uint32_t>([&]() {
|
||||
count++;
|
||||
return AsVariant(BGRAColor::Red().AsPixel());
|
||||
});
|
||||
EXPECT_EQ(WriteState::FINISHED, result);
|
||||
EXPECT_EQ(0u, count);
|
||||
EXPECT_TRUE(aSink->IsSurfaceFinished());
|
||||
|
||||
// Check that the generated image is correct.
|
||||
RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef();
|
||||
RefPtr<SourceSurface> surface = currentFrame->GetSurface();
|
||||
EXPECT_TRUE(IsSolidColor(surface, BGRAColor::Transparent()));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageSurfaceSink, SurfaceSinkWriteRowsFinish)
|
||||
{
|
||||
WithSurfaceSink<Orient::NORMAL>([](Decoder* aDecoder, SurfaceSink* aSink) {
|
||||
// Write nothing into the surface; just finish immediately.
|
||||
uint32_t count = 0;
|
||||
auto result = aSink->WriteRows<uint32_t>([&](uint32_t* aRow, uint32_t aLength) {
|
||||
count++;
|
||||
return Some(WriteState::FINISHED);
|
||||
});
|
||||
EXPECT_EQ(WriteState::FINISHED, result);
|
||||
EXPECT_EQ(1u, count);
|
||||
EXPECT_TRUE(aSink->IsSurfaceFinished());
|
||||
|
||||
// Attempt to write more and make sure that nothing gets written.
|
||||
count = 0;
|
||||
result = aSink->WriteRows<uint32_t>([&](uint32_t* aRow, uint32_t aLength) {
|
||||
count++;
|
||||
for (; aLength > 0; --aLength, ++aRow) {
|
||||
*aRow = BGRAColor::Green().AsPixel();
|
||||
}
|
||||
return Nothing();
|
||||
});
|
||||
EXPECT_EQ(WriteState::FINISHED, result);
|
||||
EXPECT_EQ(0u, count);
|
||||
EXPECT_TRUE(aSink->IsSurfaceFinished());
|
||||
|
||||
// Check that the generated image is correct.
|
||||
RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef();
|
||||
RefPtr<SourceSurface> surface = currentFrame->GetSurface();
|
||||
EXPECT_TRUE(IsSolidColor(surface, BGRAColor::Transparent()));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageSurfaceSink, SurfaceSinkProgressivePasses)
|
||||
{
|
||||
WithSurfaceSink<Orient::NORMAL>([](Decoder* aDecoder, SurfaceSink* aSink) {
|
||||
{
|
||||
// Fill the image with a first pass of red.
|
||||
uint32_t count = 0;
|
||||
auto result = aSink->WritePixels<uint32_t>([&]() {
|
||||
++count;
|
||||
return AsVariant(BGRAColor::Red().AsPixel());
|
||||
});
|
||||
EXPECT_EQ(WriteState::FINISHED, result);
|
||||
EXPECT_EQ(100u * 100u, count);
|
||||
|
||||
AssertCorrectPipelineFinalState(aSink,
|
||||
IntRect(0, 0, 100, 100),
|
||||
IntRect(0, 0, 100, 100));
|
||||
|
||||
// Check that the generated image is correct.
|
||||
RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef();
|
||||
RefPtr<SourceSurface> surface = currentFrame->GetSurface();
|
||||
EXPECT_TRUE(IsSolidColor(surface, BGRAColor::Red()));
|
||||
}
|
||||
|
||||
{
|
||||
// Reset for the second pass.
|
||||
aSink->ResetToFirstRow();
|
||||
EXPECT_FALSE(aSink->IsSurfaceFinished());
|
||||
Maybe<SurfaceInvalidRect> invalidRect = aSink->TakeInvalidRect();
|
||||
EXPECT_TRUE(invalidRect.isNothing());
|
||||
|
||||
// Check that the generated image is still the first pass image.
|
||||
RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef();
|
||||
RefPtr<SourceSurface> surface = currentFrame->GetSurface();
|
||||
EXPECT_TRUE(IsSolidColor(surface, BGRAColor::Red()));
|
||||
}
|
||||
|
||||
{
|
||||
// Fill the image with a second pass of green.
|
||||
uint32_t count = 0;
|
||||
auto result = aSink->WritePixels<uint32_t>([&]() {
|
||||
++count;
|
||||
return AsVariant(BGRAColor::Green().AsPixel());
|
||||
});
|
||||
EXPECT_EQ(WriteState::FINISHED, result);
|
||||
EXPECT_EQ(100u * 100u, count);
|
||||
|
||||
AssertCorrectPipelineFinalState(aSink,
|
||||
IntRect(0, 0, 100, 100),
|
||||
IntRect(0, 0, 100, 100));
|
||||
|
||||
// Check that the generated image is correct.
|
||||
RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef();
|
||||
RefPtr<SourceSurface> surface = currentFrame->GetSurface();
|
||||
EXPECT_TRUE(IsSolidColor(surface, BGRAColor::Green()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageSurfaceSink, SurfaceSinkInvalidRect)
|
||||
{
|
||||
WithSurfaceSink<Orient::NORMAL>([](Decoder* aDecoder, SurfaceSink* aSink) {
|
||||
{
|
||||
// Write one row.
|
||||
uint32_t count = 0;
|
||||
auto result = aSink->WritePixels<uint32_t>([&]() -> NextPixel<uint32_t> {
|
||||
if (count == 100) {
|
||||
return AsVariant(WriteState::NEED_MORE_DATA);
|
||||
}
|
||||
count++;
|
||||
return AsVariant(BGRAColor::Green().AsPixel());
|
||||
});
|
||||
EXPECT_EQ(WriteState::NEED_MORE_DATA, result);
|
||||
EXPECT_EQ(100u, count);
|
||||
EXPECT_FALSE(aSink->IsSurfaceFinished());
|
||||
|
||||
// Assert that we have the right invalid rect.
|
||||
Maybe<SurfaceInvalidRect> invalidRect = aSink->TakeInvalidRect();
|
||||
EXPECT_TRUE(invalidRect.isSome());
|
||||
EXPECT_EQ(IntRect(0, 0, 100, 1), invalidRect->mInputSpaceRect);
|
||||
EXPECT_EQ(IntRect(0, 0, 100, 1), invalidRect->mOutputSpaceRect);
|
||||
}
|
||||
|
||||
{
|
||||
// Write eight rows.
|
||||
uint32_t count = 0;
|
||||
auto result = aSink->WritePixels<uint32_t>([&]() -> NextPixel<uint32_t> {
|
||||
if (count == 100 * 8) {
|
||||
return AsVariant(WriteState::NEED_MORE_DATA);
|
||||
}
|
||||
count++;
|
||||
return AsVariant(BGRAColor::Green().AsPixel());
|
||||
});
|
||||
EXPECT_EQ(WriteState::NEED_MORE_DATA, result);
|
||||
EXPECT_EQ(100u * 8u, count);
|
||||
EXPECT_FALSE(aSink->IsSurfaceFinished());
|
||||
|
||||
// Assert that we have the right invalid rect.
|
||||
Maybe<SurfaceInvalidRect> invalidRect = aSink->TakeInvalidRect();
|
||||
EXPECT_TRUE(invalidRect.isSome());
|
||||
EXPECT_EQ(IntRect(0, 1, 100, 8), invalidRect->mInputSpaceRect);
|
||||
EXPECT_EQ(IntRect(0, 1, 100, 8), invalidRect->mOutputSpaceRect);
|
||||
}
|
||||
|
||||
{
|
||||
// Write the left half of one row.
|
||||
uint32_t count = 0;
|
||||
auto result = aSink->WritePixels<uint32_t>([&]() -> NextPixel<uint32_t> {
|
||||
if (count == 50) {
|
||||
return AsVariant(WriteState::NEED_MORE_DATA);
|
||||
}
|
||||
count++;
|
||||
return AsVariant(BGRAColor::Green().AsPixel());
|
||||
});
|
||||
EXPECT_EQ(WriteState::NEED_MORE_DATA, result);
|
||||
EXPECT_EQ(50u, count);
|
||||
EXPECT_FALSE(aSink->IsSurfaceFinished());
|
||||
|
||||
// Assert that we don't have an invalid rect, since the invalid rect only
|
||||
// gets updated when a row gets completed.
|
||||
Maybe<SurfaceInvalidRect> invalidRect = aSink->TakeInvalidRect();
|
||||
EXPECT_TRUE(invalidRect.isNothing());
|
||||
}
|
||||
|
||||
{
|
||||
// Write the right half of the same row.
|
||||
uint32_t count = 0;
|
||||
auto result = aSink->WritePixels<uint32_t>([&]() -> NextPixel<uint32_t> {
|
||||
if (count == 50) {
|
||||
return AsVariant(WriteState::NEED_MORE_DATA);
|
||||
}
|
||||
count++;
|
||||
return AsVariant(BGRAColor::Green().AsPixel());
|
||||
});
|
||||
EXPECT_EQ(WriteState::NEED_MORE_DATA, result);
|
||||
EXPECT_EQ(50u, count);
|
||||
EXPECT_FALSE(aSink->IsSurfaceFinished());
|
||||
|
||||
// Assert that we have the right invalid rect, which will include both the
|
||||
// left and right halves of this row now that we've completed it.
|
||||
Maybe<SurfaceInvalidRect> invalidRect = aSink->TakeInvalidRect();
|
||||
EXPECT_TRUE(invalidRect.isSome());
|
||||
EXPECT_EQ(IntRect(0, 9, 100, 1), invalidRect->mInputSpaceRect);
|
||||
EXPECT_EQ(IntRect(0, 9, 100, 1), invalidRect->mOutputSpaceRect);
|
||||
}
|
||||
|
||||
{
|
||||
// Write no rows.
|
||||
auto result = aSink->WritePixels<uint32_t>([&]() {
|
||||
return AsVariant(WriteState::NEED_MORE_DATA);
|
||||
});
|
||||
EXPECT_EQ(WriteState::NEED_MORE_DATA, result);
|
||||
EXPECT_FALSE(aSink->IsSurfaceFinished());
|
||||
|
||||
// Assert that we don't have an invalid rect.
|
||||
Maybe<SurfaceInvalidRect> invalidRect = aSink->TakeInvalidRect();
|
||||
EXPECT_TRUE(invalidRect.isNothing());
|
||||
}
|
||||
|
||||
{
|
||||
// Fill the rest of the image.
|
||||
uint32_t count = 0;
|
||||
auto result = aSink->WritePixels<uint32_t>([&]() {
|
||||
count++;
|
||||
return AsVariant(BGRAColor::Green().AsPixel());
|
||||
});
|
||||
EXPECT_EQ(WriteState::FINISHED, result);
|
||||
EXPECT_EQ(100u * 90u, count);
|
||||
EXPECT_TRUE(aSink->IsSurfaceFinished());
|
||||
|
||||
// Assert that we have the right invalid rect.
|
||||
Maybe<SurfaceInvalidRect> invalidRect = aSink->TakeInvalidRect();
|
||||
EXPECT_TRUE(invalidRect.isSome());
|
||||
EXPECT_EQ(IntRect(0, 10, 100, 90), invalidRect->mInputSpaceRect);
|
||||
EXPECT_EQ(IntRect(0, 10, 100, 90), invalidRect->mOutputSpaceRect);
|
||||
|
||||
// Check that the generated image is correct.
|
||||
RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef();
|
||||
RefPtr<SourceSurface> surface = currentFrame->GetSurface();
|
||||
EXPECT_TRUE(IsSolidColor(surface, BGRAColor::Green()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageSurfaceSink, SurfaceSinkFlipVertically)
|
||||
{
|
||||
WithSurfaceSink<Orient::FLIP_VERTICALLY>([](Decoder* aDecoder,
|
||||
SurfaceSink* aSink) {
|
||||
{
|
||||
// Fill the image with a first pass of red.
|
||||
uint32_t count = 0;
|
||||
auto result = aSink->WritePixels<uint32_t>([&]() {
|
||||
++count;
|
||||
return AsVariant(BGRAColor::Red().AsPixel());
|
||||
});
|
||||
EXPECT_EQ(WriteState::FINISHED, result);
|
||||
EXPECT_EQ(100u * 100u, count);
|
||||
|
||||
AssertCorrectPipelineFinalState(aSink,
|
||||
IntRect(0, 0, 100, 100),
|
||||
IntRect(0, 0, 100, 100));
|
||||
|
||||
// Check that the generated image is correct.
|
||||
RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef();
|
||||
RefPtr<SourceSurface> surface = currentFrame->GetSurface();
|
||||
EXPECT_TRUE(IsSolidColor(surface, BGRAColor::Red()));
|
||||
}
|
||||
|
||||
{
|
||||
// Reset for the second pass.
|
||||
aSink->ResetToFirstRow();
|
||||
EXPECT_FALSE(aSink->IsSurfaceFinished());
|
||||
Maybe<SurfaceInvalidRect> invalidRect = aSink->TakeInvalidRect();
|
||||
EXPECT_TRUE(invalidRect.isNothing());
|
||||
|
||||
// Check that the generated image is still the first pass image.
|
||||
RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef();
|
||||
RefPtr<SourceSurface> surface = currentFrame->GetSurface();
|
||||
EXPECT_TRUE(IsSolidColor(surface, BGRAColor::Red()));
|
||||
}
|
||||
|
||||
{
|
||||
// Fill 25 rows of the image with green and make sure everything is OK.
|
||||
uint32_t count = 0;
|
||||
auto result = aSink->WritePixels<uint32_t>([&]() -> NextPixel<uint32_t> {
|
||||
if (count == 25 * 100) {
|
||||
return AsVariant(WriteState::NEED_MORE_DATA);
|
||||
}
|
||||
count++;
|
||||
return AsVariant(BGRAColor::Green().AsPixel());
|
||||
});
|
||||
EXPECT_EQ(WriteState::NEED_MORE_DATA, result);
|
||||
EXPECT_EQ(25u * 100u, count);
|
||||
EXPECT_FALSE(aSink->IsSurfaceFinished());
|
||||
|
||||
// Assert that we have the right invalid rect, which should include the
|
||||
// *bottom* (since we're flipping vertically) 25 rows of the image.
|
||||
Maybe<SurfaceInvalidRect> invalidRect = aSink->TakeInvalidRect();
|
||||
EXPECT_TRUE(invalidRect.isSome());
|
||||
EXPECT_EQ(IntRect(0, 75, 100, 25), invalidRect->mInputSpaceRect);
|
||||
EXPECT_EQ(IntRect(0, 75, 100, 25), invalidRect->mOutputSpaceRect);
|
||||
|
||||
// Check that the generated image is correct.
|
||||
RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef();
|
||||
RefPtr<SourceSurface> surface = currentFrame->GetSurface();
|
||||
EXPECT_TRUE(RowsAreSolidColor(surface, 0, 75, BGRAColor::Red()));
|
||||
EXPECT_TRUE(RowsAreSolidColor(surface, 75, 25, BGRAColor::Green()));
|
||||
}
|
||||
|
||||
{
|
||||
// Fill the rest of the image with a second pass of green.
|
||||
uint32_t count = 0;
|
||||
auto result = aSink->WritePixels<uint32_t>([&]() {
|
||||
++count;
|
||||
return AsVariant(BGRAColor::Green().AsPixel());
|
||||
});
|
||||
EXPECT_EQ(WriteState::FINISHED, result);
|
||||
EXPECT_EQ(75u * 100u, count);
|
||||
|
||||
AssertCorrectPipelineFinalState(aSink,
|
||||
IntRect(0, 0, 100, 75),
|
||||
IntRect(0, 0, 100, 75));
|
||||
|
||||
// Check that the generated image is correct.
|
||||
RawAccessFrameRef currentFrame = aDecoder->GetCurrentFrameRef();
|
||||
RefPtr<SourceSurface> surface = currentFrame->GetSurface();
|
||||
EXPECT_TRUE(IsSolidColor(surface, BGRAColor::Green()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageSurfaceSink, PalettedSurfaceSinkWritePixelsFor0_0_100_100)
|
||||
{
|
||||
WithPalettedSurfaceSink(IntRect(0, 0, 100, 100),
|
||||
[](Decoder* aDecoder, PalettedSurfaceSink* aSink) {
|
||||
CheckPalettedWritePixels(aDecoder, aSink);
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageSurfaceSink, PalettedSurfaceSinkWriteRowsFor0_0_100_100)
|
||||
{
|
||||
WithPalettedSurfaceSink(IntRect(0, 0, 100, 100),
|
||||
[](Decoder* aDecoder, PalettedSurfaceSink* aSink) {
|
||||
CheckPalettedWriteRows(aDecoder, aSink);
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageSurfaceSink, PalettedSurfaceSinkWritePixelsFor25_25_50_50)
|
||||
{
|
||||
WithPalettedSurfaceSink(IntRect(25, 25, 50, 50),
|
||||
[](Decoder* aDecoder, PalettedSurfaceSink* aSink) {
|
||||
CheckPalettedWritePixels(aDecoder, aSink,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 50, 50)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 50, 50)),
|
||||
/* aInputWriteRect = */ Some(IntRect(25, 25, 50, 50)),
|
||||
/* aOutputWriteRect = */ Some(IntRect(25, 25, 50, 50)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageSurfaceSink, PalettedSurfaceSinkWriteRowsFor25_25_50_50)
|
||||
{
|
||||
WithPalettedSurfaceSink(IntRect(25, 25, 50, 50),
|
||||
[](Decoder* aDecoder, PalettedSurfaceSink* aSink) {
|
||||
CheckPalettedWriteRows(aDecoder, aSink,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 50, 50)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 50, 50)),
|
||||
/* aInputWriteRect = */ Some(IntRect(25, 25, 50, 50)),
|
||||
/* aOutputWriteRect = */ Some(IntRect(25, 25, 50, 50)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageSurfaceSink, PalettedSurfaceSinkWritePixelsForMinus25_Minus25_50_50)
|
||||
{
|
||||
WithPalettedSurfaceSink(IntRect(-25, -25, 50, 50),
|
||||
[](Decoder* aDecoder, PalettedSurfaceSink* aSink) {
|
||||
CheckPalettedWritePixels(aDecoder, aSink,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 50, 50)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 50, 50)),
|
||||
/* aInputWriteRect = */ Some(IntRect(-25, -25, 50, 50)),
|
||||
/* aOutputWriteRect = */ Some(IntRect(-25, -25, 50, 50)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageSurfaceSink, PalettedSurfaceSinkWriteRowsForMinus25_Minus25_50_50)
|
||||
{
|
||||
WithPalettedSurfaceSink(IntRect(-25, -25, 50, 50),
|
||||
[](Decoder* aDecoder, PalettedSurfaceSink* aSink) {
|
||||
CheckPalettedWriteRows(aDecoder, aSink,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 50, 50)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 50, 50)),
|
||||
/* aInputWriteRect = */ Some(IntRect(-25, -25, 50, 50)),
|
||||
/* aOutputWriteRect = */ Some(IntRect(-25, -25, 50, 50)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageSurfaceSink, PalettedSurfaceSinkWritePixelsFor75_Minus25_50_50)
|
||||
{
|
||||
WithPalettedSurfaceSink(IntRect(75, -25, 50, 50),
|
||||
[](Decoder* aDecoder, PalettedSurfaceSink* aSink) {
|
||||
CheckPalettedWritePixels(aDecoder, aSink,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 50, 50)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 50, 50)),
|
||||
/* aInputWriteRect = */ Some(IntRect(75, -25, 50, 50)),
|
||||
/* aOutputWriteRect = */ Some(IntRect(75, -25, 50, 50)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageSurfaceSink, PalettedSurfaceSinkWriteRowsFor75_Minus25_50_50)
|
||||
{
|
||||
WithPalettedSurfaceSink(IntRect(75, -25, 50, 50),
|
||||
[](Decoder* aDecoder, PalettedSurfaceSink* aSink) {
|
||||
CheckPalettedWriteRows(aDecoder, aSink,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 50, 50)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 50, 50)),
|
||||
/* aInputWriteRect = */ Some(IntRect(75, -25, 50, 50)),
|
||||
/* aOutputWriteRect = */ Some(IntRect(75, -25, 50, 50)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageSurfaceSink, PalettedSurfaceSinkWritePixelsForMinus25_75_50_50)
|
||||
{
|
||||
WithPalettedSurfaceSink(IntRect(-25, 75, 50, 50),
|
||||
[](Decoder* aDecoder, PalettedSurfaceSink* aSink) {
|
||||
CheckPalettedWritePixels(aDecoder, aSink,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 50, 50)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 50, 50)),
|
||||
/* aInputWriteRect = */ Some(IntRect(-25, 75, 50, 50)),
|
||||
/* aOutputWriteRect = */ Some(IntRect(-25, 75, 50, 50)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageSurfaceSink, PalettedSurfaceSinkWriteRowsForMinus25_75_50_50)
|
||||
{
|
||||
WithPalettedSurfaceSink(IntRect(-25, 75, 50, 50),
|
||||
[](Decoder* aDecoder, PalettedSurfaceSink* aSink) {
|
||||
CheckPalettedWriteRows(aDecoder, aSink,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 50, 50)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 50, 50)),
|
||||
/* aInputWriteRect = */ Some(IntRect(-25, 75, 50, 50)),
|
||||
/* aOutputWriteRect = */ Some(IntRect(-25, 75, 50, 50)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageSurfaceSink, PalettedSurfaceSinkWritePixelsFor75_75_50_50)
|
||||
{
|
||||
WithPalettedSurfaceSink(IntRect(75, 75, 50, 50),
|
||||
[](Decoder* aDecoder, PalettedSurfaceSink* aSink) {
|
||||
CheckPalettedWritePixels(aDecoder, aSink,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 50, 50)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 50, 50)),
|
||||
/* aInputWriteRect = */ Some(IntRect(75, 75, 50, 50)),
|
||||
/* aOutputWriteRect = */ Some(IntRect(75, 75, 50, 50)));
|
||||
});
|
||||
}
|
||||
|
||||
TEST(ImageSurfaceSink, PalettedSurfaceSinkWriteRowsFor75_75_50_50)
|
||||
{
|
||||
WithPalettedSurfaceSink(IntRect(75, 75, 50, 50),
|
||||
[](Decoder* aDecoder, PalettedSurfaceSink* aSink) {
|
||||
CheckPalettedWriteRows(aDecoder, aSink,
|
||||
/* aOutputRect = */ Some(IntRect(0, 0, 50, 50)),
|
||||
/* aInputRect = */ Some(IntRect(0, 0, 50, 50)),
|
||||
/* aInputWriteRect = */ Some(IntRect(75, 75, 50, 50)),
|
||||
/* aOutputWriteRect = */ Some(IntRect(75, 75, 50, 50)));
|
||||
});
|
||||
}
|
@ -11,8 +11,22 @@ UNIFIED_SOURCES = [
|
||||
'TestCopyOnWrite.cpp',
|
||||
'TestDecoders.cpp',
|
||||
'TestDecodeToSurface.cpp',
|
||||
'TestDeinterlacingFilter.cpp',
|
||||
'TestMetadata.cpp',
|
||||
'TestRemoveFrameRectFilter.cpp',
|
||||
'TestStreamingLexer.cpp',
|
||||
'TestSurfaceSink.cpp',
|
||||
]
|
||||
|
||||
if CONFIG['MOZ_ENABLE_SKIA']:
|
||||
UNIFIED_SOURCES += [
|
||||
'TestDownscalingFilter.cpp',
|
||||
'TestSurfacePipeIntegration.cpp',
|
||||
]
|
||||
|
||||
SOURCES += [
|
||||
# Can't be unified because it manipulates the preprocessor environment.
|
||||
'TestDownscalingFilterNoSkia.cpp',
|
||||
]
|
||||
|
||||
TEST_HARNESS_FILES.gtest += [
|
||||
@ -34,8 +48,14 @@ TEST_HARNESS_FILES.gtest += [
|
||||
'transparent.png',
|
||||
]
|
||||
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'/dom/base',
|
||||
'/gfx/2d',
|
||||
'/image',
|
||||
]
|
||||
|
||||
LOCAL_INCLUDES += CONFIG['SKIA_INCLUDES']
|
||||
|
||||
FINAL_LIBRARY = 'xul-gtest'
|
||||
|
Loading…
Reference in New Issue
Block a user