diff options
author | reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2012-05-16 13:35:36 +0000 |
---|---|---|
committer | reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2012-05-16 13:35:36 +0000 |
commit | 7b463acd46b8df866d3a27fbaf69b0090c842d1e (patch) | |
tree | a97acffe381eab10085cbf5fee96249ddd6ba926 | |
parent | 5dd510f1d277a31752a4c6046c4e42385605a393 (diff) |
speedup SkRect::isFinite() (almost 2x)
add SkRect:set(p0, p1) for quick bounds of 2 points
git-svn-id: http://skia.googlecode.com/svn/trunk@3967 2bbb7eff-a529-9590-31e7-b0007b416f81
-rw-r--r-- | include/core/SkRect.h | 24 | ||||
-rw-r--r-- | tests/InfRectTest.cpp | 24 |
2 files changed, 32 insertions, 16 deletions
diff --git a/include/core/SkRect.h b/include/core/SkRect.h index 2fa3256e1c..e055c3d70b 100644 --- a/include/core/SkRect.h +++ b/include/core/SkRect.h @@ -75,7 +75,7 @@ struct SK_API SkIRect { * Return true if the rectangle's width or height are <= 0 */ bool isEmpty() const { return fLeft >= fRight || fTop >= fBottom; } - + friend bool operator==(const SkIRect& a, const SkIRect& b) { return !memcmp(&a, &b, sizeof(a)); } @@ -354,13 +354,18 @@ struct SK_API SkRect { */ bool isFinite() const { #ifdef SK_SCALAR_IS_FLOAT - // x * 0 will be NaN iff x is infinity or NaN. - // a + b will be NaN iff either a or b is NaN. - float value = fLeft * 0 + fTop * 0 + fRight * 0 + fBottom * 0; + float accum = 0; + accum *= fLeft; + accum *= fTop; + accum *= fRight; + accum *= fBottom; - // value is either NaN or it is finite (zero). + // accum is either NaN or it is finite (zero). + SkASSERT(0 == accum || !(accum == accum)); + // value==value will be true iff value is not NaN - return value == value; + // TODO: is it faster to say !accum or accum==accum? + return accum == accum; #else // use bit-or for speed, since we don't care about short-circuting the // tests, and we expect the common case will be that we need to check all. @@ -436,6 +441,13 @@ struct SK_API SkRect { this->set(pts, count); } + void set(const SkPoint& p0, const SkPoint& p1) { + fLeft = SkMinScalar(p0.fX, p1.fX); + fRight = SkMaxScalar(p0.fX, p1.fX); + fTop = SkMinScalar(p0.fY, p1.fY); + fBottom = SkMaxScalar(p0.fY, p1.fY); + } + void setXYWH(SkScalar x, SkScalar y, SkScalar width, SkScalar height) { fLeft = x; fTop = y; diff --git a/tests/InfRectTest.cpp b/tests/InfRectTest.cpp index 12356d9c2f..1dc6ca7d0c 100644 --- a/tests/InfRectTest.cpp +++ b/tests/InfRectTest.cpp @@ -25,24 +25,28 @@ static void check_invalid(skiatest::Reporter* reporter, // as one of its coordinates. static void TestInfRect(skiatest::Reporter* reporter) { #ifdef SK_SCALAR_IS_FLOAT - float invalid = 1 / make_zero(); // infinity + float inf = 1 / make_zero(); // infinity + float nan = inf * 0; + SkASSERT(!(nan == nan)); #else - SkFixed invalid = SK_FixedNaN; + SkFixed inf = SK_FixedNaN; + SkFixed nan = SK_FixedNaN; #endif SkScalar small = SkIntToScalar(10); SkScalar big = SkIntToScalar(100); + REPORTER_ASSERT(reporter, SkRect::MakeEmpty().isFinite()); + SkRect rect = SkRect::MakeXYWH(small, small, big, big); REPORTER_ASSERT(reporter, rect.isFinite()); - check_invalid(reporter, small, small, big, invalid); - check_invalid(reporter, small, small, invalid, big); - check_invalid(reporter, small, invalid, big, big); - check_invalid(reporter, invalid, small, big, big); - check_invalid(reporter, small, small, big, -invalid); - check_invalid(reporter, small, small, -invalid, big); - check_invalid(reporter, small, -invalid, big, big); - check_invalid(reporter, -invalid, small, big, big); + const SkScalar invalid[] = { nan, inf, -inf }; + for (size_t i = 0; i < SK_ARRAY_COUNT(invalid); ++i) { + check_invalid(reporter, small, small, big, invalid[i]); + check_invalid(reporter, small, small, invalid[i], big); + check_invalid(reporter, small, invalid[i], big, big); + check_invalid(reporter, invalid[i], small, big, big); + } } // need tests for SkStrSearch |