summaryrefslogtreecommitdiffstats
path: root/image/test/gtest/TestDecodeToSurface.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'image/test/gtest/TestDecodeToSurface.cpp')
-rw-r--r--image/test/gtest/TestDecodeToSurface.cpp173
1 files changed, 173 insertions, 0 deletions
diff --git a/image/test/gtest/TestDecodeToSurface.cpp b/image/test/gtest/TestDecodeToSurface.cpp
new file mode 100644
index 0000000000..838f957c43
--- /dev/null
+++ b/image/test/gtest/TestDecodeToSurface.cpp
@@ -0,0 +1,173 @@
+/* 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 "Common.h"
+#include "imgIContainer.h"
+#include "ImageOps.h"
+#include "mozilla/gfx/2D.h"
+#include "nsComponentManagerUtils.h"
+#include "nsCOMPtr.h"
+#include "nsIInputStream.h"
+#include "nsIRunnable.h"
+#include "nsIThread.h"
+#include "mozilla/RefPtr.h"
+#include "nsString.h"
+#include "nsThreadUtils.h"
+
+using namespace mozilla;
+using namespace mozilla::gfx;
+using namespace mozilla::image;
+
+class DecodeToSurfaceRunnable : public Runnable {
+ public:
+ DecodeToSurfaceRunnable(RefPtr<SourceSurface>& aSurface,
+ nsIInputStream* aInputStream,
+ ImageOps::ImageBuffer* aImageBuffer,
+ const ImageTestCase& aTestCase)
+ : mozilla::Runnable("DecodeToSurfaceRunnable"),
+ mSurface(aSurface),
+ mInputStream(aInputStream),
+ mImageBuffer(aImageBuffer),
+ mTestCase(aTestCase) {}
+
+ NS_IMETHOD Run() override {
+ Go();
+ return NS_OK;
+ }
+
+ void Go() {
+ Maybe<IntSize> outputSize;
+ if (mTestCase.mOutputSize != mTestCase.mSize) {
+ outputSize.emplace(mTestCase.mOutputSize);
+ }
+
+ uint32_t flags = FromSurfaceFlags(mTestCase.mSurfaceFlags);
+
+ if (mImageBuffer) {
+ mSurface = ImageOps::DecodeToSurface(
+ mImageBuffer, nsDependentCString(mTestCase.mMimeType), flags,
+ outputSize);
+ } else {
+ mSurface = ImageOps::DecodeToSurface(
+ mInputStream.forget(), nsDependentCString(mTestCase.mMimeType), flags,
+ outputSize);
+ }
+ ASSERT_TRUE(mSurface != nullptr);
+
+ EXPECT_TRUE(mSurface->IsDataSourceSurface());
+ EXPECT_TRUE(mSurface->GetFormat() == SurfaceFormat::OS_RGBX ||
+ mSurface->GetFormat() == SurfaceFormat::OS_RGBA);
+
+ if (outputSize) {
+ EXPECT_EQ(*outputSize, mSurface->GetSize());
+ } else {
+ EXPECT_EQ(mTestCase.mSize, mSurface->GetSize());
+ }
+
+ EXPECT_TRUE(IsSolidColor(mSurface, mTestCase.Color(), mTestCase.Fuzz()));
+ }
+
+ private:
+ RefPtr<SourceSurface>& mSurface;
+ nsCOMPtr<nsIInputStream> mInputStream;
+ RefPtr<ImageOps::ImageBuffer> mImageBuffer;
+ ImageTestCase mTestCase;
+};
+
+static void RunDecodeToSurface(const ImageTestCase& aTestCase,
+ ImageOps::ImageBuffer* aImageBuffer = nullptr) {
+ nsCOMPtr<nsIInputStream> inputStream;
+ if (!aImageBuffer) {
+ inputStream = LoadFile(aTestCase.mPath);
+ ASSERT_TRUE(inputStream != nullptr);
+ }
+
+ nsCOMPtr<nsIThread> thread;
+ nsresult rv =
+ NS_NewNamedThread("DecodeToSurface", getter_AddRefs(thread), nullptr);
+ ASSERT_NS_SUCCEEDED(rv);
+
+ // We run the DecodeToSurface tests off-main-thread to ensure that
+ // DecodeToSurface doesn't require any main-thread-only code.
+ RefPtr<SourceSurface> surface;
+ nsCOMPtr<nsIRunnable> runnable = new DecodeToSurfaceRunnable(
+ surface, inputStream, aImageBuffer, aTestCase);
+ NS_DispatchAndSpinEventLoopUntilComplete("RunDecodeToSurface"_ns, thread,
+ do_AddRef(runnable));
+
+ thread->Shutdown();
+
+ // Explicitly release the SourceSurface on the main thread.
+ surface = nullptr;
+}
+
+class ImageDecodeToSurface : public ::testing::Test {
+ protected:
+ AutoInitializeImageLib mInit;
+};
+
+TEST_F(ImageDecodeToSurface, PNG) { RunDecodeToSurface(GreenPNGTestCase()); }
+TEST_F(ImageDecodeToSurface, GIF) { RunDecodeToSurface(GreenGIFTestCase()); }
+TEST_F(ImageDecodeToSurface, JPG) { RunDecodeToSurface(GreenJPGTestCase()); }
+TEST_F(ImageDecodeToSurface, BMP) { RunDecodeToSurface(GreenBMPTestCase()); }
+TEST_F(ImageDecodeToSurface, ICO) { RunDecodeToSurface(GreenICOTestCase()); }
+TEST_F(ImageDecodeToSurface, Icon) { RunDecodeToSurface(GreenIconTestCase()); }
+TEST_F(ImageDecodeToSurface, WebP) { RunDecodeToSurface(GreenWebPTestCase()); }
+
+TEST_F(ImageDecodeToSurface, AnimatedGIF) {
+ RunDecodeToSurface(GreenFirstFrameAnimatedGIFTestCase());
+}
+
+TEST_F(ImageDecodeToSurface, AnimatedPNG) {
+ RunDecodeToSurface(GreenFirstFrameAnimatedPNGTestCase());
+}
+
+TEST_F(ImageDecodeToSurface, Corrupt) {
+ ImageTestCase testCase = CorruptTestCase();
+
+ nsCOMPtr<nsIInputStream> inputStream = LoadFile(testCase.mPath);
+ ASSERT_TRUE(inputStream != nullptr);
+
+ RefPtr<SourceSurface> surface = ImageOps::DecodeToSurface(
+ inputStream.forget(), nsDependentCString(testCase.mMimeType),
+ imgIContainer::DECODE_FLAGS_DEFAULT);
+ EXPECT_TRUE(surface == nullptr);
+}
+
+TEST_F(ImageDecodeToSurface, ICOMultipleSizes) {
+ ImageTestCase testCase = GreenMultipleSizesICOTestCase();
+
+ nsCOMPtr<nsIInputStream> inputStream = LoadFile(testCase.mPath);
+ ASSERT_TRUE(inputStream != nullptr);
+
+ RefPtr<ImageOps::ImageBuffer> buffer =
+ ImageOps::CreateImageBuffer(inputStream.forget());
+ ASSERT_TRUE(buffer != nullptr);
+
+ ImageMetadata metadata;
+ nsresult rv = ImageOps::DecodeMetadata(
+ buffer, nsDependentCString(testCase.mMimeType), metadata);
+ EXPECT_NS_SUCCEEDED(rv);
+ ASSERT_TRUE(metadata.HasSize());
+ EXPECT_EQ(testCase.mSize, metadata.GetSize().ToUnknownSize());
+
+ const nsTArray<OrientedIntSize>& nativeSizes = metadata.GetNativeSizes();
+ ASSERT_EQ(6u, nativeSizes.Length());
+
+ OrientedIntSize expectedSizes[] = {
+ OrientedIntSize(16, 16), OrientedIntSize(32, 32),
+ OrientedIntSize(64, 64), OrientedIntSize(128, 128),
+ OrientedIntSize(256, 256), OrientedIntSize(256, 128),
+ };
+
+ for (int i = 0; i < 6; ++i) {
+ EXPECT_EQ(expectedSizes[i], nativeSizes[i]);
+
+ // Request decoding at native size
+ testCase.mOutputSize = nativeSizes[i].ToUnknownSize();
+ RunDecodeToSurface(testCase, buffer);
+ }
+}