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