1 /*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #ifndef SkFixed_DEFINED
18 #define SkFixed_DEFINED
19
20 #include "SkMath.h"
21
22 /** \file SkFixed.h
23
24 Types and macros for 16.16 fixed point
25 */
26
27 /** 32 bit signed integer used to represent fractions values with 16 bits to the right of the decimal point
28 */
29 typedef int32_t SkFixed;
30 #define SK_Fixed1 (1 << 16)
31 #define SK_FixedHalf (1 << 15)
32 #define SK_FixedMax (0x7FFFFFFF)
33 #define SK_FixedMin (-SK_FixedMax)
34 #define SK_FixedNaN ((int) 0x80000000)
35 #define SK_FixedPI (0x3243F)
36 #define SK_FixedSqrt2 (92682)
37 #define SK_FixedTanPIOver8 (0x6A0A)
38 #define SK_FixedRoot2Over2 (0xB505)
39
40 #ifdef SK_CAN_USE_FLOAT
41 #define SkFixedToFloat(x) ((x) * 1.5258789e-5f)
42 #if 1
43 #define SkFloatToFixed(x) ((SkFixed)((x) * SK_Fixed1))
44 #else
45 // pins over/under flows to max/min int32 (slower than just a cast)
SkFloatToFixed(float x)46 static inline SkFixed SkFloatToFixed(float x) {
47 int64_t n = x * SK_Fixed1;
48 return (SkFixed)n;
49 }
50 #endif
51
52 #define SkFixedToDouble(x) ((x) * 1.5258789e-5)
53 #define SkDoubleToFixed(x) ((SkFixed)((x) * SK_Fixed1))
54 #endif
55
56 /** 32 bit signed integer used to represent fractions values with 30 bits to the right of the decimal point
57 */
58 typedef int32_t SkFract;
59 #define SK_Fract1 (1 << 30)
60 #define Sk_FracHalf (1 << 29)
61 #define SK_FractPIOver180 (0x11DF46A)
62
63 #ifdef SK_CAN_USE_FLOAT
64 #define SkFractToFloat(x) ((float)(x) * 0.00000000093132257f)
65 #define SkFloatToFract(x) ((SkFract)((x) * SK_Fract1))
66 #endif
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 /** Round a SkFixed to an integer
107 */
108 #define SkFixedRound(x) (((x) + SK_FixedHalf) >> 16)
109 #define SkFixedCeil(x) (((x) + SK_Fixed1 - 1) >> 16)
110 #define SkFixedFloor(x) ((x) >> 16)
111 #define SkFixedAbs(x) SkAbs32(x)
112 #define SkFixedAve(a, b) (((a) + (b)) >> 1)
113
114 // The same as SkIntToFixed(SkFixedFloor(x))
115 #define SkFixedFloorToFixed(x) ((x) & ~0xFFFF)
116
117 SkFixed SkFixedMul_portable(SkFixed, SkFixed);
118 SkFract SkFractMul_portable(SkFract, SkFract);
SkFixedSquare_portable(SkFixed value)119 inline SkFixed SkFixedSquare_portable(SkFixed value)
120 {
121 uint32_t a = SkAbs32(value);
122 uint32_t ah = a >> 16;
123 uint32_t al = a & 0xFFFF;
124 SkFixed result = ah * a + al * ah + (al * al >> 16);
125 if (result >= 0)
126 return result;
127 else // Overflow.
128 return SK_FixedMax;
129 }
130
131 #define SkFixedDiv(numer, denom) SkDivBits(numer, denom, 16)
132 SkFixed SkFixedDivInt(int32_t numer, int32_t denom);
133 SkFixed SkFixedMod(SkFixed numer, SkFixed denom);
134 #define SkFixedInvert(n) SkDivBits(SK_Fixed1, n, 16)
135 SkFixed SkFixedFastInvert(SkFixed n);
136 #define SkFixedSqrt(n) SkSqrtBits(n, 23)
137 SkFixed SkFixedMean(SkFixed a, SkFixed b); //*< returns sqrt(x*y)
138 int SkFixedMulCommon(SkFixed, int , int bias); // internal used by SkFixedMulFloor, SkFixedMulCeil, SkFixedMulRound
139
140 #define SkFractDiv(numer, denom) SkDivBits(numer, denom, 30)
141 #define SkFractSqrt(n) SkSqrtBits(n, 30)
142
143 SkFixed SkFixedSinCos(SkFixed radians, SkFixed* cosValueOrNull);
144 #define SkFixedSin(radians) SkFixedSinCos(radians, NULL)
SkFixedCos(SkFixed radians)145 inline SkFixed SkFixedCos(SkFixed radians)
146 {
147 SkFixed cosValue;
148 (void)SkFixedSinCos(radians, &cosValue);
149 return cosValue;
150 }
151 SkFixed SkFixedTan(SkFixed radians);
152 SkFixed SkFixedASin(SkFixed);
153 SkFixed SkFixedACos(SkFixed);
154 SkFixed SkFixedATan2(SkFixed y, SkFixed x);
155 SkFixed SkFixedExp(SkFixed);
156 SkFixed SkFixedLog(SkFixed);
157
158 #define SK_FixedNearlyZero (SK_Fixed1 >> 12)
159
160 inline bool SkFixedNearlyZero(SkFixed x, SkFixed tolerance = SK_FixedNearlyZero)
161 {
162 SkASSERT(tolerance > 0);
163 return SkAbs32(x) < tolerance;
164 }
165
166 //////////////////////////////////////////////////////////////////////////////////////////////////////
167 // Now look for ASM overrides for our portable versions (should consider putting this in its own file)
168
169 #ifdef SkLONGLONG
SkFixedMul_longlong(SkFixed a,SkFixed b)170 inline SkFixed SkFixedMul_longlong(SkFixed a, SkFixed b)
171 {
172 return (SkFixed)((SkLONGLONG)a * b >> 16);
173 }
SkFractMul_longlong(SkFract a,SkFract b)174 inline SkFract SkFractMul_longlong(SkFract a, SkFract b)
175 {
176 return (SkFixed)((SkLONGLONG)a * b >> 30);
177 }
SkFixedSquare_longlong(SkFixed value)178 inline SkFixed SkFixedSquare_longlong(SkFixed value)
179 {
180 return (SkFixed)((SkLONGLONG)value * value >> 16);
181 }
182 #define SkFixedMul(a,b) SkFixedMul_longlong(a,b)
183 #define SkFractMul(a,b) SkFractMul_longlong(a,b)
184 #define SkFixedSquare(a) SkFixedSquare_longlong(a)
185 #endif
186
187 #if defined(__arm__) && !defined(__thumb__)
188 /* This guy does not handle NaN or other obscurities, but is faster than
189 than (int)(x*65536) when we only have software floats
190 */
SkFloatToFixed_arm(float x)191 inline SkFixed SkFloatToFixed_arm(float x)
192 {
193 register int32_t y, z;
194 asm("movs %1, %3, lsl #1 \n"
195 "mov %2, #0x8E \n"
196 "sub %1, %2, %1, lsr #24 \n"
197 "mov %2, %3, lsl #8 \n"
198 "orr %2, %2, #0x80000000 \n"
199 "mov %1, %2, lsr %1 \n"
200 "rsbcs %1, %1, #0 \n"
201 : "=r"(x), "=&r"(y), "=&r"(z)
202 : "r"(x)
203 : "cc"
204 );
205 return y;
206 }
SkFixedMul_arm(SkFixed x,SkFixed y)207 inline SkFixed SkFixedMul_arm(SkFixed x, SkFixed y)
208 {
209 register int32_t t;
210 asm("smull %0, %2, %1, %3 \n"
211 "mov %0, %0, lsr #16 \n"
212 "orr %0, %0, %2, lsl #16 \n"
213 : "=r"(x), "=&r"(y), "=r"(t)
214 : "r"(x), "1"(y)
215 :
216 );
217 return x;
218 }
SkFixedMulAdd_arm(SkFixed x,SkFixed y,SkFixed a)219 inline SkFixed SkFixedMulAdd_arm(SkFixed x, SkFixed y, SkFixed a)
220 {
221 register int32_t t;
222 asm("smull %0, %3, %1, %4 \n"
223 "add %0, %2, %0, lsr #16 \n"
224 "add %0, %0, %3, lsl #16 \n"
225 : "=r"(x), "=&r"(y), "=&r"(a), "=r"(t)
226 : "%r"(x), "1"(y), "2"(a)
227 :
228 );
229 return x;
230 }
SkFractMul_arm(SkFixed x,SkFixed y)231 inline SkFixed SkFractMul_arm(SkFixed x, SkFixed y)
232 {
233 register int32_t t;
234 asm("smull %0, %2, %1, %3 \n"
235 "mov %0, %0, lsr #30 \n"
236 "orr %0, %0, %2, lsl #2 \n"
237 : "=r"(x), "=&r"(y), "=r"(t)
238 : "r"(x), "1"(y)
239 :
240 );
241 return x;
242 }
243 #undef SkFixedMul
244 #undef SkFractMul
245 #define SkFixedMul(x, y) SkFixedMul_arm(x, y)
246 #define SkFractMul(x, y) SkFractMul_arm(x, y)
247 #define SkFixedMulAdd(x, y, a) SkFixedMulAdd_arm(x, y, a)
248
249 #undef SkFloatToFixed
250 #define SkFloatToFixed(x) SkFloatToFixed_arm(x)
251 #endif
252
253 /////////////////////// Now define our macros to the portable versions if they weren't overridden
254
255 #ifndef SkFixedSquare
256 #define SkFixedSquare(x) SkFixedSquare_portable(x)
257 #endif
258 #ifndef SkFixedMul
259 #define SkFixedMul(x, y) SkFixedMul_portable(x, y)
260 #endif
261 #ifndef SkFractMul
262 #define SkFractMul(x, y) SkFractMul_portable(x, y)
263 #endif
264 #ifndef SkFixedMulAdd
265 #define SkFixedMulAdd(x, y, a) (SkFixedMul(x, y) + (a))
266 #endif
267
268 #endif
269