1
2 /*
3 * Copyright 2006 The Android Open Source Project
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9
10 #ifndef SkFixed_DEFINED
11 #define SkFixed_DEFINED
12
13 #include "SkTypes.h"
14
15 /** \file SkFixed.h
16
17 Types and macros for 16.16 fixed point
18 */
19
20 /** 32 bit signed integer used to represent fractions values with 16 bits to the right of the decimal point
21 */
22 typedef int32_t SkFixed;
23 #define SK_Fixed1 (1 << 16)
24 #define SK_FixedHalf (1 << 15)
25 #define SK_FixedMax (0x7FFFFFFF)
26 #define SK_FixedMin (-SK_FixedMax)
27 #define SK_FixedNaN ((int) 0x80000000)
28 #define SK_FixedPI (0x3243F)
29 #define SK_FixedSqrt2 (92682)
30 #define SK_FixedTanPIOver8 (0x6A0A)
31 #define SK_FixedRoot2Over2 (0xB505)
32
33 #define SkFixedToFloat(x) ((x) * 1.5258789e-5f)
34 #if 1
35 #define SkFloatToFixed(x) ((SkFixed)((x) * SK_Fixed1))
36 #else
37 // pins over/under flows to max/min int32 (slower than just a cast)
SkFloatToFixed(float x)38 static inline SkFixed SkFloatToFixed(float x) {
39 int64_t n = x * SK_Fixed1;
40 return (SkFixed)n;
41 }
42 #endif
43
44 #ifdef SK_DEBUG
SkFloatToFixed_Check(float x)45 static inline SkFixed SkFloatToFixed_Check(float x) {
46 int64_t n64 = (int64_t)(x * SK_Fixed1);
47 SkFixed n32 = (SkFixed)n64;
48 SkASSERT(n64 == n32);
49 return n32;
50 }
51 #else
52 #define SkFloatToFixed_Check(x) SkFloatToFixed(x)
53 #endif
54
55 #define SkFixedToDouble(x) ((x) * 1.5258789e-5)
56 #define SkDoubleToFixed(x) ((SkFixed)((x) * SK_Fixed1))
57
58 /** 32 bit signed integer used to represent fractions values with 30 bits to the right of the decimal point
59 */
60 typedef int32_t SkFract;
61 #define SK_Fract1 (1 << 30)
62 #define Sk_FracHalf (1 << 29)
63 #define SK_FractPIOver180 (0x11DF46A)
64
65 #define SkFractToFloat(x) ((float)(x) * 0.00000000093132257f)
66 #define SkFloatToFract(x) ((SkFract)((x) * SK_Fract1))
67
68 /** Converts an integer to a SkFixed, asserting that the result does not overflow
69 a 32 bit signed integer
70 */
71 #ifdef SK_DEBUG
SkIntToFixed(int n)72 inline SkFixed SkIntToFixed(int n)
73 {
74 SkASSERT(n >= -32768 && n <= 32767);
75 return n << 16;
76 }
77 #else
78 // force the cast to SkFixed to ensure that the answer is signed (like the debug version)
79 #define SkIntToFixed(n) (SkFixed)((n) << 16)
80 #endif
81
82 /** Converts a SkFixed to a SkFract, asserting that the result does not overflow
83 a 32 bit signed integer
84 */
85 #ifdef SK_DEBUG
SkFixedToFract(SkFixed x)86 inline SkFract SkFixedToFract(SkFixed x)
87 {
88 SkASSERT(x >= (-2 << 16) && x <= (2 << 16) - 1);
89 return x << 14;
90 }
91 #else
92 #define SkFixedToFract(x) ((x) << 14)
93 #endif
94
95 /** Returns the signed fraction of a SkFixed
96 */
SkFixedFraction(SkFixed x)97 inline SkFixed SkFixedFraction(SkFixed x)
98 {
99 SkFixed mask = x >> 31 << 16;
100 return (x & 0xFFFF) | mask;
101 }
102
103 /** Converts a SkFract to a SkFixed
104 */
105 #define SkFractToFixed(x) ((x) >> 14)
106
107 #define SkFixedRoundToInt(x) (((x) + SK_FixedHalf) >> 16)
108 #define SkFixedCeilToInt(x) (((x) + SK_Fixed1 - 1) >> 16)
109 #define SkFixedFloorToInt(x) ((x) >> 16)
110
111 #define SkFixedRoundToFixed(x) (((x) + SK_FixedHalf) & 0xFFFF0000)
112 #define SkFixedCeilToFixed(x) (((x) + SK_Fixed1 - 1) & 0xFFFF0000)
113 #define SkFixedFloorToFixed(x) ((x) & 0xFFFF0000)
114
115 // DEPRECATED
116 #define SkFixedFloor(x) SkFixedFloorToInt(x)
117 #define SkFixedCeil(x) SkFixedCeilToInt(x)
118 #define SkFixedRound(x) SkFixedRoundToInt(x)
119
120 #define SkFixedAbs(x) SkAbs32(x)
121 #define SkFixedAve(a, b) (((a) + (b)) >> 1)
122
123 SkFixed SkFixedMul_portable(SkFixed, SkFixed);
124 SkFract SkFractMul_portable(SkFract, SkFract);
SkFixedSquare_portable(SkFixed value)125 inline SkFixed SkFixedSquare_portable(SkFixed value)
126 {
127 uint32_t a = SkAbs32(value);
128 uint32_t ah = a >> 16;
129 uint32_t al = a & 0xFFFF;
130 SkFixed result = ah * a + al * ah + (al * al >> 16);
131 if (result >= 0)
132 return result;
133 else // Overflow.
134 return SK_FixedMax;
135 }
136
137 #define SkFixedDiv(numer, denom) SkDivBits(numer, denom, 16)
138 SkFixed SkFixedDivInt(int32_t numer, int32_t denom);
139 SkFixed SkFixedMod(SkFixed numer, SkFixed denom);
140 #define SkFixedInvert(n) SkDivBits(SK_Fixed1, n, 16)
141 SkFixed SkFixedFastInvert(SkFixed n);
142 #define SkFixedSqrt(n) SkSqrtBits(n, 23)
143 SkFixed SkFixedMean(SkFixed a, SkFixed b); //*< returns sqrt(x*y)
144 int SkFixedMulCommon(SkFixed, int , int bias); // internal used by SkFixedMulFloor, SkFixedMulCeil, SkFixedMulRound
145
146 #define SkFractDiv(numer, denom) SkDivBits(numer, denom, 30)
147 #define SkFractSqrt(n) SkSqrtBits(n, 30)
148
149 SkFixed SkFixedSinCos(SkFixed radians, SkFixed* cosValueOrNull);
150 #define SkFixedSin(radians) SkFixedSinCos(radians, NULL)
SkFixedCos(SkFixed radians)151 inline SkFixed SkFixedCos(SkFixed radians)
152 {
153 SkFixed cosValue;
154 (void)SkFixedSinCos(radians, &cosValue);
155 return cosValue;
156 }
157 SkFixed SkFixedTan(SkFixed radians);
158 SkFixed SkFixedASin(SkFixed);
159 SkFixed SkFixedACos(SkFixed);
160 SkFixed SkFixedATan2(SkFixed y, SkFixed x);
161 SkFixed SkFixedExp(SkFixed);
162 SkFixed SkFixedLog(SkFixed);
163
164 #define SK_FixedNearlyZero (SK_Fixed1 >> 12)
165
166 inline bool SkFixedNearlyZero(SkFixed x, SkFixed tolerance = SK_FixedNearlyZero)
167 {
168 SkASSERT(tolerance > 0);
169 return SkAbs32(x) < tolerance;
170 }
171
172 //////////////////////////////////////////////////////////////////////////////////////////////////////
173 // Now look for ASM overrides for our portable versions (should consider putting this in its own file)
174
175 #ifdef SkLONGLONG
SkFixedMul_longlong(SkFixed a,SkFixed b)176 inline SkFixed SkFixedMul_longlong(SkFixed a, SkFixed b)
177 {
178 return (SkFixed)((SkLONGLONG)a * b >> 16);
179 }
SkFractMul_longlong(SkFract a,SkFract b)180 inline SkFract SkFractMul_longlong(SkFract a, SkFract b)
181 {
182 return (SkFixed)((SkLONGLONG)a * b >> 30);
183 }
SkFixedSquare_longlong(SkFixed value)184 inline SkFixed SkFixedSquare_longlong(SkFixed value)
185 {
186 return (SkFixed)((SkLONGLONG)value * value >> 16);
187 }
188 #define SkFixedMul(a,b) SkFixedMul_longlong(a,b)
189 #define SkFractMul(a,b) SkFractMul_longlong(a,b)
190 #define SkFixedSquare(a) SkFixedSquare_longlong(a)
191 #endif
192
193 #if defined(SK_CPU_ARM) && !defined(__thumb__)
194 /* This guy does not handle NaN or other obscurities, but is faster than
195 than (int)(x*65536) when we only have software floats
196 */
SkFloatToFixed_arm(float x)197 inline SkFixed SkFloatToFixed_arm(float x)
198 {
199 register int32_t y, z;
200 asm("movs %1, %3, lsl #1 \n"
201 "mov %2, #0x8E \n"
202 "sub %1, %2, %1, lsr #24 \n"
203 "mov %2, %3, lsl #8 \n"
204 "orr %2, %2, #0x80000000 \n"
205 "mov %1, %2, lsr %1 \n"
206 "rsbcs %1, %1, #0 \n"
207 : "=r"(x), "=&r"(y), "=&r"(z)
208 : "r"(x)
209 : "cc"
210 );
211 return y;
212 }
SkFixedMul_arm(SkFixed x,SkFixed y)213 inline SkFixed SkFixedMul_arm(SkFixed x, SkFixed y)
214 {
215 register int32_t t;
216 asm("smull %0, %2, %1, %3 \n"
217 "mov %0, %0, lsr #16 \n"
218 "orr %0, %0, %2, lsl #16 \n"
219 : "=r"(x), "=&r"(y), "=r"(t)
220 : "r"(x), "1"(y)
221 :
222 );
223 return x;
224 }
SkFixedMulAdd_arm(SkFixed x,SkFixed y,SkFixed a)225 inline SkFixed SkFixedMulAdd_arm(SkFixed x, SkFixed y, SkFixed a)
226 {
227 register int32_t t;
228 asm("smull %0, %3, %1, %4 \n"
229 "add %0, %2, %0, lsr #16 \n"
230 "add %0, %0, %3, lsl #16 \n"
231 : "=r"(x), "=&r"(y), "=&r"(a), "=r"(t)
232 : "%r"(x), "1"(y), "2"(a)
233 :
234 );
235 return x;
236 }
SkFractMul_arm(SkFixed x,SkFixed y)237 inline SkFixed SkFractMul_arm(SkFixed x, SkFixed y)
238 {
239 register int32_t t;
240 asm("smull %0, %2, %1, %3 \n"
241 "mov %0, %0, lsr #30 \n"
242 "orr %0, %0, %2, lsl #2 \n"
243 : "=r"(x), "=&r"(y), "=r"(t)
244 : "r"(x), "1"(y)
245 :
246 );
247 return x;
248 }
249 #undef SkFixedMul
250 #undef SkFractMul
251 #define SkFixedMul(x, y) SkFixedMul_arm(x, y)
252 #define SkFractMul(x, y) SkFractMul_arm(x, y)
253 #define SkFixedMulAdd(x, y, a) SkFixedMulAdd_arm(x, y, a)
254
255 #undef SkFloatToFixed
256 #define SkFloatToFixed(x) SkFloatToFixed_arm(x)
257 #endif
258
259 /////////////////////// Now define our macros to the portable versions if they weren't overridden
260
261 #ifndef SkFixedSquare
262 #define SkFixedSquare(x) SkFixedSquare_portable(x)
263 #endif
264 #ifndef SkFixedMul
265 #define SkFixedMul(x, y) SkFixedMul_portable(x, y)
266 #endif
267 #ifndef SkFractMul
268 #define SkFractMul(x, y) SkFractMul_portable(x, y)
269 #endif
270 #ifndef SkFixedMulAdd
271 #define SkFixedMulAdd(x, y, a) (SkFixedMul(x, y) + (a))
272 #endif
273
274 ///////////////////////////////////////////////////////////////////////////////
275
276 typedef int64_t SkFixed48;
277
278 #define SkIntToFixed48(x) ((SkFixed48)(x) << 48)
279 #define SkFixed48ToInt(x) ((int)((x) >> 48))
280 #define SkFixedToFixed48(x) ((SkFixed48)(x) << 32)
281 #define SkFixed48ToFixed(x) ((SkFixed)((x) >> 32))
282 #define SkFloatToFixed48(x) ((SkFixed48)((x) * (65536.0f * 65536.0f * 65536.0f)))
283
284 #ifdef SK_SCALAR_IS_FLOAT
285 #define SkScalarToFixed48(x) SkFloatToFixed48(x)
286 #else
287 #define SkScalarToFixed48(x) SkFixedToFixed48(x)
288 #endif
289
290 #endif
291