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