michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "gtest/gtest.h" michael@0: #include "nsRegion.h" michael@0: michael@0: class TestLargestRegion { michael@0: public: michael@0: static void TestSingleRect(nsRect r) { michael@0: nsRegion region(r); michael@0: EXPECT_TRUE(region.GetLargestRectangle().IsEqualInterior(r)); michael@0: } michael@0: // Construct a rectangle, remove part of it, then check the remainder michael@0: static void TestNonRectangular() { michael@0: nsRegion r(nsRect(0, 0, 30, 30)); michael@0: michael@0: const int nTests = 19; michael@0: struct { michael@0: nsRect rect; michael@0: int64_t expectedArea; michael@0: } tests[nTests] = { michael@0: // Remove a 20x10 chunk from the square michael@0: { nsRect(0, 0, 20, 10), 600 }, michael@0: { nsRect(10, 0, 20, 10), 600 }, michael@0: { nsRect(10, 20, 20, 10), 600 }, michael@0: { nsRect(0, 20, 20, 10), 600 }, michael@0: // Remove a 10x20 chunk from the square michael@0: { nsRect(0, 0, 10, 20), 600 }, michael@0: { nsRect(20, 0, 10, 20), 600 }, michael@0: { nsRect(20, 10, 10, 20), 600 }, michael@0: { nsRect(0, 10, 10, 20), 600 }, michael@0: // Remove the center 10x10 michael@0: { nsRect(10, 10, 10, 10), 300 }, michael@0: // Remove the middle column michael@0: { nsRect(10, 0, 10, 30), 300 }, michael@0: // Remove the middle row michael@0: { nsRect(0, 10, 30, 10), 300 }, michael@0: // Remove the corners 10x10 michael@0: { nsRect(0, 0, 10, 10), 600 }, michael@0: { nsRect(20, 20, 10, 10), 600 }, michael@0: { nsRect(20, 0, 10, 10), 600 }, michael@0: { nsRect(0, 20, 10, 10), 600 }, michael@0: // Remove the corners 20x20 michael@0: { nsRect(0, 0, 20, 20), 300 }, michael@0: { nsRect(10, 10, 20, 20), 300 }, michael@0: { nsRect(10, 0, 20, 20), 300 }, michael@0: { nsRect(0, 10, 20, 20), 300 } michael@0: }; michael@0: michael@0: for (int32_t i = 0; i < nTests; i++) { michael@0: nsRegion r2; michael@0: r2.Sub(r, tests[i].rect); michael@0: michael@0: EXPECT_TRUE(r2.IsComplex()) << "nsRegion code got unexpectedly smarter!"; michael@0: michael@0: nsRect largest = r2.GetLargestRectangle(); michael@0: EXPECT_TRUE(largest.width * largest.height == tests[i].expectedArea) << michael@0: "Did not successfully find largest rectangle in non-rectangular region on iteration " << i; michael@0: } michael@0: michael@0: } michael@0: static void TwoRectTest() { michael@0: nsRegion r(nsRect(0, 0, 100, 100)); michael@0: const int nTests = 4; michael@0: struct { michael@0: nsRect rect1, rect2; michael@0: int64_t expectedArea; michael@0: } tests[nTests] = { michael@0: { nsRect(0, 0, 75, 40), nsRect(0, 60, 75, 40), 2500 }, michael@0: { nsRect(25, 0, 75, 40), nsRect(25, 60, 75, 40), 2500 }, michael@0: { nsRect(25, 0, 75, 40), nsRect(0, 60, 75, 40), 2000 }, michael@0: { nsRect(0, 0, 75, 40), nsRect(25, 60, 75, 40), 2000 }, michael@0: }; michael@0: for (int32_t i = 0; i < nTests; i++) { michael@0: nsRegion r2; michael@0: michael@0: r2.Sub(r, tests[i].rect1); michael@0: r2.Sub(r2, tests[i].rect2); michael@0: michael@0: EXPECT_TRUE(r2.IsComplex()) << "nsRegion code got unexpectedly smarter!"; michael@0: michael@0: nsRect largest = r2.GetLargestRectangle(); michael@0: EXPECT_TRUE(largest.width * largest.height == tests[i].expectedArea) << michael@0: "Did not successfully find largest rectangle in two-rect-subtract region on iteration " << i; michael@0: } michael@0: } michael@0: static void TestContainsSpecifiedRect() { michael@0: nsRegion r(nsRect(0, 0, 100, 100)); michael@0: r.Or(r, nsRect(0, 300, 50, 50)); michael@0: EXPECT_TRUE(r.GetLargestRectangle(nsRect(0, 300, 10, 10)).IsEqualInterior(nsRect(0, 300, 50, 50))) << michael@0: "Chose wrong rectangle"; michael@0: } michael@0: static void TestContainsSpecifiedOverflowingRect() { michael@0: nsRegion r(nsRect(0, 0, 100, 100)); michael@0: r.Or(r, nsRect(0, 300, 50, 50)); michael@0: EXPECT_TRUE(r.GetLargestRectangle(nsRect(0, 290, 10, 20)).IsEqualInterior(nsRect(0, 300, 50, 50))) << michael@0: "Chose wrong rectangle"; michael@0: } michael@0: }; michael@0: michael@0: TEST(Gfx, RegionSingleRect) { michael@0: TestLargestRegion::TestSingleRect(nsRect(0, 52, 720, 480)); michael@0: TestLargestRegion::TestSingleRect(nsRect(-20, 40, 50, 20)); michael@0: TestLargestRegion::TestSingleRect(nsRect(-20, 40, 10, 8)); michael@0: TestLargestRegion::TestSingleRect(nsRect(-20, -40, 10, 8)); michael@0: TestLargestRegion::TestSingleRect(nsRect(-10, -10, 20, 20)); michael@0: } michael@0: michael@0: TEST(Gfx, RegionNonRectangular) { michael@0: TestLargestRegion::TestNonRectangular(); michael@0: } michael@0: michael@0: TEST(Gfx, RegionTwoRectTest) { michael@0: TestLargestRegion::TwoRectTest(); michael@0: } michael@0: michael@0: TEST(Gfx, RegionContainsSpecifiedRect) { michael@0: TestLargestRegion::TestContainsSpecifiedRect(); michael@0: } michael@0: michael@0: TEST(Gfx, RegionTestContainsSpecifiedOverflowingRect) { michael@0: TestLargestRegion::TestContainsSpecifiedOverflowingRect(); michael@0: } michael@0: michael@0: TEST(Gfx, RegionScaleToInside) { michael@0: { // no rectangles michael@0: nsRegion r; michael@0: michael@0: nsIntRegion scaled = r.ScaleToInsidePixels(1, 1, 60); michael@0: nsIntRegion result; michael@0: michael@0: EXPECT_TRUE(result.IsEqual(scaled)) << michael@0: "scaled result incorrect"; michael@0: } michael@0: michael@0: { // one rectangle michael@0: nsRegion r(nsRect(0,44760,19096,264)); michael@0: michael@0: nsIntRegion scaled = r.ScaleToInsidePixels(1, 1, 60); michael@0: nsIntRegion result(nsIntRect(0,746,318,4)); michael@0: michael@0: EXPECT_TRUE(result.IsEqual(scaled)) << michael@0: "scaled result incorrect"; michael@0: } michael@0: michael@0: michael@0: { // the first rectangle gets adjusted michael@0: nsRegion r(nsRect(0,44760,19096,264)); michael@0: r.Or(r, nsRect(0,45024,19360,1056)); michael@0: michael@0: nsIntRegion scaled = r.ScaleToInsidePixels(1, 1, 60); michael@0: nsIntRegion result(nsIntRect(0,746,318,5)); michael@0: result.Or(result, nsIntRect(0,751,322,17)); michael@0: michael@0: EXPECT_TRUE(result.IsEqual(scaled)) << michael@0: "scaled result incorrect"; michael@0: } michael@0: michael@0: { // the second rectangle gets adjusted michael@0: nsRegion r(nsRect(0,44760,19360,264)); michael@0: r.Or(r, nsRect(0,45024,19096,1056)); michael@0: michael@0: nsIntRegion scaled = r.ScaleToInsidePixels(1, 1, 60); michael@0: nsIntRegion result(nsIntRect(0,746,322,4)); michael@0: result.Or(result, nsIntRect(0,750,318,18)); michael@0: michael@0: EXPECT_TRUE(result.IsEqual(scaled)) << michael@0: "scaled result incorrect"; michael@0: } michael@0: michael@0: } michael@0: michael@0: TEST(Gfx, RegionSimplify) { michael@0: { // ensure simplify works on a single rect michael@0: nsRegion r(nsRect(0,100,200,100)); michael@0: michael@0: r.SimplifyOutwardByArea(100*100); michael@0: michael@0: nsRegion result(nsRect(0,100,200,100)); michael@0: michael@0: EXPECT_TRUE(r.IsEqual(result)) << michael@0: "regions not the same"; michael@0: } michael@0: michael@0: { // the rectangles will be merged michael@0: nsRegion r(nsRect(0,100,200,100)); michael@0: r.Or(r, nsRect(0,200,300,200)); michael@0: michael@0: r.SimplifyOutwardByArea(100*100); michael@0: michael@0: nsRegion result(nsRect(0,100,300,300)); michael@0: michael@0: EXPECT_TRUE(r.IsEqual(result)) << michael@0: "regions not merged"; michael@0: } michael@0: michael@0: { // two rectangle on the first span michael@0: // one on the second michael@0: nsRegion r(nsRect(0,100,200,100)); michael@0: r.Or(r, nsRect(0,200,300,200)); michael@0: r.Or(r, nsRect(250,100,50,100)); michael@0: michael@0: EXPECT_TRUE(r.GetNumRects() == 3) << michael@0: "wrong number of rects"; michael@0: michael@0: r.SimplifyOutwardByArea(100*100); michael@0: michael@0: nsRegion result(nsRect(0,100,300,300)); michael@0: michael@0: EXPECT_TRUE(r.IsEqual(result)) << michael@0: "regions not merged"; michael@0: } michael@0: michael@0: { // the rectangles will be merged michael@0: nsRegion r(nsRect(0,100,200,100)); michael@0: r.Or(r, nsRect(0,200,300,200)); michael@0: r.Or(r, nsRect(250,100,50,100)); michael@0: r.Sub(r, nsRect(200,200,40,200)); michael@0: michael@0: EXPECT_TRUE(r.GetNumRects() == 4) << michael@0: "wrong number of rects"; michael@0: michael@0: r.SimplifyOutwardByArea(100*100); michael@0: michael@0: nsRegion result(nsRect(0,100,300,300)); michael@0: result.Sub(result, nsRect(200,100,40,300)); michael@0: michael@0: EXPECT_TRUE(r.IsEqual(result)) << michael@0: "regions not merged"; michael@0: } michael@0: michael@0: { // three spans of rectangles michael@0: nsRegion r(nsRect(0,100,200,100)); michael@0: r.Or(r, nsRect(0,200,300,200)); michael@0: r.Or(r, nsRect(250,100,50,50)); michael@0: r.Sub(r, nsRect(200,200,40,200)); michael@0: michael@0: r.SimplifyOutwardByArea(100*100); michael@0: michael@0: nsRegion result(nsRect(0,100,300,300)); michael@0: result.Sub(result, nsRect(200,100,40,300)); michael@0: michael@0: EXPECT_TRUE(r.IsEqual(result)) << michael@0: "regions not merged"; michael@0: } michael@0: michael@0: { // three spans of rectangles and an unmerged rectangle michael@0: nsRegion r(nsRect(0,100,200,100)); michael@0: r.Or(r, nsRect(0,200,300,200)); michael@0: r.Or(r, nsRect(250,100,50,50)); michael@0: r.Sub(r, nsRect(200,200,40,200)); michael@0: r.Or(r, nsRect(250,900,150,50)); michael@0: michael@0: r.SimplifyOutwardByArea(100*100); michael@0: michael@0: nsRegion result(nsRect(0,100,300,300)); michael@0: result.Sub(result, nsRect(200,100,40,300)); michael@0: result.Or(result, nsRect(250,900,150,50)); michael@0: michael@0: EXPECT_TRUE(r.IsEqual(result)) << michael@0: "regions not merged"; michael@0: } michael@0: michael@0: { // unmerged regions michael@0: nsRegion r(nsRect(0,100,200,100)); michael@0: r.Or(r, nsRect(0,200,300,200)); michael@0: michael@0: r.SimplifyOutwardByArea(100); michael@0: michael@0: nsRegion result(nsRect(0,100,200,100)); michael@0: result.Or(result, nsRect(0,200,300,200)); michael@0: michael@0: EXPECT_TRUE(r.IsEqual(result)) << michael@0: "regions not merged"; michael@0: } michael@0: michael@0: { // empty region michael@0: // just make sure this doesn't crash. michael@0: nsRegion r; michael@0: r.SimplifyOutwardByArea(100); michael@0: } michael@0: michael@0: }