diff options
-rw-r--r-- | src/core/SkRect.cpp | 11 | ||||
-rw-r--r-- | tests/ScalarTest.cpp | 52 |
2 files changed, 60 insertions, 3 deletions
diff --git a/src/core/SkRect.cpp b/src/core/SkRect.cpp index 5e3d93c339..687febe3fc 100644 --- a/src/core/SkRect.cpp +++ b/src/core/SkRect.cpp @@ -90,19 +90,24 @@ void SkRect::set(const SkPoint pts[], int count) { 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 ef7db324c8..524d775549 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 @@ static void test_isfinite(skiatest::Reporter* reporter) { } } } + + test_isRectFinite(reporter); #endif } |