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)
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
65 0 : inline SkFixed SkIntToFixed(int n)
66 : {
67 0 : SkASSERT(n >= -32768 && n <= 32767);
68 0 : 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
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 : */
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);
118 0 : inline SkFixed SkFixedSquare_portable(SkFixed value)
119 : {
120 0 : uint32_t a = SkAbs32(value);
121 0 : uint32_t ah = a >> 16;
122 0 : uint32_t al = a & 0xFFFF;
123 0 : SkFixed result = ah * a + al * ah + (al * al >> 16);
124 0 : if (result >= 0)
125 0 : return result;
126 : else // Overflow.
127 0 : 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)
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 0 : inline bool SkFixedNearlyZero(SkFixed x, SkFixed tolerance = SK_FixedNearlyZero)
160 : {
161 0 : SkASSERT(tolerance > 0);
162 0 : 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
169 : inline SkFixed SkFixedMul_longlong(SkFixed a, SkFixed b)
170 : {
171 : return (SkFixed)((SkLONGLONG)a * b >> 16);
172 : }
173 : inline SkFract SkFractMul_longlong(SkFract a, SkFract b)
174 : {
175 : return (SkFixed)((SkLONGLONG)a * b >> 30);
176 : }
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 : */
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 : }
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 : }
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 : }
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
|