diff options
Diffstat (limited to 'gfx/2d/unittest')
-rw-r--r-- | gfx/2d/unittest/Main.cpp | 56 | ||||
-rw-r--r-- | gfx/2d/unittest/SanityChecks.cpp | 19 | ||||
-rw-r--r-- | gfx/2d/unittest/SanityChecks.h | 16 | ||||
-rw-r--r-- | gfx/2d/unittest/TestBase.cpp | 48 | ||||
-rw-r--r-- | gfx/2d/unittest/TestBase.h | 54 | ||||
-rw-r--r-- | gfx/2d/unittest/TestBugs.cpp | 86 | ||||
-rw-r--r-- | gfx/2d/unittest/TestBugs.h | 18 | ||||
-rw-r--r-- | gfx/2d/unittest/TestCairo.cpp | 96 | ||||
-rw-r--r-- | gfx/2d/unittest/TestDrawTargetBase.cpp | 109 | ||||
-rw-r--r-- | gfx/2d/unittest/TestDrawTargetBase.h | 38 | ||||
-rw-r--r-- | gfx/2d/unittest/TestDrawTargetD2D.cpp | 23 | ||||
-rw-r--r-- | gfx/2d/unittest/TestDrawTargetD2D.h | 19 | ||||
-rw-r--r-- | gfx/2d/unittest/TestPoint.cpp | 46 | ||||
-rw-r--r-- | gfx/2d/unittest/TestPoint.h | 17 | ||||
-rw-r--r-- | gfx/2d/unittest/TestScaling.cpp | 249 | ||||
-rw-r--r-- | gfx/2d/unittest/TestScaling.h | 22 | ||||
-rw-r--r-- | gfx/2d/unittest/unittest.vcxproj | 94 |
17 files changed, 1010 insertions, 0 deletions
diff --git a/gfx/2d/unittest/Main.cpp b/gfx/2d/unittest/Main.cpp new file mode 100644 index 000000000..46a1af5b6 --- /dev/null +++ b/gfx/2d/unittest/Main.cpp @@ -0,0 +1,56 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * 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 "SanityChecks.h" +#include "TestPoint.h" +#include "TestScaling.h" +#include "TestBugs.h" +#ifdef WIN32 +#include "TestDrawTargetD2D.h" +#endif + +#include <string> +#include <sstream> + +struct TestObject { + TestBase *test; + std::string name; +}; + + +using namespace std; + +int +main() +{ + TestObject tests[] = + { + { new SanityChecks(), "Sanity Checks" }, + #ifdef WIN32 + { new TestDrawTargetD2D(), "DrawTarget (D2D)" }, + #endif + { new TestPoint(), "Point Tests" }, + { new TestScaling(), "Scaling Tests" } + { new TestBugs(), "Bug Tests" } + }; + + int totalFailures = 0; + int totalTests = 0; + stringstream message; + printf("------ STARTING RUNNING TESTS ------\n"); + for (int i = 0; i < sizeof(tests) / sizeof(TestObject); i++) { + message << "--- RUNNING TESTS: " << tests[i].name << " ---\n"; + printf(message.str().c_str()); + message.str(""); + int failures = 0; + totalTests += tests[i].test->RunTests(&failures); + totalFailures += failures; + // Done with this test! + delete tests[i].test; + } + message << "------ FINISHED RUNNING TESTS ------\nTests run: " << totalTests << " - Passes: " << totalTests - totalFailures << " - Failures: " << totalFailures << "\n"; + printf(message.str().c_str()); + return totalFailures; +} diff --git a/gfx/2d/unittest/SanityChecks.cpp b/gfx/2d/unittest/SanityChecks.cpp new file mode 100644 index 000000000..7f109facd --- /dev/null +++ b/gfx/2d/unittest/SanityChecks.cpp @@ -0,0 +1,19 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * 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 "SanityChecks.h" + +SanityChecks::SanityChecks() +{ + REGISTER_TEST(SanityChecks, AlwaysPasses); +} + +void +SanityChecks::AlwaysPasses() +{ + bool testMustPass = true; + + VERIFY(testMustPass); +} diff --git a/gfx/2d/unittest/SanityChecks.h b/gfx/2d/unittest/SanityChecks.h new file mode 100644 index 000000000..f2a4a0b59 --- /dev/null +++ b/gfx/2d/unittest/SanityChecks.h @@ -0,0 +1,16 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * 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/. */ + +#pragma once + +#include "TestBase.h" + +class SanityChecks : public TestBase +{ +public: + SanityChecks(); + + void AlwaysPasses(); +}; diff --git a/gfx/2d/unittest/TestBase.cpp b/gfx/2d/unittest/TestBase.cpp new file mode 100644 index 000000000..5818a7299 --- /dev/null +++ b/gfx/2d/unittest/TestBase.cpp @@ -0,0 +1,48 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * 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 "TestBase.h" + +#include <sstream> + +using namespace std; + +int +TestBase::RunTests(int *aFailures) +{ + int testsRun = 0; + *aFailures = 0; + + for(unsigned int i = 0; i < mTests.size(); i++) { + stringstream stream; + stream << "Test (" << mTests[i].name << "): "; + LogMessage(stream.str()); + stream.str(""); + + mTestFailed = false; + + // Don't try this at home! We know these are actually pointers to members + // of child clases, so we reinterpret cast those child class pointers to + // TestBase and then call the functions. Because the compiler believes + // these function calls are members of TestBase. + ((*reinterpret_cast<TestBase*>((mTests[i].implPointer))).*(mTests[i].funcCall))(); + + if (!mTestFailed) { + LogMessage("PASSED\n"); + } else { + LogMessage("FAILED\n"); + (*aFailures)++; + } + testsRun++; + } + + return testsRun; +} + +void +TestBase::LogMessage(string aMessage) +{ + printf("%s", aMessage.c_str()); +} diff --git a/gfx/2d/unittest/TestBase.h b/gfx/2d/unittest/TestBase.h new file mode 100644 index 000000000..a57d6a730 --- /dev/null +++ b/gfx/2d/unittest/TestBase.h @@ -0,0 +1,54 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * 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/. */ + +#pragma once + +#include <string> +#include <vector> + +#ifdef _MSC_VER +// On MSVC otherwise our generic member pointer trick doesn't work. +#pragma pointers_to_members(full_generality, single_inheritance) +#endif + +#define VERIFY(arg) if (!(arg)) { \ + LogMessage("VERIFY FAILED: "#arg"\n"); \ + mTestFailed = true; \ + } + +#define REGISTER_TEST(className, testName) \ + mTests.push_back(Test(static_cast<TestCall>(&className::testName), #testName, this)) + +class TestBase +{ +public: + TestBase() {} + + typedef void (TestBase::*TestCall)(); + + int RunTests(int *aFailures); + +protected: + static void LogMessage(std::string aMessage); + + struct Test { + Test(TestCall aCall, std::string aName, void *aImplPointer) + : funcCall(aCall) + , name(aName) + , implPointer(aImplPointer) + { + } + TestCall funcCall; + std::string name; + void *implPointer; + }; + std::vector<Test> mTests; + + bool mTestFailed; + +private: + // This doesn't really work with our generic member pointer trick. + TestBase(const TestBase &aOther); +}; diff --git a/gfx/2d/unittest/TestBugs.cpp b/gfx/2d/unittest/TestBugs.cpp new file mode 100644 index 000000000..f127eed8b --- /dev/null +++ b/gfx/2d/unittest/TestBugs.cpp @@ -0,0 +1,86 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * 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 "TestBugs.h" +#include "2D.h" +#include <string.h> + +using namespace mozilla; +using namespace mozilla::gfx; + +TestBugs::TestBugs() +{ + REGISTER_TEST(TestBugs, CairoClip918671); + REGISTER_TEST(TestBugs, PushPopClip950550); +} + +void +TestBugs::CairoClip918671() +{ + RefPtr<DrawTarget> dt = Factory::CreateDrawTarget(BackendType::CAIRO, + IntSize(100, 100), + SurfaceFormat::B8G8R8A8); + RefPtr<DrawTarget> ref = Factory::CreateDrawTarget(BackendType::CAIRO, + IntSize(100, 100), + SurfaceFormat::B8G8R8A8); + // Create a path that extends around the center rect but doesn't intersect it. + RefPtr<PathBuilder> pb1 = dt->CreatePathBuilder(); + pb1->MoveTo(Point(10, 10)); + pb1->LineTo(Point(90, 10)); + pb1->LineTo(Point(90, 20)); + pb1->LineTo(Point(10, 20)); + pb1->Close(); + pb1->MoveTo(Point(90, 90)); + pb1->LineTo(Point(91, 90)); + pb1->LineTo(Point(91, 91)); + pb1->LineTo(Point(91, 90)); + pb1->Close(); + + RefPtr<Path> path1 = pb1->Finish(); + dt->PushClip(path1); + + // This center rect must NOT be rectilinear! + RefPtr<PathBuilder> pb2 = dt->CreatePathBuilder(); + pb2->MoveTo(Point(50, 50)); + pb2->LineTo(Point(55, 51)); + pb2->LineTo(Point(54, 55)); + pb2->LineTo(Point(50, 56)); + pb2->Close(); + + RefPtr<Path> path2 = pb2->Finish(); + dt->PushClip(path2); + + dt->FillRect(Rect(0, 0, 100, 100), ColorPattern(Color(1,0,0))); + + RefPtr<SourceSurface> surf1 = dt->Snapshot(); + RefPtr<SourceSurface> surf2 = ref->Snapshot(); + + RefPtr<DataSourceSurface> dataSurf1 = surf1->GetDataSurface(); + RefPtr<DataSourceSurface> dataSurf2 = surf2->GetDataSurface(); + + for (int y = 0; y < dt->GetSize().height; y++) { + VERIFY(memcmp(dataSurf1->GetData() + y * dataSurf1->Stride(), + dataSurf2->GetData() + y * dataSurf2->Stride(), + dataSurf1->GetSize().width * 4) == 0); + } + +} + +void +TestBugs::PushPopClip950550() +{ + RefPtr<DrawTarget> dt = Factory::CreateDrawTarget(BackendType::CAIRO, + IntSize(500, 500), + SurfaceFormat::B8G8R8A8); + dt->PushClipRect(Rect(0, 0, 100, 100)); + Matrix m(1, 0, 0, 1, 45, -100); + dt->SetTransform(m); + dt->PopClip(); + + // We fail the test if we assert in this call because our draw target's + // transforms are out of sync. + dt->FillRect(Rect(50, 50, 50, 50), ColorPattern(Color(0.5f, 0, 0, 1.0f))); +} + diff --git a/gfx/2d/unittest/TestBugs.h b/gfx/2d/unittest/TestBugs.h new file mode 100644 index 000000000..0c715df44 --- /dev/null +++ b/gfx/2d/unittest/TestBugs.h @@ -0,0 +1,18 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * 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/. */ + +#pragma once + +#include "TestBase.h" + +class TestBugs : public TestBase +{ +public: + TestBugs(); + + void CairoClip918671(); + void PushPopClip950550(); +}; + diff --git a/gfx/2d/unittest/TestCairo.cpp b/gfx/2d/unittest/TestCairo.cpp new file mode 100644 index 000000000..7df604695 --- /dev/null +++ b/gfx/2d/unittest/TestCairo.cpp @@ -0,0 +1,96 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +#include "cairo.h" + +#include "gtest/gtest.h" + +namespace mozilla { +namespace layers { + +void TryCircle(double centerX, double centerY, double radius) { + printf("TestCairo:TryArcs centerY %f, radius %f\n",centerY,radius); + + cairo_surface_t *surf = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,8,21); + ASSERT_TRUE(surf != nullptr); + + cairo_t *cairo = cairo_create(surf); + ASSERT_TRUE(cairo != nullptr); + + cairo_set_antialias(cairo, CAIRO_ANTIALIAS_NONE); + cairo_arc(cairo, 0.0, centerY, radius, 0.0, 6.2831853071795862); + cairo_fill_preserve(cairo); + + cairo_surface_destroy(surf); + cairo_destroy(cairo); +} + +TEST(Cairo, Simple) { + TryCircle(0.0, 0.0, 14.0); + TryCircle(0.0, 1.0, 22.4); + TryCircle(1.0, 0.0, 1422.4); + TryCircle(1.0, 1.0, 3422.4); + TryCircle(-10.0, 1.0, -2); +} + +TEST(Cairo, Bug825721) { + // OK: + TryCircle(0.0, 0.0, 8761126469220696064.0); + TryCircle(0.0, 1.0, 8761126469220696064.0); + + // OK: + TryCircle(1.0, 0.0, 5761126469220696064.0); + + // This was the crash in 825721. Note that centerY has to be non-zero, + // and radius has to be not only large, but in particular range. + // 825721 has a band-aid fix, where the crash is inevitable, but does + // not fix the cause. The same code crashes in cairo standalone. + TryCircle(0.0, 1.0, 5761126469220696064.0); +} + +TEST(Cairo, Bug1063486) { + + double x1, y1, x2, y2; + const double epsilon = .01; + + cairo_surface_t *surf = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 1, 1); + ASSERT_TRUE(surf != nullptr); + + cairo_t *cairo = cairo_create(surf); + ASSERT_TRUE(cairo != nullptr); + + printf("Path 1\n"); + cairo_move_to(cairo, -20, -10); + cairo_line_to(cairo, 20, -10); + cairo_line_to(cairo, 20, 10); + cairo_curve_to(cairo, 10,10, -10,10, -20,10); + cairo_curve_to(cairo, -30,10, -30,-10, -20,-10); + + cairo_path_extents(cairo, &x1, &y1, &x2, &y2); + + ASSERT_LT(std::abs(-27.5 - x1), epsilon); // the failing coordinate + ASSERT_LT(std::abs(-10 - y1), epsilon); + ASSERT_LT(std::abs(20 - x2), epsilon); + ASSERT_LT(std::abs(10 - y2), epsilon); + + printf("Path 2\n"); + cairo_new_path(cairo); + cairo_move_to(cairo, 10, 30); + cairo_line_to(cairo, 90, 30); + cairo_curve_to(cairo, 30,30, 30,30, 10,30); + cairo_curve_to(cairo, 0,30, 0,0, 30,5); + + cairo_path_extents(cairo, &x1, &y1, &x2, &y2); + + ASSERT_LT(std::abs(4.019531 - x1), epsilon); // the failing coordinate + ASSERT_LT(std::abs(4.437500 - y1), epsilon); + ASSERT_LT(std::abs(90. - x2), epsilon); + ASSERT_LT(std::abs(30. - y2), epsilon); + + cairo_surface_destroy(surf); + cairo_destroy(cairo); +} + +} // namespace layers +} // namespace mozilla diff --git a/gfx/2d/unittest/TestDrawTargetBase.cpp b/gfx/2d/unittest/TestDrawTargetBase.cpp new file mode 100644 index 000000000..2a0d95ed6 --- /dev/null +++ b/gfx/2d/unittest/TestDrawTargetBase.cpp @@ -0,0 +1,109 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * 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 "TestDrawTargetBase.h" +#include <sstream> + +using namespace mozilla; +using namespace mozilla::gfx; +using namespace std; + +TestDrawTargetBase::TestDrawTargetBase() +{ + REGISTER_TEST(TestDrawTargetBase, Initialized); + REGISTER_TEST(TestDrawTargetBase, FillCompletely); + REGISTER_TEST(TestDrawTargetBase, FillRect); +} + +void +TestDrawTargetBase::Initialized() +{ + VERIFY(mDT); +} + +void +TestDrawTargetBase::FillCompletely() +{ + mDT->FillRect(Rect(0, 0, DT_WIDTH, DT_HEIGHT), ColorPattern(Color(0, 0.5f, 0, 1.0f))); + + RefreshSnapshot(); + + VerifyAllPixels(Color(0, 0.5f, 0, 1.0f)); +} + +void +TestDrawTargetBase::FillRect() +{ + mDT->FillRect(Rect(0, 0, DT_WIDTH, DT_HEIGHT), ColorPattern(Color(0, 0.5f, 0, 1.0f))); + mDT->FillRect(Rect(50, 50, 50, 50), ColorPattern(Color(0.5f, 0, 0, 1.0f))); + + RefreshSnapshot(); + + VerifyPixel(IntPoint(49, 49), Color(0, 0.5f, 0, 1.0f)); + VerifyPixel(IntPoint(50, 50), Color(0.5f, 0, 0, 1.0f)); + VerifyPixel(IntPoint(99, 99), Color(0.5f, 0, 0, 1.0f)); + VerifyPixel(IntPoint(100, 100), Color(0, 0.5f, 0, 1.0f)); +} + +void +TestDrawTargetBase::RefreshSnapshot() +{ + RefPtr<SourceSurface> snapshot = mDT->Snapshot(); + mDataSnapshot = snapshot->GetDataSurface(); +} + +void +TestDrawTargetBase::VerifyAllPixels(const Color &aColor) +{ + uint32_t *colVal = (uint32_t*)mDataSnapshot->GetData(); + + uint32_t expected = RGBAPixelFromColor(aColor); + + for (int y = 0; y < DT_HEIGHT; y++) { + for (int x = 0; x < DT_WIDTH; x++) { + if (colVal[y * (mDataSnapshot->Stride() / 4) + x] != expected) { + LogMessage("VerifyAllPixels Failed\n"); + mTestFailed = true; + return; + } + } + } +} + +void +TestDrawTargetBase::VerifyPixel(const IntPoint &aPoint, mozilla::gfx::Color &aColor) +{ + uint32_t *colVal = (uint32_t*)mDataSnapshot->GetData(); + + uint32_t expected = RGBAPixelFromColor(aColor); + uint32_t rawActual = colVal[aPoint.y * (mDataSnapshot->Stride() / 4) + aPoint.x]; + + if (rawActual != expected) { + stringstream message; + uint32_t actb = rawActual & 0xFF; + uint32_t actg = (rawActual & 0xFF00) >> 8; + uint32_t actr = (rawActual & 0xFF0000) >> 16; + uint32_t acta = (rawActual & 0xFF000000) >> 24; + uint32_t expb = expected & 0xFF; + uint32_t expg = (expected & 0xFF00) >> 8; + uint32_t expr = (expected & 0xFF0000) >> 16; + uint32_t expa = (expected & 0xFF000000) >> 24; + + message << "Verify Pixel (" << aPoint.x << "x" << aPoint.y << ") Failed." + " Expected (" << expr << "," << expg << "," << expb << "," << expa << ") " + " Got (" << actr << "," << actg << "," << actb << "," << acta << ")\n"; + + LogMessage(message.str()); + mTestFailed = true; + return; + } +} + +uint32_t +TestDrawTargetBase::RGBAPixelFromColor(const Color &aColor) +{ + return uint8_t((aColor.b * 255) + 0.5f) | uint8_t((aColor.g * 255) + 0.5f) << 8 | + uint8_t((aColor.r * 255) + 0.5f) << 16 | uint8_t((aColor.a * 255) + 0.5f) << 24; +} diff --git a/gfx/2d/unittest/TestDrawTargetBase.h b/gfx/2d/unittest/TestDrawTargetBase.h new file mode 100644 index 000000000..06a62413f --- /dev/null +++ b/gfx/2d/unittest/TestDrawTargetBase.h @@ -0,0 +1,38 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * 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/. */ + +#pragma once + +#include "2D.h" +#include "TestBase.h" + +#define DT_WIDTH 500 +#define DT_HEIGHT 500 + +/* This general DrawTarget test class can be reimplemented by a child class + * with optional additional drawtarget-specific tests. And is intended to run + * on a 500x500 32 BPP drawtarget. + */ +class TestDrawTargetBase : public TestBase +{ +public: + void Initialized(); + void FillCompletely(); + void FillRect(); + +protected: + TestDrawTargetBase(); + + void RefreshSnapshot(); + + void VerifyAllPixels(const mozilla::gfx::Color &aColor); + void VerifyPixel(const mozilla::gfx::IntPoint &aPoint, + mozilla::gfx::Color &aColor); + + uint32_t RGBAPixelFromColor(const mozilla::gfx::Color &aColor); + + RefPtr<mozilla::gfx::DrawTarget> mDT; + RefPtr<mozilla::gfx::DataSourceSurface> mDataSnapshot; +}; diff --git a/gfx/2d/unittest/TestDrawTargetD2D.cpp b/gfx/2d/unittest/TestDrawTargetD2D.cpp new file mode 100644 index 000000000..0715f93d8 --- /dev/null +++ b/gfx/2d/unittest/TestDrawTargetD2D.cpp @@ -0,0 +1,23 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * 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 "TestDrawTargetD2D.h" + +using namespace mozilla::gfx; +TestDrawTargetD2D::TestDrawTargetD2D() +{ + ::D3D10CreateDevice1(nullptr, + D3D10_DRIVER_TYPE_HARDWARE, + nullptr, + D3D10_CREATE_DEVICE_BGRA_SUPPORT | + D3D10_CREATE_DEVICE_PREVENT_INTERNAL_THREADING_OPTIMIZATIONS, + D3D10_FEATURE_LEVEL_10_0, + D3D10_1_SDK_VERSION, + getter_AddRefs(mDevice)); + + Factory::SetDirect3D10Device(mDevice); + + mDT = Factory::CreateDrawTarget(BackendType::DIRECT2D, IntSize(DT_WIDTH, DT_HEIGHT), SurfaceFormat::B8G8R8A8); +} diff --git a/gfx/2d/unittest/TestDrawTargetD2D.h b/gfx/2d/unittest/TestDrawTargetD2D.h new file mode 100644 index 000000000..97bb88cf2 --- /dev/null +++ b/gfx/2d/unittest/TestDrawTargetD2D.h @@ -0,0 +1,19 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * 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/. */ + +#pragma once + +#include "TestDrawTargetBase.h" + +#include <d3d10_1.h> + +class TestDrawTargetD2D : public TestDrawTargetBase +{ +public: + TestDrawTargetD2D(); + +private: + RefPtr<ID3D10Device1> mDevice; +}; diff --git a/gfx/2d/unittest/TestPoint.cpp b/gfx/2d/unittest/TestPoint.cpp new file mode 100644 index 000000000..6aa2b6a35 --- /dev/null +++ b/gfx/2d/unittest/TestPoint.cpp @@ -0,0 +1,46 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * 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 "TestPoint.h" + +#include "Point.h" + +using namespace mozilla::gfx; + +TestPoint::TestPoint() +{ + REGISTER_TEST(TestPoint, Addition); + REGISTER_TEST(TestPoint, Subtraction); +} + +void +TestPoint::Addition() +{ + Point a, b; + a.x = 2; + a.y = 2; + b.x = 5; + b.y = -5; + + a += b; + + VERIFY(a.x == 7.f); + VERIFY(a.y == -3.f); +} + +void +TestPoint::Subtraction() +{ + Point a, b; + a.x = 2; + a.y = 2; + b.x = 5; + b.y = -5; + + a -= b; + + VERIFY(a.x == -3.f); + VERIFY(a.y == 7.f); +} diff --git a/gfx/2d/unittest/TestPoint.h b/gfx/2d/unittest/TestPoint.h new file mode 100644 index 000000000..813d66c2f --- /dev/null +++ b/gfx/2d/unittest/TestPoint.h @@ -0,0 +1,17 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * 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/. */ + +#pragma once + +#include "TestBase.h" + +class TestPoint : public TestBase +{ +public: + TestPoint(); + + void Addition(); + void Subtraction(); +}; diff --git a/gfx/2d/unittest/TestScaling.cpp b/gfx/2d/unittest/TestScaling.cpp new file mode 100644 index 000000000..60e1acbf0 --- /dev/null +++ b/gfx/2d/unittest/TestScaling.cpp @@ -0,0 +1,249 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * 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 "TestScaling.h" + +#include "ImageScaling.h" + +using namespace mozilla::gfx; + +TestScaling::TestScaling() +{ + REGISTER_TEST(TestScaling, BasicHalfScale); + REGISTER_TEST(TestScaling, DoubleHalfScale); + REGISTER_TEST(TestScaling, UnevenHalfScale); + REGISTER_TEST(TestScaling, OddStrideHalfScale); + REGISTER_TEST(TestScaling, VerticalHalfScale); + REGISTER_TEST(TestScaling, HorizontalHalfScale); + REGISTER_TEST(TestScaling, MixedHalfScale); +} + +void +TestScaling::BasicHalfScale() +{ + std::vector<uint8_t> data; + data.resize(500 * 500 * 4); + + uint32_t *pixels = reinterpret_cast<uint32_t*>(&data.front()); + for (int y = 0; y < 500; y += 2) { + for (int x = 0; x < 500; x += 2) { + pixels[y * 500 + x] = 0xff00ff00; + pixels[y * 500 + x + 1] = 0xff00ffff; + pixels[(y + 1) * 500 + x] = 0xff000000; + pixels[(y + 1) * 500 + x + 1] = 0xff0000ff; + } + } + ImageHalfScaler scaler(&data.front(), 500 * 4, IntSize(500, 500)); + + scaler.ScaleForSize(IntSize(220, 240)); + + VERIFY(scaler.GetSize().width == 250); + VERIFY(scaler.GetSize().height == 250); + + pixels = (uint32_t*)scaler.GetScaledData(); + + for (int y = 0; y < 250; y++) { + for (int x = 0; x < 250; x++) { + VERIFY(pixels[y * (scaler.GetStride() / 4) + x] == 0xff007f7f); + } + } +} + +void +TestScaling::DoubleHalfScale() +{ + std::vector<uint8_t> data; + data.resize(500 * 500 * 4); + + uint32_t *pixels = reinterpret_cast<uint32_t*>(&data.front()); + for (int y = 0; y < 500; y += 2) { + for (int x = 0; x < 500; x += 2) { + pixels[y * 500 + x] = 0xff00ff00; + pixels[y * 500 + x + 1] = 0xff00ffff; + pixels[(y + 1) * 500 + x] = 0xff000000; + pixels[(y + 1) * 500 + x + 1] = 0xff0000ff; + } + } + ImageHalfScaler scaler(&data.front(), 500 * 4, IntSize(500, 500)); + + scaler.ScaleForSize(IntSize(120, 110)); + VERIFY(scaler.GetSize().width == 125); + VERIFY(scaler.GetSize().height == 125); + + pixels = (uint32_t*)scaler.GetScaledData(); + + for (int y = 0; y < 125; y++) { + for (int x = 0; x < 125; x++) { + VERIFY(pixels[y * (scaler.GetStride() / 4) + x] == 0xff007f7f); + } + } +} + +void +TestScaling::UnevenHalfScale() +{ + std::vector<uint8_t> data; + // Use a 16-byte aligned stride still, we test none-aligned strides + // separately. + data.resize(499 * 500 * 4); + + uint32_t *pixels = reinterpret_cast<uint32_t*>(&data.front()); + for (int y = 0; y < 500; y += 2) { + for (int x = 0; x < 500; x += 2) { + pixels[y * 500 + x] = 0xff00ff00; + if (x < 498) { + pixels[y * 500 + x + 1] = 0xff00ffff; + } + if (y < 498) { + pixels[(y + 1) * 500 + x] = 0xff000000; + if (x < 498) { + pixels[(y + 1) * 500 + x + 1] = 0xff0000ff; + } + } + } + } + ImageHalfScaler scaler(&data.front(), 500 * 4, IntSize(499, 499)); + + scaler.ScaleForSize(IntSize(220, 220)); + VERIFY(scaler.GetSize().width == 249); + VERIFY(scaler.GetSize().height == 249); + + pixels = (uint32_t*)scaler.GetScaledData(); + + for (int y = 0; y < 249; y++) { + for (int x = 0; x < 249; x++) { + VERIFY(pixels[y * (scaler.GetStride() / 4) + x] == 0xff007f7f); + } + } +} + +void +TestScaling::OddStrideHalfScale() +{ + std::vector<uint8_t> data; + // Use a 4-byte aligned stride to test if that doesn't cause any issues. + data.resize(499 * 499 * 4); + + uint32_t *pixels = reinterpret_cast<uint32_t*>(&data.front()); + for (int y = 0; y < 500; y += 2) { + for (int x = 0; x < 500; x += 2) { + pixels[y * 499 + x] = 0xff00ff00; + if (x < 498) { + pixels[y * 499 + x + 1] = 0xff00ffff; + } + if (y < 498) { + pixels[(y + 1) * 499 + x] = 0xff000000; + if (x < 498) { + pixels[(y + 1) * 499 + x + 1] = 0xff0000ff; + } + } + } + } + ImageHalfScaler scaler(&data.front(), 499 * 4, IntSize(499, 499)); + + scaler.ScaleForSize(IntSize(220, 220)); + VERIFY(scaler.GetSize().width == 249); + VERIFY(scaler.GetSize().height == 249); + + pixels = (uint32_t*)scaler.GetScaledData(); + + for (int y = 0; y < 249; y++) { + for (int x = 0; x < 249; x++) { + VERIFY(pixels[y * (scaler.GetStride() / 4) + x] == 0xff007f7f); + } + } +} +void +TestScaling::VerticalHalfScale() +{ + std::vector<uint8_t> data; + data.resize(500 * 500 * 4); + + uint32_t *pixels = reinterpret_cast<uint32_t*>(&data.front()); + for (int y = 0; y < 500; y += 2) { + for (int x = 0; x < 500; x += 2) { + pixels[y * 500 + x] = 0xff00ff00; + pixels[y * 500 + x + 1] = 0xff00ffff; + pixels[(y + 1) * 500 + x] = 0xff000000; + pixels[(y + 1) * 500 + x + 1] = 0xff0000ff; + } + } + ImageHalfScaler scaler(&data.front(), 500 * 4, IntSize(500, 500)); + + scaler.ScaleForSize(IntSize(400, 240)); + VERIFY(scaler.GetSize().width == 500); + VERIFY(scaler.GetSize().height == 250); + + pixels = (uint32_t*)scaler.GetScaledData(); + + for (int y = 0; y < 250; y++) { + for (int x = 0; x < 500; x += 2) { + VERIFY(pixels[y * (scaler.GetStride() / 4) + x] == 0xff007f00); + VERIFY(pixels[y * (scaler.GetStride() / 4) + x + 1] == 0xff007fff); + } + } +} + +void +TestScaling::HorizontalHalfScale() +{ + std::vector<uint8_t> data; + data.resize(520 * 500 * 4); + + uint32_t *pixels = reinterpret_cast<uint32_t*>(&data.front()); + for (int y = 0; y < 500; y ++) { + for (int x = 0; x < 520; x += 8) { + pixels[y * 520 + x] = 0xff00ff00; + pixels[y * 520 + x + 1] = 0xff00ffff; + pixels[y * 520 + x + 2] = 0xff000000; + pixels[y * 520 + x + 3] = 0xff0000ff; + pixels[y * 520 + x + 4] = 0xffff00ff; + pixels[y * 520 + x + 5] = 0xff0000ff; + pixels[y * 520 + x + 6] = 0xffffffff; + pixels[y * 520 + x + 7] = 0xff0000ff; + } + } + ImageHalfScaler scaler(&data.front(), 520 * 4, IntSize(520, 500)); + + scaler.ScaleForSize(IntSize(240, 400)); + VERIFY(scaler.GetSize().width == 260); + VERIFY(scaler.GetSize().height == 500); + + pixels = (uint32_t*)scaler.GetScaledData(); + + for (int y = 0; y < 500; y++) { + for (int x = 0; x < 260; x += 4) { + VERIFY(pixels[y * (scaler.GetStride() / 4) + x] == 0xff00ff7f); + VERIFY(pixels[y * (scaler.GetStride() / 4) + x + 1] == 0xff00007f); + VERIFY(pixels[y * (scaler.GetStride() / 4) + x + 2] == 0xff7f00ff); + VERIFY(pixels[y * (scaler.GetStride() / 4) + x + 3] == 0xff7f7fff); + } + } +} + +void +TestScaling::MixedHalfScale() +{ + std::vector<uint8_t> data; + data.resize(500 * 500 * 4); + + uint32_t *pixels = reinterpret_cast<uint32_t*>(&data.front()); + for (int y = 0; y < 500; y += 2) { + for (int x = 0; x < 500; x += 2) { + pixels[y * 500 + x] = 0xff00ff00; + pixels[y * 500 + x + 1] = 0xff00ffff; + pixels[(y + 1) * 500 + x] = 0xff000000; + pixels[(y + 1) * 500 + x + 1] = 0xff0000ff; + } + } + ImageHalfScaler scaler(&data.front(), 500 * 4, IntSize(500, 500)); + + scaler.ScaleForSize(IntSize(120, 240)); + VERIFY(scaler.GetSize().width == 125); + VERIFY(scaler.GetSize().height == 250); + scaler.ScaleForSize(IntSize(240, 120)); + VERIFY(scaler.GetSize().width == 250); + VERIFY(scaler.GetSize().height == 125); +} diff --git a/gfx/2d/unittest/TestScaling.h b/gfx/2d/unittest/TestScaling.h new file mode 100644 index 000000000..e9bd1a8e0 --- /dev/null +++ b/gfx/2d/unittest/TestScaling.h @@ -0,0 +1,22 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * 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/. */ + +#pragma once + +#include "TestBase.h" + +class TestScaling : public TestBase +{ +public: + TestScaling(); + + void BasicHalfScale(); + void DoubleHalfScale(); + void UnevenHalfScale(); + void OddStrideHalfScale(); + void VerticalHalfScale(); + void HorizontalHalfScale(); + void MixedHalfScale(); +}; diff --git a/gfx/2d/unittest/unittest.vcxproj b/gfx/2d/unittest/unittest.vcxproj new file mode 100644 index 000000000..7ddf92530 --- /dev/null +++ b/gfx/2d/unittest/unittest.vcxproj @@ -0,0 +1,94 @@ +<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{CCF4BC8B-0CED-47CA-B621-ABF1832527D9}</ProjectGuid>
+ <RootNamespace>unittest</RootNamespace>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>true</UseDebugLibraries>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>Application</ConfigurationType>
+ <UseDebugLibraries>false</UseDebugLibraries>
+ <WholeProgramOptimization>true</WholeProgramOptimization>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <LibraryPath>$(DXSDK_DIR)\Lib\x86;$(VCInstallDir)lib;$(VCInstallDir)atlmfc\lib;$(WindowsSdkDir)lib;$(FrameworkSDKDir)\lib</LibraryPath>
+ <IncludePath>$(ProjectDir)..\;$(IncludePath)</IncludePath>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <LibraryPath>$(DXSDK_DIR)\Lib\x86;$(VCInstallDir)lib;$(VCInstallDir)lib;$(VCInstallDir)atlmfc\lib;$(WindowsSdkDir)lib;$(FrameworkSDKDir)\lib</LibraryPath>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>../</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <AdditionalDependencies>../$(Configuration)/gfx2d.lib;dxguid.lib;d3d10_1.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <WarningLevel>Level3</WarningLevel>
+ <Optimization>MaxSpeed</Optimization>
+ <FunctionLevelLinking>true</FunctionLevelLinking>
+ <IntrinsicFunctions>true</IntrinsicFunctions>
+ <AdditionalIncludeDirectories>../</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_MBCS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <GenerateDebugInformation>true</GenerateDebugInformation>
+ <EnableCOMDATFolding>true</EnableCOMDATFolding>
+ <OptimizeReferences>true</OptimizeReferences>
+ <AdditionalDependencies>../$(Configuration)/gfx2d.lib;dxguid.lib;d3d10_1.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="Main.cpp" />
+ <ClCompile Include="SanityChecks.cpp" />
+ <ClCompile Include="TestBase.cpp" />
+ <ClCompile Include="TestDrawTargetBase.cpp" />
+ <ClCompile Include="TestDrawTargetD2D.cpp" />
+ <ClCompile Include="TestPoint.cpp" />
+ <ClCompile Include="TestScaling.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="TestDrawTargetBase.h" />
+ <ClInclude Include="SanityChecks.h" />
+ <ClInclude Include="TestBase.h" />
+ <ClInclude Include="TestDrawTargetD2D.h" />
+ <ClInclude Include="TestPoint.h" />
+ <ClInclude Include="TestScaling.h" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
\ No newline at end of file |