OLD | NEW |
1 /***************************************************************************/ | 1 /***************************************************************************/ |
2 /* */ | 2 /* */ |
3 /* ftcalc.h */ | 3 /* ftcalc.h */ |
4 /* */ | 4 /* */ |
5 /* Arithmetic computations (specification). */ | 5 /* Arithmetic computations (specification). */ |
6 /* */ | 6 /* */ |
7 /* Copyright 1996-2006, 2008, 2009, 2012-2013 by */ | 7 /* Copyright 1996-2006, 2008, 2009, 2012-2014 by */ |
8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */ | 8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */ |
9 /* */ | 9 /* */ |
10 /* This file is part of the FreeType project, and may only be used, */ | 10 /* This file is part of the FreeType project, and may only be used, */ |
11 /* modified, and distributed under the terms of the FreeType project */ | 11 /* modified, and distributed under the terms of the FreeType project */ |
12 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ | 12 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ |
13 /* this file you indicate that you have read the license and */ | 13 /* this file you indicate that you have read the license and */ |
14 /* understand and accept it fully. */ | 14 /* understand and accept it fully. */ |
15 /* */ | 15 /* */ |
16 /***************************************************************************/ | 16 /***************************************************************************/ |
17 | 17 |
18 | 18 |
19 #ifndef __FTCALC_H__ | 19 #ifndef __FTCALC_H__ |
20 #define __FTCALC_H__ | 20 #define __FTCALC_H__ |
21 | 21 |
22 | 22 |
23 #include "../../ft2build.h" | 23 #include <ft2build.h> |
24 #include "../freetype.h" | 24 #include FT_FREETYPE_H |
25 | 25 |
26 | 26 |
27 FT_BEGIN_HEADER | 27 FT_BEGIN_HEADER |
28 | 28 |
29 | 29 |
30 /*************************************************************************/ | 30 /*************************************************************************/ |
31 /* */ | 31 /* */ |
32 /* <Function> */ | |
33 /* FT_FixedSqrt */ | |
34 /* */ | |
35 /* <Description> */ | |
36 /* Computes the square root of a 16.16 fixed-point value. */ | |
37 /* */ | |
38 /* <Input> */ | |
39 /* x :: The value to compute the root for. */ | |
40 /* */ | |
41 /* <Return> */ | |
42 /* The result of `sqrt(x)'. */ | |
43 /* */ | |
44 /* <Note> */ | |
45 /* This function is not very fast. */ | |
46 /* */ | |
47 FT_BASE( FT_Int32 ) | |
48 FT_SqrtFixed( FT_Int32 x ); | |
49 | |
50 | |
51 /*************************************************************************/ | |
52 /* */ | |
53 /* FT_MulDiv() and FT_MulFix() are declared in freetype.h. */ | 32 /* FT_MulDiv() and FT_MulFix() are declared in freetype.h. */ |
54 /* */ | 33 /* */ |
55 /*************************************************************************/ | 34 /*************************************************************************/ |
56 | 35 |
| 36 #ifndef FT_CONFIG_OPTION_NO_ASSEMBLER |
| 37 /* Provide assembler fragments for performance-critical functions. */ |
| 38 /* These must be defined `static __inline__' with GCC. */ |
| 39 |
| 40 #if defined( __CC_ARM ) || defined( __ARMCC__ ) /* RVCT */ |
| 41 |
| 42 #define FT_MULFIX_ASSEMBLER FT_MulFix_arm |
| 43 |
| 44 /* documentation is in freetype.h */ |
| 45 |
| 46 static __inline FT_Int32 |
| 47 FT_MulFix_arm( FT_Int32 a, |
| 48 FT_Int32 b ) |
| 49 { |
| 50 register FT_Int32 t, t2; |
| 51 |
| 52 |
| 53 __asm |
| 54 { |
| 55 smull t2, t, b, a /* (lo=t2,hi=t) = a*b */ |
| 56 mov a, t, asr #31 /* a = (hi >> 31) */ |
| 57 add a, a, #0x8000 /* a += 0x8000 */ |
| 58 adds t2, t2, a /* t2 += a */ |
| 59 adc t, t, #0 /* t += carry */ |
| 60 mov a, t2, lsr #16 /* a = t2 >> 16 */ |
| 61 orr a, a, t, lsl #16 /* a |= t << 16 */ |
| 62 } |
| 63 return a; |
| 64 } |
| 65 |
| 66 #endif /* __CC_ARM || __ARMCC__ */ |
| 67 |
| 68 |
| 69 #ifdef __GNUC__ |
| 70 |
| 71 #if defined( __arm__ ) && \ |
| 72 ( !defined( __thumb__ ) || defined( __thumb2__ ) ) && \ |
| 73 !( defined( __CC_ARM ) || defined( __ARMCC__ ) ) |
| 74 |
| 75 #define FT_MULFIX_ASSEMBLER FT_MulFix_arm |
| 76 |
| 77 /* documentation is in freetype.h */ |
| 78 |
| 79 static __inline__ FT_Int32 |
| 80 FT_MulFix_arm( FT_Int32 a, |
| 81 FT_Int32 b ) |
| 82 { |
| 83 register FT_Int32 t, t2; |
| 84 |
| 85 |
| 86 __asm__ __volatile__ ( |
| 87 "smull %1, %2, %4, %3\n\t" /* (lo=%1,hi=%2) = a*b */ |
| 88 "mov %0, %2, asr #31\n\t" /* %0 = (hi >> 31) */ |
| 89 #if defined( __clang__ ) && defined( __thumb2__ ) |
| 90 "add.w %0, %0, #0x8000\n\t" /* %0 += 0x8000 */ |
| 91 #else |
| 92 "add %0, %0, #0x8000\n\t" /* %0 += 0x8000 */ |
| 93 #endif |
| 94 "adds %1, %1, %0\n\t" /* %1 += %0 */ |
| 95 "adc %2, %2, #0\n\t" /* %2 += carry */ |
| 96 "mov %0, %1, lsr #16\n\t" /* %0 = %1 >> 16 */ |
| 97 "orr %0, %0, %2, lsl #16\n\t" /* %0 |= %2 << 16 */ |
| 98 : "=r"(a), "=&r"(t2), "=&r"(t) |
| 99 : "r"(a), "r"(b) |
| 100 : "cc" ); |
| 101 return a; |
| 102 } |
| 103 |
| 104 #endif /* __arm__ && */ |
| 105 /* ( __thumb2__ || !__thumb__ ) && */ |
| 106 /* !( __CC_ARM || __ARMCC__ ) */ |
| 107 |
| 108 |
| 109 #if defined( __i386__ ) |
| 110 |
| 111 #define FT_MULFIX_ASSEMBLER FT_MulFix_i386 |
| 112 |
| 113 /* documentation is in freetype.h */ |
| 114 |
| 115 static __inline__ FT_Int32 |
| 116 FT_MulFix_i386( FT_Int32 a, |
| 117 FT_Int32 b ) |
| 118 { |
| 119 register FT_Int32 result; |
| 120 |
| 121 |
| 122 __asm__ __volatile__ ( |
| 123 "imul %%edx\n" |
| 124 "movl %%edx, %%ecx\n" |
| 125 "sarl $31, %%ecx\n" |
| 126 "addl $0x8000, %%ecx\n" |
| 127 "addl %%ecx, %%eax\n" |
| 128 "adcl $0, %%edx\n" |
| 129 "shrl $16, %%eax\n" |
| 130 "shll $16, %%edx\n" |
| 131 "addl %%edx, %%eax\n" |
| 132 : "=a"(result), "=d"(b) |
| 133 : "a"(a), "d"(b) |
| 134 : "%ecx", "cc" ); |
| 135 return result; |
| 136 } |
| 137 |
| 138 #endif /* i386 */ |
| 139 |
| 140 #endif /* __GNUC__ */ |
| 141 |
| 142 |
| 143 #ifdef _MSC_VER /* Visual C++ */ |
| 144 |
| 145 #ifdef _M_IX86 |
| 146 |
| 147 #define FT_MULFIX_ASSEMBLER FT_MulFix_i386 |
| 148 |
| 149 /* documentation is in freetype.h */ |
| 150 |
| 151 static __inline FT_Int32 |
| 152 FT_MulFix_i386( FT_Int32 a, |
| 153 FT_Int32 b ) |
| 154 { |
| 155 register FT_Int32 result; |
| 156 |
| 157 __asm |
| 158 { |
| 159 mov eax, a |
| 160 mov edx, b |
| 161 imul edx |
| 162 mov ecx, edx |
| 163 sar ecx, 31 |
| 164 add ecx, 8000h |
| 165 add eax, ecx |
| 166 adc edx, 0 |
| 167 shr eax, 16 |
| 168 shl edx, 16 |
| 169 add eax, edx |
| 170 mov result, eax |
| 171 } |
| 172 return result; |
| 173 } |
| 174 |
| 175 #endif /* _M_IX86 */ |
| 176 |
| 177 #endif /* _MSC_VER */ |
| 178 |
| 179 |
| 180 #if defined( __GNUC__ ) && defined( __x86_64__ ) |
| 181 |
| 182 #define FT_MULFIX_ASSEMBLER FT_MulFix_x86_64 |
| 183 |
| 184 static __inline__ FT_Int32 |
| 185 FT_MulFix_x86_64( FT_Int32 a, |
| 186 FT_Int32 b ) |
| 187 { |
| 188 /* Temporarily disable the warning that C90 doesn't support */ |
| 189 /* `long long'. */ |
| 190 #if __GNUC__ > 4 || ( __GNUC__ == 4 && __GNUC_MINOR__ >= 6 ) |
| 191 #pragma GCC diagnostic push |
| 192 #pragma GCC diagnostic ignored "-Wlong-long" |
| 193 #endif |
| 194 |
| 195 #if 1 |
| 196 /* Technically not an assembly fragment, but GCC does a really good */ |
| 197 /* job at inlining it and generating good machine code for it. */ |
| 198 long long ret, tmp; |
| 199 |
| 200 |
| 201 ret = (long long)a * b; |
| 202 tmp = ret >> 63; |
| 203 ret += 0x8000 + tmp; |
| 204 |
| 205 return (FT_Int32)( ret >> 16 ); |
| 206 #else |
| 207 |
| 208 /* For some reason, GCC 4.6 on Ubuntu 12.04 generates invalid machine */ |
| 209 /* code from the lines below. The main issue is that `wide_a' is not */ |
| 210 /* properly initialized by sign-extending `a'. Instead, the generated */ |
| 211 /* machine code assumes that the register that contains `a' on input */ |
| 212 /* can be used directly as a 64-bit value, which is wrong most of the */ |
| 213 /* time. */ |
| 214 long long wide_a = (long long)a; |
| 215 long long wide_b = (long long)b; |
| 216 long long result; |
| 217 |
| 218 |
| 219 __asm__ __volatile__ ( |
| 220 "imul %2, %1\n" |
| 221 "mov %1, %0\n" |
| 222 "sar $63, %0\n" |
| 223 "lea 0x8000(%1, %0), %0\n" |
| 224 "sar $16, %0\n" |
| 225 : "=&r"(result), "=&r"(wide_a) |
| 226 : "r"(wide_b) |
| 227 : "cc" ); |
| 228 |
| 229 return (FT_Int32)result; |
| 230 #endif |
| 231 |
| 232 #if __GNUC__ > 4 || ( __GNUC__ == 4 && __GNUC_MINOR__ >= 6 ) |
| 233 #pragma GCC diagnostic pop |
| 234 #endif |
| 235 } |
| 236 |
| 237 #endif /* __GNUC__ && __x86_64__ */ |
| 238 |
| 239 #endif /* !FT_CONFIG_OPTION_NO_ASSEMBLER */ |
| 240 |
| 241 |
| 242 #ifdef FT_CONFIG_OPTION_INLINE_MULFIX |
| 243 #ifdef FT_MULFIX_ASSEMBLER |
| 244 #define FT_MulFix( a, b ) FT_MULFIX_ASSEMBLER( (FT_Int32)(a), (FT_Int32)(b) ) |
| 245 #endif |
| 246 #endif |
| 247 |
57 | 248 |
58 /*************************************************************************/ | 249 /*************************************************************************/ |
59 /* */ | 250 /* */ |
60 /* <Function> */ | 251 /* <Function> */ |
61 /* FT_MulDiv_No_Round */ | 252 /* FT_MulDiv_No_Round */ |
62 /* */ | 253 /* */ |
63 /* <Description> */ | 254 /* <Description> */ |
64 /* A very simple function used to perform the computation `(a*b)/c' */ | 255 /* A very simple function used to perform the computation `(a*b)/c' */ |
65 /* (without rounding) with maximum accuracy (it uses a 64-bit */ | 256 /* (without rounding) with maximum accuracy (it uses a 64-bit */ |
66 /* intermediate integer whenever necessary). */ | 257 /* intermediate integer whenever necessary). */ |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
113 * We use the Cartesian coordinate system, with positive vertical values | 304 * We use the Cartesian coordinate system, with positive vertical values |
114 * going upwards. The function returns +1 if the corner turns to the | 305 * going upwards. The function returns +1 if the corner turns to the |
115 * left, -1 to the right, and 0 for undecidable cases. | 306 * left, -1 to the right, and 0 for undecidable cases. |
116 */ | 307 */ |
117 FT_BASE( FT_Int ) | 308 FT_BASE( FT_Int ) |
118 ft_corner_orientation( FT_Pos in_x, | 309 ft_corner_orientation( FT_Pos in_x, |
119 FT_Pos in_y, | 310 FT_Pos in_y, |
120 FT_Pos out_x, | 311 FT_Pos out_x, |
121 FT_Pos out_y ); | 312 FT_Pos out_y ); |
122 | 313 |
| 314 |
123 /* | 315 /* |
124 * Return TRUE if a corner is flat or nearly flat. This is equivalent to | 316 * Return TRUE if a corner is flat or nearly flat. This is equivalent to |
125 * saying that the angle difference between the `in' and `out' vectors is | 317 * saying that the corner point is close to its neighbors, or inside an |
126 * very small. | 318 * ellipse defined by the neighbor focal points to be more precise. |
127 */ | 319 */ |
128 FT_BASE( FT_Int ) | 320 FT_BASE( FT_Int ) |
129 ft_corner_is_flat( FT_Pos in_x, | 321 ft_corner_is_flat( FT_Pos in_x, |
130 FT_Pos in_y, | 322 FT_Pos in_y, |
131 FT_Pos out_x, | 323 FT_Pos out_x, |
132 FT_Pos out_y ); | 324 FT_Pos out_y ); |
133 | 325 |
134 | 326 |
135 /* | 327 /* |
136 * Return the most significant bit index. | 328 * Return the most significant bit index. |
137 */ | 329 */ |
| 330 |
| 331 #ifndef FT_CONFIG_OPTION_NO_ASSEMBLER |
| 332 #if defined( __GNUC__ ) && \ |
| 333 ( __GNUC__ > 3 || ( __GNUC__ == 3 && __GNUC_MINOR__ >= 4 ) ) |
| 334 |
| 335 #if FT_SIZEOF_INT == 4 |
| 336 |
| 337 #define FT_MSB( x ) ( 31 - __builtin_clz( x ) ) |
| 338 |
| 339 #elif FT_SIZEOF_LONG == 4 |
| 340 |
| 341 #define FT_MSB( x ) ( 31 - __builtin_clzl( x ) ) |
| 342 |
| 343 #endif |
| 344 |
| 345 #endif /* __GNUC__ */ |
| 346 #endif /* !FT_CONFIG_OPTION_NO_ASSEMBLER */ |
| 347 |
| 348 #ifndef FT_MSB |
| 349 |
138 FT_BASE( FT_Int ) | 350 FT_BASE( FT_Int ) |
139 FT_MSB( FT_UInt32 z ); | 351 FT_MSB( FT_UInt32 z ); |
140 | 352 |
| 353 #endif |
| 354 |
141 | 355 |
142 /* | 356 /* |
143 * Return sqrt(x*x+y*y), which is the same as `FT_Vector_Length' but uses | 357 * Return sqrt(x*x+y*y), which is the same as `FT_Vector_Length' but uses |
144 * two fixed-point arguments instead. | 358 * two fixed-point arguments instead. |
145 */ | 359 */ |
146 FT_BASE( FT_Fixed ) | 360 FT_BASE( FT_Fixed ) |
147 FT_Hypot( FT_Fixed x, | 361 FT_Hypot( FT_Fixed x, |
148 FT_Fixed y ); | 362 FT_Fixed y ); |
149 | 363 |
150 | 364 |
| 365 #if 0 |
| 366 |
| 367 /*************************************************************************/ |
| 368 /* */ |
| 369 /* <Function> */ |
| 370 /* FT_SqrtFixed */ |
| 371 /* */ |
| 372 /* <Description> */ |
| 373 /* Computes the square root of a 16.16 fixed-point value. */ |
| 374 /* */ |
| 375 /* <Input> */ |
| 376 /* x :: The value to compute the root for. */ |
| 377 /* */ |
| 378 /* <Return> */ |
| 379 /* The result of `sqrt(x)'. */ |
| 380 /* */ |
| 381 /* <Note> */ |
| 382 /* This function is not very fast. */ |
| 383 /* */ |
| 384 FT_BASE( FT_Int32 ) |
| 385 FT_SqrtFixed( FT_Int32 x ); |
| 386 |
| 387 #endif /* 0 */ |
| 388 |
| 389 |
151 #define INT_TO_F26DOT6( x ) ( (FT_Long)(x) << 6 ) | 390 #define INT_TO_F26DOT6( x ) ( (FT_Long)(x) << 6 ) |
152 #define INT_TO_F2DOT14( x ) ( (FT_Long)(x) << 14 ) | 391 #define INT_TO_F2DOT14( x ) ( (FT_Long)(x) << 14 ) |
153 #define INT_TO_FIXED( x ) ( (FT_Long)(x) << 16 ) | 392 #define INT_TO_FIXED( x ) ( (FT_Long)(x) << 16 ) |
154 #define F2DOT14_TO_FIXED( x ) ( (FT_Long)(x) << 2 ) | 393 #define F2DOT14_TO_FIXED( x ) ( (FT_Long)(x) << 2 ) |
155 #define FLOAT_TO_FIXED( x ) ( (FT_Long)( x * 65536.0 ) ) | 394 #define FLOAT_TO_FIXED( x ) ( (FT_Long)( x * 65536.0 ) ) |
156 #define FIXED_TO_INT( x ) ( FT_RoundFix( x ) >> 16 ) | 395 #define FIXED_TO_INT( x ) ( FT_RoundFix( x ) >> 16 ) |
157 | 396 |
158 #define ROUND_F26DOT6( x ) ( x >= 0 ? ( ( (x) + 32 ) & -64 ) \ | 397 #define ROUND_F26DOT6( x ) ( x >= 0 ? ( ( (x) + 32 ) & -64 ) \ |
159 : ( -( ( 32 - (x) ) & -64 ) ) ) | 398 : ( -( ( 32 - (x) ) & -64 ) ) ) |
160 | 399 |
161 | 400 |
162 FT_END_HEADER | 401 FT_END_HEADER |
163 | 402 |
164 #endif /* __FTCALC_H__ */ | 403 #endif /* __FTCALC_H__ */ |
165 | 404 |
166 | 405 |
167 /* END */ | 406 /* END */ |
OLD | NEW |