blob: 1628f6e7537b7e0150e34f233fd72ca87ca3b8d2 [file] [log] [blame]
reed@android.com8a1c16f2008-12-17 15:59:43 +00001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef SkFloatBits_DEFINED
18#define SkFloatBits_DEFINED
19
20#include "SkTypes.h"
21
22/** Convert a sign-bit int (i.e. float interpreted as int) into a 2s compliement
23 int. This also converts -0 (0x80000000) to 0. Doing this to a float allows
24 it to be compared using normal C operators (<, <=, etc.)
25*/
26static inline int32_t SkSignBitTo2sCompliment(int32_t x) {
27 if (x < 0) {
28 x &= 0x7FFFFFFF;
29 x = -x;
30 }
31 return x;
32}
33
34/** Convert a 2s compliment int to a sign-bit (i.e. int interpreted as float).
35 This undoes the result of SkSignBitTo2sCompliment().
36 */
37static inline int32_t Sk2sComplimentToSignBit(int32_t x) {
38 int sign = x >> 31;
39 // make x positive
40 x = (x ^ sign) - sign;
41 // set the sign bit as needed
42 x |= sign << 31;
43 return x;
44}
45
46/** Given the bit representation of a float, return its value cast to an int.
47 If the value is out of range, or NaN, return return +/- SK_MaxS32
48*/
49int32_t SkFloatBits_toIntCast(int32_t floatBits);
50
51/** Given the bit representation of a float, return its floor as an int.
52 If the value is out of range, or NaN, return return +/- SK_MaxS32
53 */
54int32_t SkFloatBits_toIntFloor(int32_t floatBits);
55
56/** Given the bit representation of a float, return it rounded to an int.
57 If the value is out of range, or NaN, return return +/- SK_MaxS32
58 */
59int32_t SkFloatBits_toIntRound(int32_t floatBits);
60
61/** Given the bit representation of a float, return its ceiling as an int.
62 If the value is out of range, or NaN, return return +/- SK_MaxS32
63 */
64int32_t SkFloatBits_toIntCeil(int32_t floatBits);
65
66
67#ifdef SK_CAN_USE_FLOAT
68
69union SkFloatIntUnion {
70 float fFloat;
71 int32_t fSignBitInt;
72};
73
74// Helper to see a float as its bit pattern (w/o aliasing warnings)
75static inline int32_t SkFloat2Bits(float x) {
76 SkFloatIntUnion data;
77 data.fFloat = x;
78 return data.fSignBitInt;
79}
80
81// Helper to see a bit pattern as a float (w/o aliasing warnings)
82static inline float SkBits2Float(int32_t floatAsBits) {
83 SkFloatIntUnion data;
84 data.fSignBitInt = floatAsBits;
85 return data.fFloat;
86}
87
88/** Return the float as a 2s compliment int. Just to be used to compare floats
89 to each other or against positive float-bit-constants (like 0). This does
90 not return the int equivalent of the float, just something cheaper for
91 compares-only.
92 */
93static inline int32_t SkFloatAs2sCompliment(float x) {
94 return SkSignBitTo2sCompliment(SkFloat2Bits(x));
95}
96
97/** Return the 2s compliment int as a float. This undos the result of
98 SkFloatAs2sCompliment
99 */
100static inline float Sk2sComplimentAsFloat(int32_t x) {
101 return SkBits2Float(Sk2sComplimentToSignBit(x));
102}
103
104/** Return x cast to a float (i.e. (float)x)
105*/
106float SkIntToFloatCast(int x);
107float SkIntToFloatCast_NoOverflowCheck(int x);
108
109/** Return the float cast to an int.
110 If the value is out of range, or NaN, return +/- SK_MaxS32
111*/
112static inline int32_t SkFloatToIntCast(float x) {
113 return SkFloatBits_toIntCast(SkFloat2Bits(x));
114}
115
116/** Return the floor of the float as an int.
117 If the value is out of range, or NaN, return +/- SK_MaxS32
118*/
119static inline int32_t SkFloatToIntFloor(float x) {
120 return SkFloatBits_toIntFloor(SkFloat2Bits(x));
121}
122
123/** Return the float rounded to an int.
124 If the value is out of range, or NaN, return +/- SK_MaxS32
125*/
126static inline int32_t SkFloatToIntRound(float x) {
127 return SkFloatBits_toIntRound(SkFloat2Bits(x));
128}
129
130/** Return the ceiling of the float as an int.
131 If the value is out of range, or NaN, return +/- SK_MaxS32
132*/
133static inline int32_t SkFloatToIntCeil(float x) {
134 return SkFloatBits_toIntCeil(SkFloat2Bits(x));
135}
136
137#endif
138
139// Scalar wrappers for float-bit routines
140
141#ifdef SK_SCALAR_IS_FLOAT
142 #define SkScalarAs2sCompliment(x) SkFloatAs2sCompliment(x)
143 #define Sk2sComplimentAsScalar(x) Sk2sComplimentAsFloat(x)
144#else
145 #define SkScalarAs2sCompliment(x) (x)
146 #define Sk2sComplimentAsScalar(x) (x)
147#endif
148
149#endif
150