OLD | NEW |
1 /***************************************************************************/ | 1 /***************************************************************************/ |
2 /* */ | 2 /* */ |
3 /* fttrigon.c */ | 3 /* fttrigon.c */ |
4 /* */ | 4 /* */ |
5 /* FreeType trigonometric functions (body). */ | 5 /* FreeType trigonometric functions (body). */ |
6 /* */ | 6 /* */ |
7 /* Copyright 2001-2005, 2012-2014 by */ | 7 /* Copyright 2001-2015 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 |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
66 if ( val < 0 ) | 66 if ( val < 0 ) |
67 { | 67 { |
68 val = -val; | 68 val = -val; |
69 s = -1; | 69 s = -1; |
70 } | 70 } |
71 | 71 |
72 /* 0x40000000 comes from regression analysis between true */ | 72 /* 0x40000000 comes from regression analysis between true */ |
73 /* and CORDIC hypotenuse, so it minimizes the error */ | 73 /* and CORDIC hypotenuse, so it minimizes the error */ |
74 val = (FT_Fixed)( ( (FT_Int64)val * FT_TRIG_SCALE + 0x40000000UL ) >> 32 ); | 74 val = (FT_Fixed)( ( (FT_Int64)val * FT_TRIG_SCALE + 0x40000000UL ) >> 32 ); |
75 | 75 |
76 return ( s >= 0 ) ? val : -val; | 76 return s < 0 ? -val : val; |
77 } | 77 } |
78 | 78 |
79 #else /* !FT_LONG64 */ | 79 #else /* !FT_LONG64 */ |
80 | 80 |
81 /* multiply a given value by the CORDIC shrink factor */ | 81 /* multiply a given value by the CORDIC shrink factor */ |
82 static FT_Fixed | 82 static FT_Fixed |
83 ft_trig_downscale( FT_Fixed val ) | 83 ft_trig_downscale( FT_Fixed val ) |
84 { | 84 { |
85 FT_Int s = 1; | 85 FT_Int s = 1; |
86 FT_UInt32 lo1, hi1, lo2, hi2, lo, hi, i1, i2; | 86 FT_UInt32 lo1, hi1, lo2, hi2, lo, hi, i1, i2; |
87 | 87 |
88 | 88 |
89 if ( val < 0 ) | 89 if ( val < 0 ) |
90 { | 90 { |
91 val = -val; | 91 val = -val; |
92 s = -1; | 92 s = -1; |
93 } | 93 } |
94 | 94 |
95 lo1 = val & 0x0000FFFFU; | 95 lo1 = (FT_UInt32)val & 0x0000FFFFU; |
96 hi1 = val >> 16; | 96 hi1 = (FT_UInt32)val >> 16; |
97 lo2 = FT_TRIG_SCALE & 0x0000FFFFU; | 97 lo2 = FT_TRIG_SCALE & 0x0000FFFFU; |
98 hi2 = FT_TRIG_SCALE >> 16; | 98 hi2 = FT_TRIG_SCALE >> 16; |
99 | 99 |
100 lo = lo1 * lo2; | 100 lo = lo1 * lo2; |
101 i1 = lo1 * hi2; | 101 i1 = lo1 * hi2; |
102 i2 = lo2 * hi1; | 102 i2 = lo2 * hi1; |
103 hi = hi1 * hi2; | 103 hi = hi1 * hi2; |
104 | 104 |
105 /* Check carry overflow of i1 + i2 */ | 105 /* Check carry overflow of i1 + i2 */ |
106 i1 += i2; | 106 i1 += i2; |
107 hi += (FT_UInt32)( i1 < i2 ) << 16; | 107 hi += (FT_UInt32)( i1 < i2 ) << 16; |
108 | 108 |
109 hi += i1 >> 16; | 109 hi += i1 >> 16; |
110 i1 = i1 << 16; | 110 i1 = i1 << 16; |
111 | 111 |
112 /* Check carry overflow of i1 + lo */ | 112 /* Check carry overflow of i1 + lo */ |
113 lo += i1; | 113 lo += i1; |
114 hi += ( lo < i1 ); | 114 hi += ( lo < i1 ); |
115 | 115 |
116 /* 0x40000000 comes from regression analysis between true */ | 116 /* 0x40000000 comes from regression analysis between true */ |
117 /* and CORDIC hypotenuse, so it minimizes the error */ | 117 /* and CORDIC hypotenuse, so it minimizes the error */ |
118 | 118 |
119 /* Check carry overflow of lo + 0x40000000 */ | 119 /* Check carry overflow of lo + 0x40000000 */ |
120 lo += 0x40000000U; | 120 lo += 0x40000000UL; |
121 hi += ( lo < 0x40000000U ); | 121 hi += ( lo < 0x40000000UL ); |
122 | 122 |
123 val = (FT_Fixed)hi; | 123 val = (FT_Fixed)hi; |
124 | 124 |
125 return ( s >= 0 ) ? val : -val; | 125 return s < 0 ? -val : val; |
126 } | 126 } |
127 | 127 |
128 #endif /* !FT_LONG64 */ | 128 #endif /* !FT_LONG64 */ |
129 | 129 |
130 | 130 |
131 /* undefined and never called for zero vector */ | 131 /* undefined and never called for zero vector */ |
132 static FT_Int | 132 static FT_Int |
133 ft_trig_prenorm( FT_Vector* vec ) | 133 ft_trig_prenorm( FT_Vector* vec ) |
134 { | 134 { |
135 FT_Pos x, y; | 135 FT_Pos x, y; |
136 FT_Int shift; | 136 FT_Int shift; |
137 | 137 |
138 | 138 |
139 x = vec->x; | 139 x = vec->x; |
140 y = vec->y; | 140 y = vec->y; |
141 | 141 |
142 shift = FT_MSB( FT_ABS( x ) | FT_ABS( y ) ); | 142 shift = FT_MSB( (FT_UInt32)( FT_ABS( x ) | FT_ABS( y ) ) ); |
143 | 143 |
144 if ( shift <= FT_TRIG_SAFE_MSB ) | 144 if ( shift <= FT_TRIG_SAFE_MSB ) |
145 { | 145 { |
146 shift = FT_TRIG_SAFE_MSB - shift; | 146 shift = FT_TRIG_SAFE_MSB - shift; |
147 vec->x = (FT_Pos)( (FT_ULong)x << shift ); | 147 vec->x = (FT_Pos)( (FT_ULong)x << shift ); |
148 vec->y = (FT_Pos)( (FT_ULong)y << shift ); | 148 vec->y = (FT_Pos)( (FT_ULong)y << shift ); |
149 } | 149 } |
150 else | 150 else |
151 { | 151 { |
152 shift -= FT_TRIG_SAFE_MSB; | 152 shift -= FT_TRIG_SAFE_MSB; |
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
292 | 292 |
293 | 293 |
294 /* documentation is in fttrigon.h */ | 294 /* documentation is in fttrigon.h */ |
295 | 295 |
296 FT_EXPORT_DEF( FT_Fixed ) | 296 FT_EXPORT_DEF( FT_Fixed ) |
297 FT_Cos( FT_Angle angle ) | 297 FT_Cos( FT_Angle angle ) |
298 { | 298 { |
299 FT_Vector v; | 299 FT_Vector v; |
300 | 300 |
301 | 301 |
302 v.x = FT_TRIG_SCALE >> 8; | 302 FT_Vector_Unit( &v, angle ); |
303 v.y = 0; | |
304 ft_trig_pseudo_rotate( &v, angle ); | |
305 | 303 |
306 return ( v.x + 0x80L ) >> 8; | 304 return v.x; |
307 } | 305 } |
308 | 306 |
309 | 307 |
310 /* documentation is in fttrigon.h */ | 308 /* documentation is in fttrigon.h */ |
311 | 309 |
312 FT_EXPORT_DEF( FT_Fixed ) | 310 FT_EXPORT_DEF( FT_Fixed ) |
313 FT_Sin( FT_Angle angle ) | 311 FT_Sin( FT_Angle angle ) |
314 { | 312 { |
315 return FT_Cos( FT_ANGLE_PI2 - angle ); | 313 FT_Vector v; |
| 314 |
| 315 |
| 316 FT_Vector_Unit( &v, angle ); |
| 317 |
| 318 return v.y; |
316 } | 319 } |
317 | 320 |
318 | 321 |
319 /* documentation is in fttrigon.h */ | 322 /* documentation is in fttrigon.h */ |
320 | 323 |
321 FT_EXPORT_DEF( FT_Fixed ) | 324 FT_EXPORT_DEF( FT_Fixed ) |
322 FT_Tan( FT_Angle angle ) | 325 FT_Tan( FT_Angle angle ) |
323 { | 326 { |
324 FT_Vector v; | 327 FT_Vector v; |
325 | 328 |
326 | 329 |
327 v.x = FT_TRIG_SCALE >> 8; | 330 FT_Vector_Unit( &v, angle ); |
328 v.y = 0; | |
329 ft_trig_pseudo_rotate( &v, angle ); | |
330 | 331 |
331 return FT_DivFix( v.y, v.x ); | 332 return FT_DivFix( v.y, v.x ); |
332 } | 333 } |
333 | 334 |
334 | 335 |
335 /* documentation is in fttrigon.h */ | 336 /* documentation is in fttrigon.h */ |
336 | 337 |
337 FT_EXPORT_DEF( FT_Angle ) | 338 FT_EXPORT_DEF( FT_Angle ) |
338 FT_Atan2( FT_Fixed dx, | 339 FT_Atan2( FT_Fixed dx, |
339 FT_Fixed dy ) | 340 FT_Fixed dy ) |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
381 /* documentation is in fttrigon.h */ | 382 /* documentation is in fttrigon.h */ |
382 | 383 |
383 FT_EXPORT_DEF( void ) | 384 FT_EXPORT_DEF( void ) |
384 FT_Vector_Rotate( FT_Vector* vec, | 385 FT_Vector_Rotate( FT_Vector* vec, |
385 FT_Angle angle ) | 386 FT_Angle angle ) |
386 { | 387 { |
387 FT_Int shift; | 388 FT_Int shift; |
388 FT_Vector v; | 389 FT_Vector v; |
389 | 390 |
390 | 391 |
391 if ( !vec ) | 392 if ( !vec || !angle ) |
392 return; | 393 return; |
393 | 394 |
394 v.x = vec->x; | 395 v = *vec; |
395 v.y = vec->y; | |
396 | 396 |
397 if ( angle && ( v.x != 0 || v.y != 0 ) ) | 397 if ( v.x == 0 && v.y == 0 ) |
| 398 return; |
| 399 |
| 400 shift = ft_trig_prenorm( &v ); |
| 401 ft_trig_pseudo_rotate( &v, angle ); |
| 402 v.x = ft_trig_downscale( v.x ); |
| 403 v.y = ft_trig_downscale( v.y ); |
| 404 |
| 405 if ( shift > 0 ) |
398 { | 406 { |
399 shift = ft_trig_prenorm( &v ); | 407 FT_Int32 half = (FT_Int32)1L << ( shift - 1 ); |
400 ft_trig_pseudo_rotate( &v, angle ); | |
401 v.x = ft_trig_downscale( v.x ); | |
402 v.y = ft_trig_downscale( v.y ); | |
403 | |
404 if ( shift > 0 ) | |
405 { | |
406 FT_Int32 half = (FT_Int32)1L << ( shift - 1 ); | |
407 | 408 |
408 | 409 |
409 vec->x = ( v.x + half + FT_SIGN_LONG( v.x ) ) >> shift; | 410 vec->x = ( v.x + half + FT_SIGN_LONG( v.x ) ) >> shift; |
410 vec->y = ( v.y + half + FT_SIGN_LONG( v.y ) ) >> shift; | 411 vec->y = ( v.y + half + FT_SIGN_LONG( v.y ) ) >> shift; |
411 } | 412 } |
412 else | 413 else |
413 { | 414 { |
414 shift = -shift; | 415 shift = -shift; |
415 vec->x = (FT_Pos)( (FT_ULong)v.x << shift ); | 416 vec->x = (FT_Pos)( (FT_ULong)v.x << shift ); |
416 vec->y = (FT_Pos)( (FT_ULong)v.y << shift ); | 417 vec->y = (FT_Pos)( (FT_ULong)v.y << shift ); |
417 } | |
418 } | 418 } |
419 } | 419 } |
420 | 420 |
421 | 421 |
422 /* documentation is in fttrigon.h */ | 422 /* documentation is in fttrigon.h */ |
423 | 423 |
424 FT_EXPORT_DEF( FT_Fixed ) | 424 FT_EXPORT_DEF( FT_Fixed ) |
425 FT_Vector_Length( FT_Vector* vec ) | 425 FT_Vector_Length( FT_Vector* vec ) |
426 { | 426 { |
427 FT_Int shift; | 427 FT_Int shift; |
(...skipping 15 matching lines...) Expand all Loading... |
443 return FT_ABS( v.x ); | 443 return FT_ABS( v.x ); |
444 } | 444 } |
445 | 445 |
446 /* general case */ | 446 /* general case */ |
447 shift = ft_trig_prenorm( &v ); | 447 shift = ft_trig_prenorm( &v ); |
448 ft_trig_pseudo_polarize( &v ); | 448 ft_trig_pseudo_polarize( &v ); |
449 | 449 |
450 v.x = ft_trig_downscale( v.x ); | 450 v.x = ft_trig_downscale( v.x ); |
451 | 451 |
452 if ( shift > 0 ) | 452 if ( shift > 0 ) |
453 return ( v.x + ( 1 << ( shift - 1 ) ) ) >> shift; | 453 return ( v.x + ( 1L << ( shift - 1 ) ) ) >> shift; |
454 | 454 |
455 return (FT_Fixed)( (FT_UInt32)v.x << -shift ); | 455 return (FT_Fixed)( (FT_UInt32)v.x << -shift ); |
456 } | 456 } |
457 | 457 |
458 | 458 |
459 /* documentation is in fttrigon.h */ | 459 /* documentation is in fttrigon.h */ |
460 | 460 |
461 FT_EXPORT_DEF( void ) | 461 FT_EXPORT_DEF( void ) |
462 FT_Vector_Polarize( FT_Vector* vec, | 462 FT_Vector_Polarize( FT_Vector* vec, |
463 FT_Fixed *length, | 463 FT_Fixed *length, |
464 FT_Angle *angle ) | 464 FT_Angle *angle ) |
465 { | 465 { |
466 FT_Int shift; | 466 FT_Int shift; |
467 FT_Vector v; | 467 FT_Vector v; |
468 | 468 |
469 | 469 |
470 if ( !vec || !length || !angle ) | 470 if ( !vec || !length || !angle ) |
471 return; | 471 return; |
472 | 472 |
473 v = *vec; | 473 v = *vec; |
474 | 474 |
475 if ( v.x == 0 && v.y == 0 ) | 475 if ( v.x == 0 && v.y == 0 ) |
476 return; | 476 return; |
477 | 477 |
478 shift = ft_trig_prenorm( &v ); | 478 shift = ft_trig_prenorm( &v ); |
479 ft_trig_pseudo_polarize( &v ); | 479 ft_trig_pseudo_polarize( &v ); |
480 | 480 |
481 v.x = ft_trig_downscale( v.x ); | 481 v.x = ft_trig_downscale( v.x ); |
482 | 482 |
483 *length = ( shift >= 0 ) ? ( v.x >> shift ) | 483 *length = shift >= 0 ? ( v.x >> shift ) |
484 : (FT_Fixed)( (FT_UInt32)v.x << -shift ); | 484 : (FT_Fixed)( (FT_UInt32)v.x << -shift ); |
485 *angle = v.y; | 485 *angle = v.y; |
486 } | 486 } |
487 | 487 |
488 | 488 |
489 /* documentation is in fttrigon.h */ | 489 /* documentation is in fttrigon.h */ |
490 | 490 |
491 FT_EXPORT_DEF( void ) | 491 FT_EXPORT_DEF( void ) |
492 FT_Vector_From_Polar( FT_Vector* vec, | 492 FT_Vector_From_Polar( FT_Vector* vec, |
493 FT_Fixed length, | 493 FT_Fixed length, |
494 FT_Angle angle ) | 494 FT_Angle angle ) |
(...skipping 10 matching lines...) Expand all Loading... |
505 | 505 |
506 /* documentation is in fttrigon.h */ | 506 /* documentation is in fttrigon.h */ |
507 | 507 |
508 FT_EXPORT_DEF( FT_Angle ) | 508 FT_EXPORT_DEF( FT_Angle ) |
509 FT_Angle_Diff( FT_Angle angle1, | 509 FT_Angle_Diff( FT_Angle angle1, |
510 FT_Angle angle2 ) | 510 FT_Angle angle2 ) |
511 { | 511 { |
512 FT_Angle delta = angle2 - angle1; | 512 FT_Angle delta = angle2 - angle1; |
513 | 513 |
514 | 514 |
515 delta %= FT_ANGLE_2PI; | 515 while ( delta <= -FT_ANGLE_PI ) |
516 if ( delta < 0 ) | |
517 delta += FT_ANGLE_2PI; | 516 delta += FT_ANGLE_2PI; |
518 | 517 |
519 if ( delta > FT_ANGLE_PI ) | 518 while ( delta > FT_ANGLE_PI ) |
520 delta -= FT_ANGLE_2PI; | 519 delta -= FT_ANGLE_2PI; |
521 | 520 |
522 return delta; | 521 return delta; |
523 } | 522 } |
524 | 523 |
525 | 524 |
526 /* END */ | 525 /* END */ |
OLD | NEW |