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