• 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 #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