Bug 903526 - Add BaseRect::IsFinite() method. r=bas

This commit is contained in:
Milan Sreckovic 2013-08-13 14:48:17 -04:00
parent 01ba992f4f
commit c0b45ceae6
2 changed files with 72 additions and 0 deletions

View File

@ -9,6 +9,7 @@
#include <cmath>
#include <mozilla/Assertions.h>
#include <algorithm>
#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.

View File

@ -6,6 +6,7 @@
#include "gtest/gtest.h"
#include "nsRect.h"
#include "gfxRect.h"
#ifdef XP_WIN
#include <windows.h>
#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<nsIntRect>();
}
TEST(Gfx, gfxRect) {
TestConstructors<gfxRect>();
// Skip TestEqualityOperator<gfxRect>(); as gfxRect::operator== is private
TestContainment<gfxRect>();
TestIntersects<gfxRect>();
TestIntersection<gfxRect>();
TestUnion<gfxRect>();
TestFiniteGfx();
}