aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-05-16 13:35:36 +0000
committerGravatar reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-05-16 13:35:36 +0000
commit7b463acd46b8df866d3a27fbaf69b0090c842d1e (patch)
treea97acffe381eab10085cbf5fee96249ddd6ba926
parent5dd510f1d277a31752a4c6046c4e42385605a393 (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.h24
-rw-r--r--tests/InfRectTest.cpp24
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