Add pinned versions of *ToFixed.

BUG=skia:4632
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1707023002

Review URL: https://codereview.chromium.org/1707023002
This commit is contained in:
benjaminwagner 2016-04-07 09:23:11 -07:00 committed by Commit bot
parent 73add93a9c
commit 70f1a6c64e
2 changed files with 67 additions and 9 deletions

View File

@ -9,6 +9,8 @@
#define SkFixed_DEFINED
#include "SkScalar.h"
#include "math.h"
#include "SkTypes.h"
/** \file SkFixed.h
@ -29,15 +31,18 @@ typedef int32_t SkFixed;
#define SK_FixedRoot2Over2 (0xB505)
#define SkFixedToFloat(x) ((x) * 1.52587890625e-5f)
#if 1
#define SkFloatToFixed(x) ((SkFixed)((x) * SK_Fixed1))
#else
// pins over/under flows to max/min int32 (slower than just a cast)
static inline SkFixed SkFloatToFixed(float x) {
int64_t n = x * SK_Fixed1;
return (SkFixed)n;
}
#endif
#define SkFloatToFixed(x) ((SkFixed)((x) * SK_Fixed1))
// Pins over/under flows to SK_FixedMax/SK_FixedMin (slower than just a cast).
static inline SkFixed SkFloatPinToFixed(float x) {
x *= SK_Fixed1;
// Casting float to int outside the range of the target type (int32_t) is undefined behavior.
if (x >= SK_FixedMax) return SK_FixedMax;
if (x <= SK_FixedMin) return SK_FixedMin;
const SkFixed result = static_cast<SkFixed>(x);
SkASSERT(truncf(x) == static_cast<float>(result));
return result;
}
#ifdef SK_DEBUG
static inline SkFixed SkFloatToFixed_Check(float x) {
@ -53,6 +58,17 @@ typedef int32_t SkFixed;
#define SkFixedToDouble(x) ((x) * 1.52587890625e-5)
#define SkDoubleToFixed(x) ((SkFixed)((x) * SK_Fixed1))
// Pins over/under flows to SK_FixedMax/SK_FixedMin (slower than just a cast).
static inline SkFixed SkDoublePinToFixed(double x) {
x *= SK_Fixed1;
// Casting double to int outside the range of the target type (int32_t) is undefined behavior.
if (x >= SK_FixedMax) return SK_FixedMax;
if (x <= SK_FixedMin) return SK_FixedMin;
const SkFixed result = static_cast<SkFixed>(x);
SkASSERT(trunc(x) == static_cast<double>(result));
return result;
}
/** Converts an integer to a SkFixed, asserting that the result does not overflow
a 32 bit signed integer
*/
@ -147,11 +163,13 @@ inline SkFixed SkFixedMul_longlong(SkFixed a, SkFixed b) {
#define SkFixedToScalar(x) SkFixedToFloat(x)
#define SkScalarToFixed(x) SkFloatToFixed(x)
#define SkScalarPinToFixed(x) SkFloatPinToFixed(x)
#else // SK_SCALAR_IS_DOUBLE
#define SkFixedToScalar(x) SkFixedToDouble(x)
#define SkScalarToFixed(x) SkDoubleToFixed(x)
#define SkScalarPinToFixed(x) SkDoublePinToFixed(x)
#endif

View File

@ -5,6 +5,8 @@
* found in the LICENSE file.
*/
#include "float.h"
#include "SkColorPriv.h"
#include "SkEndian.h"
#include "SkFixed.h"
@ -697,3 +699,41 @@ DEF_TEST(divmod_s32, r) {
DEF_TEST(divmod_s64, r) {
test_divmod<int64_t>(r);
}
DEF_TEST(PinToFixed, reporter) {
// double
REPORTER_ASSERT(reporter, 0 == SkDoublePinToFixed(0.0));
REPORTER_ASSERT(reporter, 0x10000 == SkDoublePinToFixed(1.0));
REPORTER_ASSERT(reporter, 0x7FFFFFFE == SkDoublePinToFixed(32767.999984741));
REPORTER_ASSERT(reporter, 0x7FFFFFFF == SkDoublePinToFixed(32767.999984742));
REPORTER_ASSERT(reporter, 0x7FFFFFFF == SkDoublePinToFixed(32767.999999999));
REPORTER_ASSERT(reporter, 0x7FFFFFFF == SkDoublePinToFixed(32768.0));
REPORTER_ASSERT(reporter, 0x7FFFFFFF == SkDoublePinToFixed(5e10));
REPORTER_ASSERT(reporter, 0x7FFFFFFF == SkDoublePinToFixed(DBL_MAX));
REPORTER_ASSERT(reporter, -0x10000 == SkDoublePinToFixed(-1.0));
// SK_FixedMin is defined to be -SK_FixedMax.
REPORTER_ASSERT(reporter, -0x7FFFFFFE == SkDoublePinToFixed(-32767.999984741));
REPORTER_ASSERT(reporter, -0x7FFFFFFF == SkDoublePinToFixed(-32767.999984742));
REPORTER_ASSERT(reporter, -0x7FFFFFFF == SkDoublePinToFixed(-32767.999999999));
REPORTER_ASSERT(reporter, -0x7FFFFFFF == SkDoublePinToFixed(-32768.0));
REPORTER_ASSERT(reporter, -0x7FFFFFFF == SkDoublePinToFixed(-5e10));
REPORTER_ASSERT(reporter, -0x7FFFFFFF == SkDoublePinToFixed(-DBL_MAX));
// float
REPORTER_ASSERT(reporter, 0 == SkFloatPinToFixed(0.0f));
REPORTER_ASSERT(reporter, 0x10000 == SkFloatPinToFixed(1.0f));
// SkFixed has more precision than float near SK_FixedMax, so SkFloatPinToFixed will never
// produce output between 0x7FFFFF80 and 0x7FFFFFFF.
REPORTER_ASSERT(reporter, 0x7FFFFF80 == SkFloatPinToFixed(32767.9990f));
REPORTER_ASSERT(reporter, 0x7FFFFFFF == SkFloatPinToFixed(32767.9991f));
REPORTER_ASSERT(reporter, 0x7FFFFFFF == SkFloatPinToFixed(32768.0f));
REPORTER_ASSERT(reporter, 0x7FFFFFFF == SkFloatPinToFixed(5e10f));
REPORTER_ASSERT(reporter, 0x7FFFFFFF == SkFloatPinToFixed(FLT_MAX));
REPORTER_ASSERT(reporter, -0x10000 == SkFloatPinToFixed(-1.0f));
// SK_FixedMin is defined to be -SK_FixedMax.
REPORTER_ASSERT(reporter, -0x7FFFFF80 == SkFloatPinToFixed(-32767.9990f));
REPORTER_ASSERT(reporter, -0x7FFFFFFF == SkFloatPinToFixed(-32767.9991f));
REPORTER_ASSERT(reporter, -0x7FFFFFFF == SkFloatPinToFixed(-32768.0f));
REPORTER_ASSERT(reporter, -0x7FFFFFFF == SkFloatPinToFixed(-5e10f));
REPORTER_ASSERT(reporter, -0x7FFFFFFF == SkFloatPinToFixed(-FLT_MAX));
}