1/***************************************************************************/ 2/* */ 3/* ftcalc.h */ 4/* */ 5/* Arithmetic computations (specification). */ 6/* */ 7/* Copyright 1996-2015 by */ 8/* David Turner, Robert Wilhelm, and Werner Lemberg. */ 9/* */ 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 */ 12/* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 13/* this file you indicate that you have read the license and */ 14/* understand and accept it fully. */ 15/* */ 16/***************************************************************************/ 17 18 19#ifndef __FTCALC_H__ 20#define __FTCALC_H__ 21 22 23#include <ft2build.h> 24#include FT_FREETYPE_H 25 26 27FT_BEGIN_HEADER 28 29 30 /*************************************************************************/ 31 /* */ 32 /* FT_MulDiv() and FT_MulFix() are declared in freetype.h. */ 33 /* */ 34 /*************************************************************************/ 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 248 249 /*************************************************************************/ 250 /* */ 251 /* <Function> */ 252 /* FT_MulDiv_No_Round */ 253 /* */ 254 /* <Description> */ 255 /* A very simple function used to perform the computation `(a*b)/c' */ 256 /* (without rounding) with maximum accuracy (it uses a 64-bit */ 257 /* intermediate integer whenever necessary). */ 258 /* */ 259 /* This function isn't necessarily as fast as some processor specific */ 260 /* operations, but is at least completely portable. */ 261 /* */ 262 /* <Input> */ 263 /* a :: The first multiplier. */ 264 /* b :: The second multiplier. */ 265 /* c :: The divisor. */ 266 /* */ 267 /* <Return> */ 268 /* The result of `(a*b)/c'. This function never traps when trying to */ 269 /* divide by zero; it simply returns `MaxInt' or `MinInt' depending */ 270 /* on the signs of `a' and `b'. */ 271 /* */ 272 FT_BASE( FT_Long ) 273 FT_MulDiv_No_Round( FT_Long a, 274 FT_Long b, 275 FT_Long c ); 276 277 278 /* 279 * A variant of FT_Matrix_Multiply which scales its result afterwards. 280 * The idea is that both `a' and `b' are scaled by factors of 10 so that 281 * the values are as precise as possible to get a correct result during 282 * the 64bit multiplication. Let `sa' and `sb' be the scaling factors of 283 * `a' and `b', respectively, then the scaling factor of the result is 284 * `sa*sb'. 285 */ 286 FT_BASE( void ) 287 FT_Matrix_Multiply_Scaled( const FT_Matrix* a, 288 FT_Matrix *b, 289 FT_Long scaling ); 290 291 292 /* 293 * A variant of FT_Vector_Transform. See comments for 294 * FT_Matrix_Multiply_Scaled. 295 */ 296 FT_BASE( void ) 297 FT_Vector_Transform_Scaled( FT_Vector* vector, 298 const FT_Matrix* matrix, 299 FT_Long scaling ); 300 301 302 /* 303 * Return -1, 0, or +1, depending on the orientation of a given corner. 304 * We use the Cartesian coordinate system, with positive vertical values 305 * going upwards. The function returns +1 if the corner turns to the 306 * left, -1 to the right, and 0 for undecidable cases. 307 */ 308 FT_BASE( FT_Int ) 309 ft_corner_orientation( FT_Pos in_x, 310 FT_Pos in_y, 311 FT_Pos out_x, 312 FT_Pos out_y ); 313 314 315 /* 316 * Return TRUE if a corner is flat or nearly flat. This is equivalent to 317 * saying that the corner point is close to its neighbors, or inside an 318 * ellipse defined by the neighbor focal points to be more precise. 319 */ 320 FT_BASE( FT_Int ) 321 ft_corner_is_flat( FT_Pos in_x, 322 FT_Pos in_y, 323 FT_Pos out_x, 324 FT_Pos out_y ); 325 326 327 /* 328 * Return the most significant bit index. 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 350 FT_BASE( FT_Int ) 351 FT_MSB( FT_UInt32 z ); 352 353#endif 354 355 356 /* 357 * Return sqrt(x*x+y*y), which is the same as `FT_Vector_Length' but uses 358 * two fixed-point arguments instead. 359 */ 360 FT_BASE( FT_Fixed ) 361 FT_Hypot( FT_Fixed x, 362 FT_Fixed y ); 363 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 390#define INT_TO_F26DOT6( x ) ( (FT_Long)(x) << 6 ) 391#define INT_TO_F2DOT14( x ) ( (FT_Long)(x) << 14 ) 392#define INT_TO_FIXED( x ) ( (FT_Long)(x) << 16 ) 393#define F2DOT14_TO_FIXED( x ) ( (FT_Long)(x) << 2 ) 394#define FLOAT_TO_FIXED( x ) ( (FT_Long)( x * 65536.0 ) ) 395#define FIXED_TO_INT( x ) ( FT_RoundFix( x ) >> 16 ) 396 397#define ROUND_F26DOT6( x ) ( x >= 0 ? ( ( (x) + 32 ) & -64 ) \ 398 : ( -( ( 32 - (x) ) & -64 ) ) ) 399 400 401FT_END_HEADER 402 403#endif /* __FTCALC_H__ */ 404 405 406/* END */ 407