• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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