/** SkScalarIsNaN(n) returns true if argument is not a number
*/
static inline bool SkScalarIsNaN(float x) { return x != x; }
+ /** Returns true if x is not NaN and not infinite */
+ static inline bool SkScalarIsFinite(float x) {
+ uint32_t bits = SkFloat2Bits(x); // need unsigned for our shifts
+ int exponent = bits << 1 >> 24;
+ return exponent != 0xFF;
+ }
/** SkIntToScalar(n) returns its integer argument as an SkScalar
*/
#define SkIntToScalar(n) ((float)(n))
#define SK_ScalarMin SK_FixedMin
#define SK_ScalarNaN SK_FixedNaN
#define SkScalarIsNaN(x) ((x) == SK_FixedNaN)
+ #define SkScalarIsFinite(x) ((x) != SK_FixedNaN)
+
#define SkIntToScalar(n) SkIntToFixed(n)
#define SkFixedToScalar(x) (x)
#define SkScalarToFixed(x) (x)
*/
#include "SkRect.h"
-#include <limits>
void SkIRect::join(int32_t left, int32_t top, int32_t right, int32_t bottom)
{
/////////////////////////////////////////////////////////////////////////////
-template <typename NumType> static inline bool isValidRange(const NumType& x)
-{
- static const NumType max = std::numeric_limits<NumType>::max();
- return x >= -max && x <= max;
-}
-
-
-bool SkRect::hasValidCoordinates() const
-{
- return isValidRange<SkScalar>(fLeft) && isValidRange<SkScalar>(fRight) &&
- isValidRange<SkScalar>(fTop) && isValidRange<SkScalar>(fBottom);
+bool SkRect::hasValidCoordinates() const {
+ return SkScalarIsFinite(fLeft) &&
+ SkScalarIsFinite(fTop) &&
+ SkScalarIsFinite(fRight) &&
+ SkScalarIsFinite(fBottom);
}
void SkRect::sort()
} else {
#ifdef SK_SCALAR_SLOW_COMPARES
int32_t l, t, r, b;
-
+
l = r = SkScalarAs2sCompliment(pts[0].fX);
t = b = SkScalarAs2sCompliment(pts[0].fY);
-
+
for (int i = 1; i < count; i++) {
int32_t x = SkScalarAs2sCompliment(pts[i].fX);
int32_t y = SkScalarAs2sCompliment(pts[i].fY);
-
+
if (x < l) l = x; else if (x > r) r = x;
if (y < t) t = y; else if (y > b) b = y;
}
// do nothing if the params are empty
if (left >= right || top >= bottom)
return;
-
+
// if we are empty, just assign
if (fLeft >= fRight || fTop >= fBottom)
this->set(left, top, right, bottom);
}
}
+static float make_zero() {
+ return sk_float_sin(0);
+}
+
+static void unittest_isfinite(skiatest::Reporter* reporter) {
+#ifdef SK_SCALAR_IS_FLOAT
+ float nan = ::asin(2);
+ float inf = 1.0 / make_zero();
+ float big = 3.40282e+038;
+
+ REPORTER_ASSERT(reporter, SkScalarIsNaN(nan));
+ REPORTER_ASSERT(reporter, !SkScalarIsNaN(inf));
+ REPORTER_ASSERT(reporter, !SkScalarIsNaN(big));
+ REPORTER_ASSERT(reporter, !SkScalarIsNaN(-big));
+ REPORTER_ASSERT(reporter, !SkScalarIsNaN(0));
+
+ REPORTER_ASSERT(reporter, !SkScalarIsFinite(nan));
+ REPORTER_ASSERT(reporter, !SkScalarIsFinite(inf));
+ REPORTER_ASSERT(reporter, SkScalarIsFinite(big));
+ REPORTER_ASSERT(reporter, SkScalarIsFinite(-big));
+ REPORTER_ASSERT(reporter, SkScalarIsFinite(0));
+#else
+ REPORTER_ASSERT(reporter, SkScalarIsNaN(0x80000000));
+ REPORTER_ASSERT(reporter, !SkScalarIsNaN(0x7FFFFFFF));
+ REPORTER_ASSERT(reporter, !SkScalarIsNaN(0x80000001));
+ REPORTER_ASSERT(reporter, !SkScalarIsNaN(0));
+
+ REPORTER_ASSERT(reporter, !SkScalarIsFinite(0x80000000));
+ REPORTER_ASSERT(reporter, SkScalarIsFinite(0x7FFFFFFF));
+ REPORTER_ASSERT(reporter, SkScalarIsFinite(0x80000001));
+ REPORTER_ASSERT(reporter, SkScalarIsFinite(0));
+#endif
+}
+
#endif
static void test_muldiv255(skiatest::Reporter* reporter) {
#ifdef SK_CAN_USE_FLOAT
unittest_fastfloat(reporter);
+ unittest_isfinite(reporter);
#endif
#ifdef SkLONGLONG