From c0b45ceae641ff4c8ac30a43c85713d8bd18e9fd Mon Sep 17 00:00:00 2001 From: Milan Sreckovic Date: Tue, 13 Aug 2013 14:48:17 -0400 Subject: [PATCH] Bug 903526 - Add BaseRect::IsFinite() method. r=bas --- gfx/2d/BaseRect.h | 10 ++++++ gfx/tests/gtest/TestRect.cpp | 62 ++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+) diff --git a/gfx/2d/BaseRect.h b/gfx/2d/BaseRect.h index 2ca68e2b1f2..dbf36bff04d 100644 --- a/gfx/2d/BaseRect.h +++ b/gfx/2d/BaseRect.h @@ -9,6 +9,7 @@ #include #include #include +#include "nsMathUtils.h" namespace mozilla { namespace gfx { @@ -56,6 +57,15 @@ struct BaseRect { bool IsEmpty() const { return height <= 0 || width <= 0; } void SetEmpty() { width = height = 0; } + // "Finite" means not inf and not NaN + bool IsFinite() const + { + return (NS_finite(x) && + NS_finite(y) && + NS_finite(width) && + NS_finite(height)); + } + // Returns true if this rectangle contains the interior of aRect. Always // returns true if aRect is empty, and always returns false is aRect is // nonempty but this rect is empty. diff --git a/gfx/tests/gtest/TestRect.cpp b/gfx/tests/gtest/TestRect.cpp index 805114eef34..4d7f3722a67 100644 --- a/gfx/tests/gtest/TestRect.cpp +++ b/gfx/tests/gtest/TestRect.cpp @@ -6,6 +6,7 @@ #include "gtest/gtest.h" #include "nsRect.h" +#include "gfxRect.h" #ifdef XP_WIN #include #endif @@ -30,6 +31,11 @@ TestConstructors() rect2.width == rect2.width && rect2.height == rect2.height) << "[2] Make sure the rectangle was properly initialized with copy constructor"; + + EXPECT_TRUE(!rect1.IsEmpty() && rect1.IsFinite() && + !rect2.IsEmpty() && rect2.IsFinite()) << + "[3] These rectangles are not empty and are finite"; + return true; } @@ -219,6 +225,7 @@ TestIntersection() // Make sure an empty rect is returned EXPECT_FALSE(!dest.IsEmpty()) << "[4] Make sure an empty rect is returned"; + EXPECT_TRUE(dest.IsFinite()) << "[4b] Should be finite"; rect2.x += rect2.width; // Test against a rect that overlaps the top edge of rect1 @@ -226,6 +233,7 @@ TestIntersection() EXPECT_FALSE(!dest.IntersectRect(rect1, rect2) || !(dest.IsEqualInterior(RectType(rect1.x, rect1.y, rect1.width, rect1.height - 1)))) << "[5] Test against a rect that overlaps the top edge of rect1"; + EXPECT_TRUE(dest.IsFinite()) << "[5b] Should be finite"; rect2.y++; // Test against a rect that's outside of rect1 on the top @@ -235,6 +243,7 @@ TestIntersection() // Make sure an empty rect is returned EXPECT_FALSE(!dest.IsEmpty()) << "[6] Make sure an empty rect is returned"; + EXPECT_TRUE(dest.IsFinite()) << "[6b] Should be finite"; rect2.y += rect2.height; // Test against a rect that overlaps the right edge of rect1 @@ -251,6 +260,7 @@ TestIntersection() // Make sure an empty rect is returned EXPECT_FALSE(!dest.IsEmpty()) << "[8] Make sure an empty rect is returned"; + EXPECT_TRUE(dest.IsFinite()) << "[8b] Should be finite"; rect2.x -= rect2.width; // Test against a rect that overlaps the bottom edge of rect1 @@ -258,6 +268,7 @@ TestIntersection() EXPECT_FALSE(!dest.IntersectRect(rect1, rect2) || !(dest.IsEqualInterior(RectType(rect1.x, rect1.y + 1, rect1.width, rect1.height - 1)))) << "[9] Test against a rect that overlaps the bottom edge of rect1"; + EXPECT_TRUE(dest.IsFinite()) << "[9b] Should be finite"; rect2.y--; // Test against a rect that's outside of rect1 on the bottom @@ -267,6 +278,7 @@ TestIntersection() // Make sure an empty rect is returned EXPECT_FALSE(!dest.IsEmpty()) << "[10] Make sure an empty rect is returned"; + EXPECT_TRUE(dest.IsFinite()) << "[10b] Should be finite"; rect2.y -= rect2.height; // Test against a rect with zero width or height @@ -274,6 +286,7 @@ TestIntersection() rect2.SetRect(150, 100, 0, 100); EXPECT_FALSE(dest.IntersectRect(rect1, rect2) || !dest.IsEmpty()) << "[11] Intersection of rects with zero width or height should be empty"; + EXPECT_TRUE(dest.IsFinite()) << "[11b] Should be finite"; // Tests against a rect with negative width or height // @@ -283,6 +296,7 @@ TestIntersection() rect2.SetRect(100, 100, -100, 100); EXPECT_FALSE(dest.IntersectRect(rect1, rect2) || !dest.IsEmpty()) << "[12] Intersection of rects with negative width or height should be empty"; + EXPECT_TRUE(dest.IsFinite()) << "[12b] Should be finite"; // Those two rects exactly overlap in some way... // but we still want to return an empty rect @@ -290,12 +304,14 @@ TestIntersection() rect2.SetRect(200, 200, -100, -100); EXPECT_FALSE(dest.IntersectRect(rect1, rect2) || !dest.IsEmpty()) << "[13] Intersection of rects with negative width or height should be empty"; + EXPECT_TRUE(dest.IsFinite()) << "[13b] Should be finite"; // Test against two identical rects with negative height rect1.SetRect(100, 100, 100, -100); rect2.SetRect(100, 100, 100, -100); EXPECT_FALSE(dest.IntersectRect(rect1, rect2) || !dest.IsEmpty()) << "[14] Intersection of rects with negative width or height should be empty"; + EXPECT_TRUE(dest.IsFinite()) << "[14b] Should be finite"; return true; } @@ -313,6 +329,7 @@ TestUnion() dest.UnionRect(rect1, rect2); EXPECT_FALSE(dest.IsEmpty() || !dest.IsEqualInterior(rect2)) << "[1] Check the case where the receiver is an empty rect"; + EXPECT_TRUE(dest.IsFinite()) << "[1b] Should be finite"; // Check the case where the source rect is an empty rect rect1 = rect2; @@ -320,6 +337,7 @@ TestUnion() dest.UnionRect(rect1, rect2); EXPECT_FALSE(dest.IsEmpty() || !dest.IsEqualInterior(rect1)) << "[2] Check the case where the source rect is an empty rect"; + EXPECT_TRUE(dest.IsFinite()) << "[2b] Should be finite"; // Test the case where both rects are empty rect1.SetEmpty(); @@ -327,6 +345,7 @@ TestUnion() dest.UnionRect(rect1, rect2); EXPECT_FALSE(!dest.IsEmpty()) << "[3] Test the case where both rects are empty"; + EXPECT_TRUE(dest.IsFinite()) << "[3b] Should be finite"; // Test union case where the two rects don't overlap at all rect1.SetRect(10, 10, 50, 50); @@ -335,6 +354,7 @@ TestUnion() EXPECT_FALSE(dest.IsEmpty() || !(dest.IsEqualInterior(RectType(rect1.x, rect1.y, rect2.XMost() - rect1.x, rect2.YMost() - rect1.y)))) << "[4] Test union case where the two rects don't overlap at all"; + EXPECT_TRUE(dest.IsFinite()) << "[4b] Should be finite"; // Test union case where the two rects overlap rect1.SetRect(30, 30, 50, 50); @@ -343,6 +363,39 @@ TestUnion() EXPECT_FALSE(dest.IsEmpty() || !(dest.IsEqualInterior(RectType(rect2.x, rect2.y, rect1.XMost() - rect2.x, rect1.YMost() - rect2.y)))) << "[5] Test union case where the two rects overlap"; + EXPECT_TRUE(dest.IsFinite()) << "[5b] Should be finite"; + + return true; +} + +static bool +TestFiniteGfx() +{ + // Doesn't appear that __builtin_inf() and __builtin_nan() are available on + // all compilers, so go the old fashioned way for inf and nan. + float posInf = 1.0/0.0; + float negInf = -1.0/0.0; + float justNaN = 0.0/0.0; + + gfxFloat values[4] = {5.0, 10.0, 15.0, 20.0}; + + // Try the "non-finite" values for x, y, width, height, one at a time + for (int i=0; i<4; i+=1) { + values[i] = posInf; + gfxRect rectPosInf(values[0], values[1], values[2], values[3]); + EXPECT_FALSE(rectPosInf.IsFinite()) << "For +inf (" << values[0] << "," << values[1] << "," << values[2] << "," << values[3] << ")"; + + values[i] = negInf; + gfxRect rectNegInf(values[0], values[1], values[2], values[3]); + EXPECT_FALSE(rectNegInf.IsFinite()) << "For -inf (" << values[0] << "," << values[1] << "," << values[2] << "," << values[3] << ")"; + + values[i] = justNaN; + gfxRect rectNaN(values[0], values[1], values[2], values[3]); + EXPECT_FALSE(rectNaN.IsFinite()) << "For NaN (" << values[0] << "," << values[1] << "," << values[2] << "," << values[3] << ")"; + + // Reset to a finite value... + values[i] = 5.0*i; + } return true; } @@ -365,3 +418,12 @@ TEST(Gfx, nsIntRect) { TestUnion(); } +TEST(Gfx, gfxRect) { + TestConstructors(); + // Skip TestEqualityOperator(); as gfxRect::operator== is private + TestContainment(); + TestIntersects(); + TestIntersection(); + TestUnion(); + TestFiniteGfx(); +}