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: michael@0: #include "nsRect.h" michael@0: #include "gfxRect.h" michael@0: #ifdef XP_WIN michael@0: #include michael@0: #endif michael@0: michael@0: template michael@0: static bool michael@0: TestConstructors() michael@0: { michael@0: // Create a rectangle michael@0: RectType rect1(10, 20, 30, 40); michael@0: michael@0: // Make sure the rectangle was properly initialized michael@0: EXPECT_TRUE(rect1.x == 10 && rect1.y == 20 && michael@0: rect1.width == 30 && rect1.height == 40) << michael@0: "[1] Make sure the rectangle was properly initialized with constructor"; michael@0: michael@0: // Create a second rect using the copy constructor michael@0: RectType rect2(rect1); michael@0: michael@0: // Make sure the rectangle was properly initialized michael@0: EXPECT_TRUE(rect2.x == rect1.x && rect2.y == rect2.y && michael@0: rect2.width == rect2.width && rect2.height == rect2.height) << michael@0: "[2] Make sure the rectangle was properly initialized with copy constructor"; michael@0: michael@0: michael@0: EXPECT_TRUE(!rect1.IsEmpty() && rect1.IsFinite() && michael@0: !rect2.IsEmpty() && rect2.IsFinite()) << michael@0: "[3] These rectangles are not empty and are finite"; michael@0: michael@0: return true; michael@0: } michael@0: michael@0: template michael@0: static bool michael@0: TestEqualityOperator() michael@0: { michael@0: RectType rect1(10, 20, 30, 40); michael@0: RectType rect2(rect1); michael@0: michael@0: // Test the equality operator michael@0: EXPECT_TRUE(rect1 == rect2) << michael@0: "[1] Test the equality operator"; michael@0: michael@0: EXPECT_FALSE(!rect1.IsEqualInterior(rect2)) << michael@0: "[2] Test the inequality operator"; michael@0: michael@0: // Make sure that two empty rects are equal michael@0: rect1.SetEmpty(); michael@0: rect2.SetEmpty(); michael@0: EXPECT_TRUE(rect1 == rect2) << michael@0: "[3] Make sure that two empty rects are equal"; michael@0: michael@0: return true; michael@0: } michael@0: michael@0: template michael@0: static bool michael@0: TestContainment() michael@0: { michael@0: RectType rect1(10, 10, 50, 50); michael@0: michael@0: // Test the point containment methods michael@0: // michael@0: michael@0: // Basic test of a point in the middle of the rect michael@0: EXPECT_FALSE(!rect1.Contains(rect1.x + rect1.width/2, rect1.y + rect1.height/2)) << michael@0: "[1] Basic test of a point in the middle of the rect"; michael@0: michael@0: // Test against a point at the left/top edges michael@0: EXPECT_FALSE(!rect1.Contains(rect1.x, rect1.y)) << michael@0: "[2] Test against a point at the left/top edges"; michael@0: michael@0: // Test against a point at the right/bottom extents michael@0: EXPECT_FALSE(rect1.Contains(rect1.XMost(), rect1.YMost())) << michael@0: "[3] Test against a point at the right/bottom extents"; michael@0: michael@0: // Test the rect containment methods michael@0: // michael@0: RectType rect2(rect1); michael@0: michael@0: // Test against a rect that's the same as rect1 michael@0: EXPECT_FALSE(!rect1.Contains(rect2)) << michael@0: "[4] Test against a rect that's the same as rect1"; michael@0: michael@0: // Test against a rect whose left edge (only) is outside of rect1 michael@0: rect2.x--; michael@0: EXPECT_FALSE(rect1.Contains(rect2)) << michael@0: "[5] Test against a rect whose left edge (only) is outside of rect1"; michael@0: rect2.x++; michael@0: michael@0: // Test against a rect whose top edge (only) is outside of rect1 michael@0: rect2.y--; michael@0: EXPECT_FALSE(rect1.Contains(rect2)) << michael@0: "[6] Test against a rect whose top edge (only) is outside of rect1"; michael@0: rect2.y++; michael@0: michael@0: // Test against a rect whose right edge (only) is outside of rect1 michael@0: rect2.x++; michael@0: EXPECT_FALSE(rect1.Contains(rect2)) << michael@0: "[7] Test against a rect whose right edge (only) is outside of rect1"; michael@0: rect2.x--; michael@0: michael@0: // Test against a rect whose bottom edge (only) is outside of rect1 michael@0: rect2.y++; michael@0: EXPECT_FALSE(rect1.Contains(rect2)) << michael@0: "[8] Test against a rect whose bottom edge (only) is outside of rect1"; michael@0: rect2.y--; michael@0: michael@0: return true; michael@0: } michael@0: michael@0: // Test the method that returns a boolean result but doesn't return a michael@0: // a rectangle michael@0: template michael@0: static bool michael@0: TestIntersects() michael@0: { michael@0: RectType rect1(10, 10, 50, 50); michael@0: RectType rect2(rect1); michael@0: michael@0: // Test against a rect that's the same as rect1 michael@0: EXPECT_FALSE(!rect1.Intersects(rect2)) << michael@0: "[1] Test against a rect that's the same as rect1"; michael@0: michael@0: // Test against a rect that's enclosed by rect1 michael@0: rect2.Inflate(-1, -1); michael@0: EXPECT_FALSE(!rect1.Contains(rect2) || !rect1.Intersects(rect2)) << michael@0: "[2] Test against a rect that's enclosed by rect1"; michael@0: rect2.Inflate(1, 1); michael@0: michael@0: // Make sure inflate and deflate worked correctly michael@0: EXPECT_TRUE(rect1.IsEqualInterior(rect2)) << michael@0: "[3] Make sure inflate and deflate worked correctly"; michael@0: michael@0: // Test against a rect that overlaps the left edge of rect1 michael@0: rect2.x--; michael@0: EXPECT_FALSE(!rect1.Intersects(rect2)) << michael@0: "[4] Test against a rect that overlaps the left edge of rect1"; michael@0: rect2.x++; michael@0: michael@0: // Test against a rect that's outside of rect1 on the left michael@0: rect2.x -= rect2.width; michael@0: EXPECT_FALSE(rect1.Intersects(rect2)) << michael@0: "[5] Test against a rect that's outside of rect1 on the left"; michael@0: rect2.x += rect2.width; michael@0: michael@0: // Test against a rect that overlaps the top edge of rect1 michael@0: rect2.y--; michael@0: EXPECT_FALSE(!rect1.Intersects(rect2)) << michael@0: "[6] Test against a rect that overlaps the top edge of rect1"; michael@0: rect2.y++; michael@0: michael@0: // Test against a rect that's outside of rect1 on the top michael@0: rect2.y -= rect2.height; michael@0: EXPECT_FALSE(rect1.Intersects(rect2)) << michael@0: "[7] Test against a rect that's outside of rect1 on the top"; michael@0: rect2.y += rect2.height; michael@0: michael@0: // Test against a rect that overlaps the right edge of rect1 michael@0: rect2.x++; michael@0: EXPECT_FALSE(!rect1.Intersects(rect2)) << michael@0: "[8] Test against a rect that overlaps the right edge of rect1"; michael@0: rect2.x--; michael@0: michael@0: // Test against a rect that's outside of rect1 on the right michael@0: rect2.x += rect2.width; michael@0: EXPECT_FALSE(rect1.Intersects(rect2)) << michael@0: "[9] Test against a rect that's outside of rect1 on the right"; michael@0: rect2.x -= rect2.width; michael@0: michael@0: // Test against a rect that overlaps the bottom edge of rect1 michael@0: rect2.y++; michael@0: EXPECT_FALSE(!rect1.Intersects(rect2)) << michael@0: "[10] Test against a rect that overlaps the bottom edge of rect1"; michael@0: rect2.y--; michael@0: michael@0: // Test against a rect that's outside of rect1 on the bottom michael@0: rect2.y += rect2.height; michael@0: EXPECT_FALSE(rect1.Intersects(rect2)) << michael@0: "[11] Test against a rect that's outside of rect1 on the bottom"; michael@0: rect2.y -= rect2.height; michael@0: michael@0: return true; michael@0: } michael@0: michael@0: // Test the method that returns a boolean result and an intersection rect michael@0: template michael@0: static bool michael@0: TestIntersection() michael@0: { michael@0: RectType rect1(10, 10, 50, 50); michael@0: RectType rect2(rect1); michael@0: RectType dest; michael@0: michael@0: // Test against a rect that's the same as rect1 michael@0: EXPECT_FALSE(!dest.IntersectRect(rect1, rect2) || !(dest.IsEqualInterior(rect1))) << michael@0: "[1] Test against a rect that's the same as rect1"; michael@0: michael@0: // Test against a rect that's enclosed by rect1 michael@0: rect2.Inflate(-1, -1); michael@0: EXPECT_FALSE(!dest.IntersectRect(rect1, rect2) || !(dest.IsEqualInterior(rect2))) << michael@0: "[2] Test against a rect that's enclosed by rect1"; michael@0: rect2.Inflate(1, 1); michael@0: michael@0: // Test against a rect that overlaps the left edge of rect1 michael@0: rect2.x--; michael@0: EXPECT_FALSE(!dest.IntersectRect(rect1, rect2) || michael@0: !(dest.IsEqualInterior(RectType(rect1.x, rect1.y, rect1.width - 1, rect1.height)))) << michael@0: "[3] Test against a rect that overlaps the left edge of rect1"; michael@0: rect2.x++; michael@0: michael@0: // Test against a rect that's outside of rect1 on the left michael@0: rect2.x -= rect2.width; michael@0: EXPECT_FALSE(dest.IntersectRect(rect1, rect2)) << michael@0: "[4] Test against a rect that's outside of rect1 on the left"; michael@0: // Make sure an empty rect is returned michael@0: EXPECT_FALSE(!dest.IsEmpty()) << michael@0: "[4] Make sure an empty rect is returned"; michael@0: EXPECT_TRUE(dest.IsFinite()) << "[4b] Should be finite"; michael@0: rect2.x += rect2.width; michael@0: michael@0: // Test against a rect that overlaps the top edge of rect1 michael@0: rect2.y--; michael@0: EXPECT_FALSE(!dest.IntersectRect(rect1, rect2) || michael@0: !(dest.IsEqualInterior(RectType(rect1.x, rect1.y, rect1.width, rect1.height - 1)))) << michael@0: "[5] Test against a rect that overlaps the top edge of rect1"; michael@0: EXPECT_TRUE(dest.IsFinite()) << "[5b] Should be finite"; michael@0: rect2.y++; michael@0: michael@0: // Test against a rect that's outside of rect1 on the top michael@0: rect2.y -= rect2.height; michael@0: EXPECT_FALSE(dest.IntersectRect(rect1, rect2)) << michael@0: "[6] Test against a rect that's outside of rect1 on the top"; michael@0: // Make sure an empty rect is returned michael@0: EXPECT_FALSE(!dest.IsEmpty()) << michael@0: "[6] Make sure an empty rect is returned"; michael@0: EXPECT_TRUE(dest.IsFinite()) << "[6b] Should be finite"; michael@0: rect2.y += rect2.height; michael@0: michael@0: // Test against a rect that overlaps the right edge of rect1 michael@0: rect2.x++; michael@0: EXPECT_FALSE(!dest.IntersectRect(rect1, rect2) || michael@0: !(dest.IsEqualInterior(RectType(rect1.x + 1, rect1.y, rect1.width - 1, rect1.height)))) << michael@0: "[7] Test against a rect that overlaps the right edge of rect1"; michael@0: rect2.x--; michael@0: michael@0: // Test against a rect that's outside of rect1 on the right michael@0: rect2.x += rect2.width; michael@0: EXPECT_FALSE(dest.IntersectRect(rect1, rect2)) << michael@0: "[8] Test against a rect that's outside of rect1 on the right"; michael@0: // Make sure an empty rect is returned michael@0: EXPECT_FALSE(!dest.IsEmpty()) << michael@0: "[8] Make sure an empty rect is returned"; michael@0: EXPECT_TRUE(dest.IsFinite()) << "[8b] Should be finite"; michael@0: rect2.x -= rect2.width; michael@0: michael@0: // Test against a rect that overlaps the bottom edge of rect1 michael@0: rect2.y++; michael@0: EXPECT_FALSE(!dest.IntersectRect(rect1, rect2) || michael@0: !(dest.IsEqualInterior(RectType(rect1.x, rect1.y + 1, rect1.width, rect1.height - 1)))) << michael@0: "[9] Test against a rect that overlaps the bottom edge of rect1"; michael@0: EXPECT_TRUE(dest.IsFinite()) << "[9b] Should be finite"; michael@0: rect2.y--; michael@0: michael@0: // Test against a rect that's outside of rect1 on the bottom michael@0: rect2.y += rect2.height; michael@0: EXPECT_FALSE(dest.IntersectRect(rect1, rect2)) << michael@0: "[10] Test against a rect that's outside of rect1 on the bottom"; michael@0: // Make sure an empty rect is returned michael@0: EXPECT_FALSE(!dest.IsEmpty()) << michael@0: "[10] Make sure an empty rect is returned"; michael@0: EXPECT_TRUE(dest.IsFinite()) << "[10b] Should be finite"; michael@0: rect2.y -= rect2.height; michael@0: michael@0: // Test against a rect with zero width or height michael@0: rect1.SetRect(100, 100, 100, 100); michael@0: rect2.SetRect(150, 100, 0, 100); michael@0: EXPECT_FALSE(dest.IntersectRect(rect1, rect2) || !dest.IsEmpty()) << michael@0: "[11] Intersection of rects with zero width or height should be empty"; michael@0: EXPECT_TRUE(dest.IsFinite()) << "[11b] Should be finite"; michael@0: michael@0: // Tests against a rect with negative width or height michael@0: // michael@0: michael@0: // Test against a rect with negative width michael@0: rect1.SetRect(100, 100, 100, 100); michael@0: rect2.SetRect(100, 100, -100, 100); michael@0: EXPECT_FALSE(dest.IntersectRect(rect1, rect2) || !dest.IsEmpty()) << michael@0: "[12] Intersection of rects with negative width or height should be empty"; michael@0: EXPECT_TRUE(dest.IsFinite()) << "[12b] Should be finite"; michael@0: michael@0: // Those two rects exactly overlap in some way... michael@0: // but we still want to return an empty rect michael@0: rect1.SetRect(100, 100, 100, 100); michael@0: rect2.SetRect(200, 200, -100, -100); michael@0: EXPECT_FALSE(dest.IntersectRect(rect1, rect2) || !dest.IsEmpty()) << michael@0: "[13] Intersection of rects with negative width or height should be empty"; michael@0: EXPECT_TRUE(dest.IsFinite()) << "[13b] Should be finite"; michael@0: michael@0: // Test against two identical rects with negative height michael@0: rect1.SetRect(100, 100, 100, -100); michael@0: rect2.SetRect(100, 100, 100, -100); michael@0: EXPECT_FALSE(dest.IntersectRect(rect1, rect2) || !dest.IsEmpty()) << michael@0: "[14] Intersection of rects with negative width or height should be empty"; michael@0: EXPECT_TRUE(dest.IsFinite()) << "[14b] Should be finite"; michael@0: michael@0: return true; michael@0: } michael@0: michael@0: template michael@0: static bool michael@0: TestUnion() michael@0: { michael@0: RectType rect1; michael@0: RectType rect2(10, 10, 50, 50); michael@0: RectType dest; michael@0: michael@0: // Check the case where the receiver is an empty rect michael@0: rect1.SetEmpty(); michael@0: dest.UnionRect(rect1, rect2); michael@0: EXPECT_FALSE(dest.IsEmpty() || !dest.IsEqualInterior(rect2)) << michael@0: "[1] Check the case where the receiver is an empty rect"; michael@0: EXPECT_TRUE(dest.IsFinite()) << "[1b] Should be finite"; michael@0: michael@0: // Check the case where the source rect is an empty rect michael@0: rect1 = rect2; michael@0: rect2.SetEmpty(); michael@0: dest.UnionRect(rect1, rect2); michael@0: EXPECT_FALSE(dest.IsEmpty() || !dest.IsEqualInterior(rect1)) << michael@0: "[2] Check the case where the source rect is an empty rect"; michael@0: EXPECT_TRUE(dest.IsFinite()) << "[2b] Should be finite"; michael@0: michael@0: // Test the case where both rects are empty michael@0: rect1.SetEmpty(); michael@0: rect2.SetEmpty(); michael@0: dest.UnionRect(rect1, rect2); michael@0: EXPECT_FALSE(!dest.IsEmpty()) << michael@0: "[3] Test the case where both rects are empty"; michael@0: EXPECT_TRUE(dest.IsFinite()) << "[3b] Should be finite"; michael@0: michael@0: // Test union case where the two rects don't overlap at all michael@0: rect1.SetRect(10, 10, 50, 50); michael@0: rect2.SetRect(100, 100, 50, 50); michael@0: dest.UnionRect(rect1, rect2); michael@0: EXPECT_FALSE(dest.IsEmpty() || michael@0: !(dest.IsEqualInterior(RectType(rect1.x, rect1.y, rect2.XMost() - rect1.x, rect2.YMost() - rect1.y)))) << michael@0: "[4] Test union case where the two rects don't overlap at all"; michael@0: EXPECT_TRUE(dest.IsFinite()) << "[4b] Should be finite"; michael@0: michael@0: // Test union case where the two rects overlap michael@0: rect1.SetRect(30, 30, 50, 50); michael@0: rect2.SetRect(10, 10, 50, 50); michael@0: dest.UnionRect(rect1, rect2); michael@0: EXPECT_FALSE(dest.IsEmpty() || michael@0: !(dest.IsEqualInterior(RectType(rect2.x, rect2.y, rect1.XMost() - rect2.x, rect1.YMost() - rect2.y)))) << michael@0: "[5] Test union case where the two rects overlap"; michael@0: EXPECT_TRUE(dest.IsFinite()) << "[5b] Should be finite"; michael@0: michael@0: return true; michael@0: } michael@0: michael@0: static bool michael@0: TestFiniteGfx() michael@0: { michael@0: // Doesn't appear that __builtin_inf() and __builtin_nan() are available on michael@0: // all compilers, so go the old fashioned way for inf and nan. michael@0: float posInf = 1.0/0.0; michael@0: float negInf = -1.0/0.0; michael@0: float justNaN = 0.0/0.0; michael@0: michael@0: gfxFloat values[4] = {5.0, 10.0, 15.0, 20.0}; michael@0: michael@0: // Try the "non-finite" values for x, y, width, height, one at a time michael@0: for (int i=0; i<4; i+=1) { michael@0: values[i] = posInf; michael@0: gfxRect rectPosInf(values[0], values[1], values[2], values[3]); michael@0: EXPECT_FALSE(rectPosInf.IsFinite()) << "For +inf (" << values[0] << "," << values[1] << "," << values[2] << "," << values[3] << ")"; michael@0: michael@0: values[i] = negInf; michael@0: gfxRect rectNegInf(values[0], values[1], values[2], values[3]); michael@0: EXPECT_FALSE(rectNegInf.IsFinite()) << "For -inf (" << values[0] << "," << values[1] << "," << values[2] << "," << values[3] << ")"; michael@0: michael@0: values[i] = justNaN; michael@0: gfxRect rectNaN(values[0], values[1], values[2], values[3]); michael@0: EXPECT_FALSE(rectNaN.IsFinite()) << "For NaN (" << values[0] << "," << values[1] << "," << values[2] << "," << values[3] << ")"; michael@0: michael@0: // Reset to a finite value... michael@0: values[i] = 5.0*i; michael@0: } michael@0: michael@0: return true; michael@0: } michael@0: michael@0: TEST(Gfx, nsRect) { michael@0: TestConstructors(); michael@0: TestEqualityOperator(); michael@0: TestContainment(); michael@0: TestIntersects(); michael@0: TestIntersection(); michael@0: TestUnion(); michael@0: } michael@0: michael@0: TEST(Gfx, nsIntRect) { michael@0: TestConstructors(); michael@0: TestEqualityOperator(); michael@0: TestContainment(); michael@0: TestIntersects(); michael@0: TestIntersection(); michael@0: TestUnion(); michael@0: } michael@0: michael@0: TEST(Gfx, gfxRect) { michael@0: TestConstructors(); michael@0: // Skip TestEqualityOperator(); as gfxRect::operator== is private michael@0: TestContainment(); michael@0: TestIntersects(); michael@0: TestIntersection(); michael@0: TestUnion(); michael@0: TestFiniteGfx(); michael@0: }