00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <ft2build.h>
00020 #include FT_INTERNAL_OBJECTS_H
00021 #include FT_TRIGONOMETRY_H
00022
00023
00024
00025 #define FT_TRIG_COSCALE 0x11616E8EUL
00026
00027
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
00039 #define FT_TRIG_SCALE 1166391785UL
00040
00041
00042 #ifdef FT_CONFIG_HAS_INT64
00043
00044
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
00062
00063
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;
00078 k2 = (FT_UInt32)(FT_TRIG_SCALE & 0xFFFFL);
00079
00080 hi = k1 * v1;
00081 lo1 = k1 * v2 + k2 * v1;
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
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
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
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
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
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
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
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
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
00284 yi = y + ( x << 1 );
00285 x = x - ( y << 1 );
00286 y = yi;
00287 theta -= *arctanptr++;
00288 }
00289 else
00290 {
00291
00292 yi = y - ( x << 1 );
00293 x = x + ( y << 1 );
00294 y = yi;
00295 theta += *arctanptr++;
00296 }
00297
00298 i = 0;
00299 do
00300 {
00301 if ( y < 0 )
00302 {
00303
00304 yi = y + ( x >> i );
00305 x = x - ( y >> i );
00306 y = yi;
00307 theta -= *arctanptr++;
00308 }
00309 else
00310 {
00311
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
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
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
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
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
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
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
00407
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
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
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
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
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
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
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
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