Use x*0 instead of x!=x to detect non-finite values, since x*0 also detects infinities
and it is faster (at least faster in SkRect::set).

Add unittest for SkRect::set to see that it correctly detects NaN and infinities.




git-svn-id: http://skia.googlecode.com/svn/trunk@3936 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/core/SkRect.cpp b/src/core/SkRect.cpp
index 5e3d93c..687febe 100644
--- a/src/core/SkRect.cpp
+++ b/src/core/SkRect.cpp
@@ -90,19 +90,24 @@
 
         l = r = pts[0].fX;
         t = b = pts[0].fY;
-        SkFLOATCODE(isNaN = (l != l) | (t != t);)
+
+        // If all of the points are finite, accum should stay 0. If we encounter
+        // a NaN or infinity, then accum should become NaN.
+        SkFLOATCODE(float accum = 0;)
 
         for (int i = 1; i < count; i++) {
             SkScalar x = pts[i].fX;
             SkScalar y = pts[i].fY;
-            SkFLOATCODE(isNaN |= (x != x) | (y != y);)
+
+            SkFLOATCODE(accum *= x; accum *= y;)
 
             if (x < l) l = x; else if (x > r) r = x;
             if (y < t) t = y; else if (y > b) b = y;
         }
 
 #ifdef SK_SCALAR_IS_FLOAT
-        if (isNaN) {
+        SkASSERT(!accum || !SkScalarIsFinite(accum));
+        if (accum) {
             l = t = r = b = 0;
         }
 #endif
diff --git a/tests/ScalarTest.cpp b/tests/ScalarTest.cpp
index ef7db32..524d775 100644
--- a/tests/ScalarTest.cpp
+++ b/tests/ScalarTest.cpp
@@ -10,9 +10,59 @@
 #include "SkMath.h"
 #include "SkPoint.h"
 #include "SkRandom.h"
+#include "SkRect.h"
 
 #ifdef SK_CAN_USE_FLOAT
 
+struct PointSet {
+    const SkPoint* fPts;
+    size_t         fCount;
+    bool           fIsFinite;
+};
+
+static void test_isRectFinite(skiatest::Reporter* reporter) {
+    static const SkPoint gF0[] = {
+        { 0, 0 }, { 1, 1 }
+    };
+    static const SkPoint gF1[] = {
+        { 0, 0 }, { 1, 1 }, { 99.234f, -42342 }
+    };
+
+    static const SkPoint gI0[] = {
+        { 0, 0 }, { 1, 1 }, { 99.234f, -42342 }, { SK_ScalarNaN, 3 }, { 2, 3 },
+    };
+    static const SkPoint gI1[] = {
+        { 0, 0 }, { 1, 1 }, { 99.234f, -42342 }, { 3, SK_ScalarNaN }, { 2, 3 },
+    };
+    static const SkPoint gI2[] = {
+        { 0, 0 }, { 1, 1 }, { 99.234f, -42342 }, { SK_ScalarInfinity, 3 }, { 2, 3 },
+    };
+    static const SkPoint gI3[] = {
+        { 0, 0 }, { 1, 1 }, { 99.234f, -42342 }, { 3, SK_ScalarInfinity }, { 2, 3 },
+    };
+
+    static const struct {
+        const SkPoint* fPts;
+        size_t         fCount;
+        bool           fIsFinite;
+    } gSets[] = {
+        { gF0, SK_ARRAY_COUNT(gF0), true },
+        { gF1, SK_ARRAY_COUNT(gF1), true },
+
+        { gI0, SK_ARRAY_COUNT(gI0), false },
+        { gI1, SK_ARRAY_COUNT(gI1), false },
+        { gI2, SK_ARRAY_COUNT(gI2), false },
+        { gI3, SK_ARRAY_COUNT(gI3), false },
+    };
+    
+    for (size_t i = 0; i < SK_ARRAY_COUNT(gSets); ++i) {
+        SkRect r;
+        r.set(gSets[i].fPts, gSets[i].fCount);
+        bool rectIsFinite = !r.isEmpty();
+        REPORTER_ASSERT(reporter, gSets[i].fIsFinite == rectIsFinite);
+    }
+}
+
 static bool isFinite_int(float x) {
     uint32_t bits = SkFloat2Bits(x);    // need unsigned for our shifts
     int exponent = bits << 1 >> 24;
@@ -132,6 +182,8 @@
             }
         }
     }
+    
+    test_isRectFinite(reporter);
 #endif
 }