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
This commit is contained in:
parent
63c57613b8
commit
30d90ebe7c
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user