1/***************************************************************************/ 2/* */ 3/* fttrigon.c */ 4/* */ 5/* FreeType trigonometric functions (body). */ 6/* */ 7/* Copyright 2001-2005, 2012-2013 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 /* */ 20 /* This is a fixed-point CORDIC implementation of trigonometric */ 21 /* functions as well as transformations between Cartesian and polar */ 22 /* coordinates. The angles are represented as 16.16 fixed-point values */ 23 /* in degrees, i.e., the angular resolution is 2^-16 degrees. Note that */ 24 /* only vectors longer than 2^16*180/pi (or at least 22 bits) on a */ 25 /* discrete Cartesian grid can have the same or better angular */ 26 /* resolution. Therefore, to maintain this precision, some functions */ 27 /* require an interim upscaling of the vectors, whereas others operate */ 28 /* with 24-bit long vectors directly. */ 29 /* */ 30 /*************************************************************************/ 31 32#include <ft2build.h> 33#include FT_INTERNAL_OBJECTS_H 34#include FT_INTERNAL_CALC_H 35#include FT_TRIGONOMETRY_H 36 37 38 /* the Cordic shrink factor 0.858785336480436 * 2^32 */ 39#define FT_TRIG_SCALE 0xDBD95B16UL 40 41 /* the highest bit in overflow-safe vector components, */ 42 /* MSB of 0.858785336480436 * sqrt(0.5) * 2^30 */ 43#define FT_TRIG_SAFE_MSB 29 44 45 /* this table was generated for FT_PI = 180L << 16, i.e. degrees */ 46#define FT_TRIG_MAX_ITERS 23 47 48 static const FT_Fixed 49 ft_trig_arctan_table[] = 50 { 51 1740967L, 919879L, 466945L, 234379L, 117304L, 58666L, 29335L, 52 14668L, 7334L, 3667L, 1833L, 917L, 458L, 229L, 115L, 53 57L, 29L, 14L, 7L, 4L, 2L, 1L 54 }; 55 56 57#ifdef FT_LONG64 58 59 /* multiply a given value by the CORDIC shrink factor */ 60 static FT_Fixed 61 ft_trig_downscale( FT_Fixed val ) 62 { 63 FT_Fixed s; 64 FT_Int64 v; 65 66 67 s = val; 68 val = FT_ABS( val ); 69 70 v = ( val * (FT_Int64)FT_TRIG_SCALE ) + 0x100000000UL; 71 val = (FT_Fixed)( v >> 32 ); 72 73 return ( s >= 0 ) ? val : -val; 74 } 75 76#else /* !FT_LONG64 */ 77 78 /* multiply a given value by the CORDIC shrink factor */ 79 static FT_Fixed 80 ft_trig_downscale( FT_Fixed val ) 81 { 82 FT_Fixed s; 83 FT_UInt32 v1, v2, k1, k2, hi, lo1, lo2, lo3; 84 85 86 s = val; 87 val = FT_ABS( val ); 88 89 v1 = (FT_UInt32)val >> 16; 90 v2 = (FT_UInt32)( val & 0xFFFFL ); 91 92 k1 = (FT_UInt32)FT_TRIG_SCALE >> 16; /* constant */ 93 k2 = (FT_UInt32)( FT_TRIG_SCALE & 0xFFFFL ); /* constant */ 94 95 hi = k1 * v1; 96 lo1 = k1 * v2 + k2 * v1; /* can't overflow */ 97 98 lo2 = ( k2 * v2 ) >> 16; 99 lo3 = FT_MAX( lo1, lo2 ); 100 lo1 += lo2; 101 102 hi += lo1 >> 16; 103 if ( lo1 < lo3 ) 104 hi += (FT_UInt32)0x10000UL; 105 106 val = (FT_Fixed)hi; 107 108 return ( s >= 0 ) ? val : -val; 109 } 110 111#endif /* !FT_LONG64 */ 112 113 114 static FT_Int 115 ft_trig_prenorm( FT_Vector* vec ) 116 { 117 FT_Pos x, y; 118 FT_Int shift; 119 120 121 x = vec->x; 122 y = vec->y; 123 124 shift = FT_MSB( FT_ABS( x ) | FT_ABS( y ) ); 125 126 if ( shift <= FT_TRIG_SAFE_MSB ) 127 { 128 shift = FT_TRIG_SAFE_MSB - shift; 129 vec->x = (FT_Pos)( (FT_ULong)x << shift ); 130 vec->y = (FT_Pos)( (FT_ULong)y << shift ); 131 } 132 else 133 { 134 shift -= FT_TRIG_SAFE_MSB; 135 vec->x = x >> shift; 136 vec->y = y >> shift; 137 shift = -shift; 138 } 139 140 return shift; 141 } 142 143 144 static void 145 ft_trig_pseudo_rotate( FT_Vector* vec, 146 FT_Angle theta ) 147 { 148 FT_Int i; 149 FT_Fixed x, y, xtemp, b; 150 const FT_Fixed *arctanptr; 151 152 153 x = vec->x; 154 y = vec->y; 155 156 /* Rotate inside [-PI/4,PI/4] sector */ 157 while ( theta < -FT_ANGLE_PI4 ) 158 { 159 xtemp = y; 160 y = -x; 161 x = xtemp; 162 theta += FT_ANGLE_PI2; 163 } 164 165 while ( theta > FT_ANGLE_PI4 ) 166 { 167 xtemp = -y; 168 y = x; 169 x = xtemp; 170 theta -= FT_ANGLE_PI2; 171 } 172 173 arctanptr = ft_trig_arctan_table; 174 175 /* Pseudorotations, with right shifts */ 176 for ( i = 1, b = 1; i < FT_TRIG_MAX_ITERS; b <<= 1, i++ ) 177 { 178 if ( theta < 0 ) 179 { 180 xtemp = x + ( ( y + b ) >> i ); 181 y = y - ( ( x + b ) >> i ); 182 x = xtemp; 183 theta += *arctanptr++; 184 } 185 else 186 { 187 xtemp = x - ( ( y + b ) >> i ); 188 y = y + ( ( x + b ) >> i ); 189 x = xtemp; 190 theta -= *arctanptr++; 191 } 192 } 193 194 vec->x = x; 195 vec->y = y; 196 } 197 198 199 static void 200 ft_trig_pseudo_polarize( FT_Vector* vec ) 201 { 202 FT_Angle theta; 203 FT_Int i; 204 FT_Fixed x, y, xtemp, b; 205 const FT_Fixed *arctanptr; 206 207 208 x = vec->x; 209 y = vec->y; 210 211 /* Get the vector into [-PI/4,PI/4] sector */ 212 if ( y > x ) 213 { 214 if ( y > -x ) 215 { 216 theta = FT_ANGLE_PI2; 217 xtemp = y; 218 y = -x; 219 x = xtemp; 220 } 221 else 222 { 223 theta = y > 0 ? FT_ANGLE_PI : -FT_ANGLE_PI; 224 x = -x; 225 y = -y; 226 } 227 } 228 else 229 { 230 if ( y < -x ) 231 { 232 theta = -FT_ANGLE_PI2; 233 xtemp = -y; 234 y = x; 235 x = xtemp; 236 } 237 else 238 { 239 theta = 0; 240 } 241 } 242 243 arctanptr = ft_trig_arctan_table; 244 245 /* Pseudorotations, with right shifts */ 246 for ( i = 1, b = 1; i < FT_TRIG_MAX_ITERS; b <<= 1, i++ ) 247 { 248 if ( y > 0 ) 249 { 250 xtemp = x + ( ( y + b ) >> i ); 251 y = y - ( ( x + b ) >> i ); 252 x = xtemp; 253 theta += *arctanptr++; 254 } 255 else 256 { 257 xtemp = x - ( ( y + b ) >> i ); 258 y = y + ( ( x + b ) >> i ); 259 x = xtemp; 260 theta -= *arctanptr++; 261 } 262 } 263 264 /* round theta */ 265 if ( theta >= 0 ) 266 theta = FT_PAD_ROUND( theta, 32 ); 267 else 268 theta = -FT_PAD_ROUND( -theta, 32 ); 269 270 vec->x = x; 271 vec->y = theta; 272 } 273 274 275 /* documentation is in fttrigon.h */ 276 277 FT_EXPORT_DEF( FT_Fixed ) 278 FT_Cos( FT_Angle angle ) 279 { 280 FT_Vector v; 281 282 283 v.x = FT_TRIG_SCALE >> 8; 284 v.y = 0; 285 ft_trig_pseudo_rotate( &v, angle ); 286 287 return ( v.x + 0x80L ) >> 8; 288 } 289 290 291 /* documentation is in fttrigon.h */ 292 293 FT_EXPORT_DEF( FT_Fixed ) 294 FT_Sin( FT_Angle angle ) 295 { 296 return FT_Cos( FT_ANGLE_PI2 - angle ); 297 } 298 299 300 /* documentation is in fttrigon.h */ 301 302 FT_EXPORT_DEF( FT_Fixed ) 303 FT_Tan( FT_Angle angle ) 304 { 305 FT_Vector v; 306 307 308 v.x = FT_TRIG_SCALE >> 8; 309 v.y = 0; 310 ft_trig_pseudo_rotate( &v, angle ); 311 312 return FT_DivFix( v.y, v.x ); 313 } 314 315 316 /* documentation is in fttrigon.h */ 317 318 FT_EXPORT_DEF( FT_Angle ) 319 FT_Atan2( FT_Fixed dx, 320 FT_Fixed dy ) 321 { 322 FT_Vector v; 323 324 325 if ( dx == 0 && dy == 0 ) 326 return 0; 327 328 v.x = dx; 329 v.y = dy; 330 ft_trig_prenorm( &v ); 331 ft_trig_pseudo_polarize( &v ); 332 333 return v.y; 334 } 335 336 337 /* documentation is in fttrigon.h */ 338 339 FT_EXPORT_DEF( void ) 340 FT_Vector_Unit( FT_Vector* vec, 341 FT_Angle angle ) 342 { 343 vec->x = FT_TRIG_SCALE >> 8; 344 vec->y = 0; 345 ft_trig_pseudo_rotate( vec, angle ); 346 vec->x = ( vec->x + 0x80L ) >> 8; 347 vec->y = ( vec->y + 0x80L ) >> 8; 348 } 349 350 351 /* these macros return 0 for positive numbers, 352 and -1 for negative ones */ 353#define FT_SIGN_LONG( x ) ( (x) >> ( FT_SIZEOF_LONG * 8 - 1 ) ) 354#define FT_SIGN_INT( x ) ( (x) >> ( FT_SIZEOF_INT * 8 - 1 ) ) 355#define FT_SIGN_INT32( x ) ( (x) >> 31 ) 356#define FT_SIGN_INT16( x ) ( (x) >> 15 ) 357 358 359 /* documentation is in fttrigon.h */ 360 361 FT_EXPORT_DEF( void ) 362 FT_Vector_Rotate( FT_Vector* vec, 363 FT_Angle angle ) 364 { 365 FT_Int shift; 366 FT_Vector v; 367 368 369 v.x = vec->x; 370 v.y = vec->y; 371 372 if ( angle && ( v.x != 0 || v.y != 0 ) ) 373 { 374 shift = ft_trig_prenorm( &v ); 375 ft_trig_pseudo_rotate( &v, angle ); 376 v.x = ft_trig_downscale( v.x ); 377 v.y = ft_trig_downscale( v.y ); 378 379 if ( shift > 0 ) 380 { 381 FT_Int32 half = (FT_Int32)1L << ( shift - 1 ); 382 383 384 vec->x = ( v.x + half + FT_SIGN_LONG( v.x ) ) >> shift; 385 vec->y = ( v.y + half + FT_SIGN_LONG( v.y ) ) >> shift; 386 } 387 else 388 { 389 shift = -shift; 390 vec->x = (FT_Pos)( (FT_ULong)v.x << shift ); 391 vec->y = (FT_Pos)( (FT_ULong)v.y << shift ); 392 } 393 } 394 } 395 396 397 /* documentation is in fttrigon.h */ 398 399 FT_EXPORT_DEF( FT_Fixed ) 400 FT_Vector_Length( FT_Vector* vec ) 401 { 402 FT_Int shift; 403 FT_Vector v; 404 405 406 v = *vec; 407 408 /* handle trivial cases */ 409 if ( v.x == 0 ) 410 { 411 return FT_ABS( v.y ); 412 } 413 else if ( v.y == 0 ) 414 { 415 return FT_ABS( v.x ); 416 } 417 418 /* general case */ 419 shift = ft_trig_prenorm( &v ); 420 ft_trig_pseudo_polarize( &v ); 421 422 v.x = ft_trig_downscale( v.x ); 423 424 if ( shift > 0 ) 425 return ( v.x + ( 1 << ( shift - 1 ) ) ) >> shift; 426 427 return (FT_Fixed)( (FT_UInt32)v.x << -shift ); 428 } 429 430 431 /* documentation is in fttrigon.h */ 432 433 FT_EXPORT_DEF( void ) 434 FT_Vector_Polarize( FT_Vector* vec, 435 FT_Fixed *length, 436 FT_Angle *angle ) 437 { 438 FT_Int shift; 439 FT_Vector v; 440 441 442 v = *vec; 443 444 if ( v.x == 0 && v.y == 0 ) 445 return; 446 447 shift = ft_trig_prenorm( &v ); 448 ft_trig_pseudo_polarize( &v ); 449 450 v.x = ft_trig_downscale( v.x ); 451 452 *length = ( shift >= 0 ) ? ( v.x >> shift ) 453 : (FT_Fixed)( (FT_UInt32)v.x << -shift ); 454 *angle = v.y; 455 } 456 457 458 /* documentation is in fttrigon.h */ 459 460 FT_EXPORT_DEF( void ) 461 FT_Vector_From_Polar( FT_Vector* vec, 462 FT_Fixed length, 463 FT_Angle angle ) 464 { 465 vec->x = length; 466 vec->y = 0; 467 468 FT_Vector_Rotate( vec, angle ); 469 } 470 471 472 /* documentation is in fttrigon.h */ 473 474 FT_EXPORT_DEF( FT_Angle ) 475 FT_Angle_Diff( FT_Angle angle1, 476 FT_Angle angle2 ) 477 { 478 FT_Angle delta = angle2 - angle1; 479 480 481 delta %= FT_ANGLE_2PI; 482 if ( delta < 0 ) 483 delta += FT_ANGLE_2PI; 484 485 if ( delta > FT_ANGLE_PI ) 486 delta -= FT_ANGLE_2PI; 487 488 return delta; 489 } 490 491 492/* END */ 493