Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenfttrigon.c
Go to the documentation of this file.
00001 /***************************************************************************/ 00002 /* */ 00003 /* fttrigon.c */ 00004 /* */ 00005 /* FreeType trigonometric functions (body). */ 00006 /* */ 00007 /* Copyright 2001, 2002, 2003, 2004, 2005 by */ 00008 /* David Turner, Robert Wilhelm, and Werner Lemberg. */ 00009 /* */ 00010 /* This file is part of the FreeType project, and may only be used, */ 00011 /* modified, and distributed under the terms of the FreeType project */ 00012 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 00013 /* this file you indicate that you have read the license and */ 00014 /* understand and accept it fully. */ 00015 /* */ 00016 /***************************************************************************/ 00017 00018 00019 #include <ft2build.h> 00020 #include FT_INTERNAL_OBJECTS_H 00021 #include FT_TRIGONOMETRY_H 00022 00023 00024 /* the following is 0.2715717684432231 * 2^30 */ 00025 #define FT_TRIG_COSCALE 0x11616E8EUL 00026 00027 /* this table was generated for FT_PI = 180L << 16, i.e. degrees */ 00028 #define FT_TRIG_MAX_ITERS 23 00029 00030 static const FT_Fixed 00031 ft_trig_arctan_table[24] = 00032 { 00033 4157273L, 2949120L, 1740967L, 919879L, 466945L, 234379L, 117304L, 00034 58666L, 29335L, 14668L, 7334L, 3667L, 1833L, 917L, 458L, 229L, 115L, 00035 57L, 29L, 14L, 7L, 4L, 2L, 1L 00036 }; 00037 00038 /* the Cordic shrink factor, multiplied by 2^32 */ 00039 #define FT_TRIG_SCALE 1166391785UL /* 0x4585BA38UL */ 00040 00041 00042 #ifdef FT_CONFIG_HAS_INT64 00043 00044 /* multiply a given value by the CORDIC shrink factor */ 00045 static FT_Fixed 00046 ft_trig_downscale( FT_Fixed val ) 00047 { 00048 FT_Fixed s; 00049 FT_Int64 v; 00050 00051 00052 s = val; 00053 val = ( val >= 0 ) ? val : -val; 00054 00055 v = ( val * (FT_Int64)FT_TRIG_SCALE ) + 0x100000000UL; 00056 val = (FT_Fixed)( v >> 32 ); 00057 00058 return ( s >= 0 ) ? val : -val; 00059 } 00060 00061 #else /* !FT_CONFIG_HAS_INT64 */ 00062 00063 /* multiply a given value by the CORDIC shrink factor */ 00064 static FT_Fixed 00065 ft_trig_downscale( FT_Fixed val ) 00066 { 00067 FT_Fixed s; 00068 FT_UInt32 v1, v2, k1, k2, hi, lo1, lo2, lo3; 00069 00070 00071 s = val; 00072 val = ( val >= 0 ) ? val : -val; 00073 00074 v1 = (FT_UInt32)val >> 16; 00075 v2 = (FT_UInt32)(val & 0xFFFFL); 00076 00077 k1 = (FT_UInt32)FT_TRIG_SCALE >> 16; /* constant */ 00078 k2 = (FT_UInt32)(FT_TRIG_SCALE & 0xFFFFL); /* constant */ 00079 00080 hi = k1 * v1; 00081 lo1 = k1 * v2 + k2 * v1; /* can't overflow */ 00082 00083 lo2 = ( k2 * v2 ) >> 16; 00084 lo3 = ( lo1 >= lo2 ) ? lo1 : lo2; 00085 lo1 += lo2; 00086 00087 hi += lo1 >> 16; 00088 if ( lo1 < lo3 ) 00089 hi += (FT_UInt32)0x10000UL; 00090 00091 val = (FT_Fixed)hi; 00092 00093 return ( s >= 0 ) ? val : -val; 00094 } 00095 00096 #endif /* !FT_CONFIG_HAS_INT64 */ 00097 00098 00099 static FT_Int 00100 ft_trig_prenorm( FT_Vector* vec ) 00101 { 00102 FT_Fixed x, y, z; 00103 FT_Int shift; 00104 00105 00106 x = vec->x; 00107 y = vec->y; 00108 00109 z = ( ( x >= 0 ) ? x : - x ) | ( (y >= 0) ? y : -y ); 00110 shift = 0; 00111 00112 #if 1 00113 /* determine msb bit index in `shift' */ 00114 if ( z >= ( 1L << 16 ) ) 00115 { 00116 z >>= 16; 00117 shift += 16; 00118 } 00119 if ( z >= ( 1L << 8 ) ) 00120 { 00121 z >>= 8; 00122 shift += 8; 00123 } 00124 if ( z >= ( 1L << 4 ) ) 00125 { 00126 z >>= 4; 00127 shift += 4; 00128 } 00129 if ( z >= ( 1L << 2 ) ) 00130 { 00131 z >>= 2; 00132 shift += 2; 00133 } 00134 if ( z >= ( 1L << 1 ) ) 00135 { 00136 z >>= 1; 00137 shift += 1; 00138 } 00139 00140 if ( shift <= 27 ) 00141 { 00142 shift = 27 - shift; 00143 vec->x = x << shift; 00144 vec->y = y << shift; 00145 } 00146 else 00147 { 00148 shift -= 27; 00149 vec->x = x >> shift; 00150 vec->y = y >> shift; 00151 shift = -shift; 00152 } 00153 00154 #else /* 0 */ 00155 00156 if ( z < ( 1L << 27 ) ) 00157 { 00158 do 00159 { 00160 shift++; 00161 z <<= 1; 00162 } while ( z < ( 1L << 27 ) ); 00163 vec->x = x << shift; 00164 vec->y = y << shift; 00165 } 00166 else if ( z > ( 1L << 28 ) ) 00167 { 00168 do 00169 { 00170 shift++; 00171 z >>= 1; 00172 } while ( z > ( 1L << 28 ) ); 00173 00174 vec->x = x >> shift; 00175 vec->y = y >> shift; 00176 shift = -shift; 00177 } 00178 00179 #endif /* 0 */ 00180 00181 return shift; 00182 } 00183 00184 00185 static void 00186 ft_trig_pseudo_rotate( FT_Vector* vec, 00187 FT_Angle theta ) 00188 { 00189 FT_Int i; 00190 FT_Fixed x, y, xtemp; 00191 const FT_Fixed *arctanptr; 00192 00193 00194 x = vec->x; 00195 y = vec->y; 00196 00197 /* Get angle between -90 and 90 degrees */ 00198 while ( theta <= -FT_ANGLE_PI2 ) 00199 { 00200 x = -x; 00201 y = -y; 00202 theta += FT_ANGLE_PI; 00203 } 00204 00205 while ( theta > FT_ANGLE_PI2 ) 00206 { 00207 x = -x; 00208 y = -y; 00209 theta -= FT_ANGLE_PI; 00210 } 00211 00212 /* Initial pseudorotation, with left shift */ 00213 arctanptr = ft_trig_arctan_table; 00214 00215 if ( theta < 0 ) 00216 { 00217 xtemp = x + ( y << 1 ); 00218 y = y - ( x << 1 ); 00219 x = xtemp; 00220 theta += *arctanptr++; 00221 } 00222 else 00223 { 00224 xtemp = x - ( y << 1 ); 00225 y = y + ( x << 1 ); 00226 x = xtemp; 00227 theta -= *arctanptr++; 00228 } 00229 00230 /* Subsequent pseudorotations, with right shifts */ 00231 i = 0; 00232 do 00233 { 00234 if ( theta < 0 ) 00235 { 00236 xtemp = x + ( y >> i ); 00237 y = y - ( x >> i ); 00238 x = xtemp; 00239 theta += *arctanptr++; 00240 } 00241 else 00242 { 00243 xtemp = x - ( y >> i ); 00244 y = y + ( x >> i ); 00245 x = xtemp; 00246 theta -= *arctanptr++; 00247 } 00248 } while ( ++i < FT_TRIG_MAX_ITERS ); 00249 00250 vec->x = x; 00251 vec->y = y; 00252 } 00253 00254 00255 static void 00256 ft_trig_pseudo_polarize( FT_Vector* vec ) 00257 { 00258 FT_Fixed theta; 00259 FT_Fixed yi, i; 00260 FT_Fixed x, y; 00261 const FT_Fixed *arctanptr; 00262 00263 00264 x = vec->x; 00265 y = vec->y; 00266 00267 /* Get the vector into the right half plane */ 00268 theta = 0; 00269 if ( x < 0 ) 00270 { 00271 x = -x; 00272 y = -y; 00273 theta = 2 * FT_ANGLE_PI2; 00274 } 00275 00276 if ( y > 0 ) 00277 theta = - theta; 00278 00279 arctanptr = ft_trig_arctan_table; 00280 00281 if ( y < 0 ) 00282 { 00283 /* Rotate positive */ 00284 yi = y + ( x << 1 ); 00285 x = x - ( y << 1 ); 00286 y = yi; 00287 theta -= *arctanptr++; /* Subtract angle */ 00288 } 00289 else 00290 { 00291 /* Rotate negative */ 00292 yi = y - ( x << 1 ); 00293 x = x + ( y << 1 ); 00294 y = yi; 00295 theta += *arctanptr++; /* Add angle */ 00296 } 00297 00298 i = 0; 00299 do 00300 { 00301 if ( y < 0 ) 00302 { 00303 /* Rotate positive */ 00304 yi = y + ( x >> i ); 00305 x = x - ( y >> i ); 00306 y = yi; 00307 theta -= *arctanptr++; 00308 } 00309 else 00310 { 00311 /* Rotate negative */ 00312 yi = y - ( x >> i ); 00313 x = x + ( y >> i ); 00314 y = yi; 00315 theta += *arctanptr++; 00316 } 00317 } while ( ++i < FT_TRIG_MAX_ITERS ); 00318 00319 /* round theta */ 00320 if ( theta >= 0 ) 00321 theta = FT_PAD_ROUND( theta, 32 ); 00322 else 00323 theta = -FT_PAD_ROUND( -theta, 32 ); 00324 00325 vec->x = x; 00326 vec->y = theta; 00327 } 00328 00329 00330 /* documentation is in fttrigon.h */ 00331 00332 FT_EXPORT_DEF( FT_Fixed ) 00333 FT_Cos( FT_Angle angle ) 00334 { 00335 FT_Vector v; 00336 00337 00338 v.x = FT_TRIG_COSCALE >> 2; 00339 v.y = 0; 00340 ft_trig_pseudo_rotate( &v, angle ); 00341 00342 return v.x / ( 1 << 12 ); 00343 } 00344 00345 00346 /* documentation is in fttrigon.h */ 00347 00348 FT_EXPORT_DEF( FT_Fixed ) 00349 FT_Sin( FT_Angle angle ) 00350 { 00351 return FT_Cos( FT_ANGLE_PI2 - angle ); 00352 } 00353 00354 00355 /* documentation is in fttrigon.h */ 00356 00357 FT_EXPORT_DEF( FT_Fixed ) 00358 FT_Tan( FT_Angle angle ) 00359 { 00360 FT_Vector v; 00361 00362 00363 v.x = FT_TRIG_COSCALE >> 2; 00364 v.y = 0; 00365 ft_trig_pseudo_rotate( &v, angle ); 00366 00367 return FT_DivFix( v.y, v.x ); 00368 } 00369 00370 00371 /* documentation is in fttrigon.h */ 00372 00373 FT_EXPORT_DEF( FT_Angle ) 00374 FT_Atan2( FT_Fixed dx, 00375 FT_Fixed dy ) 00376 { 00377 FT_Vector v; 00378 00379 00380 if ( dx == 0 && dy == 0 ) 00381 return 0; 00382 00383 v.x = dx; 00384 v.y = dy; 00385 ft_trig_prenorm( &v ); 00386 ft_trig_pseudo_polarize( &v ); 00387 00388 return v.y; 00389 } 00390 00391 00392 /* documentation is in fttrigon.h */ 00393 00394 FT_EXPORT_DEF( void ) 00395 FT_Vector_Unit( FT_Vector* vec, 00396 FT_Angle angle ) 00397 { 00398 vec->x = FT_TRIG_COSCALE >> 2; 00399 vec->y = 0; 00400 ft_trig_pseudo_rotate( vec, angle ); 00401 vec->x >>= 12; 00402 vec->y >>= 12; 00403 } 00404 00405 00406 /* these macros return 0 for positive numbers, 00407 and -1 for negative ones */ 00408 #define FT_SIGN_LONG( x ) ( (x) >> ( FT_SIZEOF_LONG * 8 - 1 ) ) 00409 #define FT_SIGN_INT( x ) ( (x) >> ( FT_SIZEOF_INT * 8 - 1 ) ) 00410 #define FT_SIGN_INT32( x ) ( (x) >> 31 ) 00411 #define FT_SIGN_INT16( x ) ( (x) >> 15 ) 00412 00413 00414 /* documentation is in fttrigon.h */ 00415 00416 FT_EXPORT_DEF( void ) 00417 FT_Vector_Rotate( FT_Vector* vec, 00418 FT_Angle angle ) 00419 { 00420 FT_Int shift; 00421 FT_Vector v; 00422 00423 00424 v.x = vec->x; 00425 v.y = vec->y; 00426 00427 if ( angle && ( v.x != 0 || v.y != 0 ) ) 00428 { 00429 shift = ft_trig_prenorm( &v ); 00430 ft_trig_pseudo_rotate( &v, angle ); 00431 v.x = ft_trig_downscale( v.x ); 00432 v.y = ft_trig_downscale( v.y ); 00433 00434 if ( shift > 0 ) 00435 { 00436 FT_Int32 half = (FT_Int32)1L << ( shift - 1 ); 00437 00438 00439 vec->x = ( v.x + half + FT_SIGN_LONG( v.x ) ) >> shift; 00440 vec->y = ( v.y + half + FT_SIGN_LONG( v.y ) ) >> shift; 00441 } 00442 else 00443 { 00444 shift = -shift; 00445 vec->x = v.x << shift; 00446 vec->y = v.y << shift; 00447 } 00448 } 00449 } 00450 00451 00452 /* documentation is in fttrigon.h */ 00453 00454 FT_EXPORT_DEF( FT_Fixed ) 00455 FT_Vector_Length( FT_Vector* vec ) 00456 { 00457 FT_Int shift; 00458 FT_Vector v; 00459 00460 00461 v = *vec; 00462 00463 /* handle trivial cases */ 00464 if ( v.x == 0 ) 00465 { 00466 return ( v.y >= 0 ) ? v.y : -v.y; 00467 } 00468 else if ( v.y == 0 ) 00469 { 00470 return ( v.x >= 0 ) ? v.x : -v.x; 00471 } 00472 00473 /* general case */ 00474 shift = ft_trig_prenorm( &v ); 00475 ft_trig_pseudo_polarize( &v ); 00476 00477 v.x = ft_trig_downscale( v.x ); 00478 00479 if ( shift > 0 ) 00480 return ( v.x + ( 1 << ( shift - 1 ) ) ) >> shift; 00481 00482 return v.x << -shift; 00483 } 00484 00485 00486 /* documentation is in fttrigon.h */ 00487 00488 FT_EXPORT_DEF( void ) 00489 FT_Vector_Polarize( FT_Vector* vec, 00490 FT_Fixed *length, 00491 FT_Angle *angle ) 00492 { 00493 FT_Int shift; 00494 FT_Vector v; 00495 00496 00497 v = *vec; 00498 00499 if ( v.x == 0 && v.y == 0 ) 00500 return; 00501 00502 shift = ft_trig_prenorm( &v ); 00503 ft_trig_pseudo_polarize( &v ); 00504 00505 v.x = ft_trig_downscale( v.x ); 00506 00507 *length = ( shift >= 0 ) ? ( v.x >> shift ) : ( v.x << -shift ); 00508 *angle = v.y; 00509 } 00510 00511 00512 /* documentation is in fttrigon.h */ 00513 00514 FT_EXPORT_DEF( void ) 00515 FT_Vector_From_Polar( FT_Vector* vec, 00516 FT_Fixed length, 00517 FT_Angle angle ) 00518 { 00519 vec->x = length; 00520 vec->y = 0; 00521 00522 FT_Vector_Rotate( vec, angle ); 00523 } 00524 00525 00526 /* documentation is in fttrigon.h */ 00527 00528 FT_EXPORT_DEF( FT_Angle ) 00529 FT_Angle_Diff( FT_Angle angle1, 00530 FT_Angle angle2 ) 00531 { 00532 FT_Angle delta = angle2 - angle1; 00533 00534 00535 delta %= FT_ANGLE_2PI; 00536 if ( delta < 0 ) 00537 delta += FT_ANGLE_2PI; 00538 00539 if ( delta > FT_ANGLE_PI ) 00540 delta -= FT_ANGLE_2PI; 00541 00542 return delta; 00543 } 00544 00545 00546 /* END */ Generated on Sun May 27 2012 04:33:47 for ReactOS by
1.7.6.1
|