1 /***************************************************************************/
5 /* FreeType trigonometric functions (body). */
7 /* Copyright 2001 by */
8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */
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. */
16 /***************************************************************************/
20 #include FT_TRIGONOMETRY_H
23 /* the following is 0.2715717684432231 * 2^30 */
24 #define FT_TRIG_COSCALE 0x11616E8EUL
26 /* this table was generated for FT_PI = 180L << 16, i.e. degrees */
27 #define FT_TRIG_MAX_ITERS 23
30 ft_trig_arctan_table
[24] =
32 4157273L, 2949120L, 1740967L, 919879L, 466945L, 234379L, 117304L,
33 58666L, 29335L, 14668L, 7334L, 3667L, 1833L, 917L, 458L, 229L, 115L,
34 57L, 29L, 14L, 7L, 4L, 2L, 1L
37 /* the Cordic shrink factor, multiplied by 2^32 */
38 #define FT_TRIG_SCALE 1166391785UL /* 0x4585BA38UL */
41 #ifdef FT_CONFIG_HAS_INT64
43 /* multiply a given value by the CORDIC shrink factor */
45 ft_trig_downscale( FT_Fixed val
)
52 val
= ( val
>= 0 ) ? val
: -val
;
54 v
= ( val
* (FT_Int64
)FT_TRIG_SCALE
) + 0x100000000UL
;
55 val
= (FT_Fixed
)( v
>> 32 );
57 return ( s
>= 0 ) ? val
: -val
;
60 #else /* !FT_CONFIG_HAS_INT64 */
62 /* multiply a given value by the CORDIC shrink factor */
64 ft_trig_downscale( FT_Fixed val
)
67 FT_UInt32 v1
, v2
, k1
, k2
, hi
, lo1
, lo2
, lo3
;
71 val
= ( val
>= 0 ) ? val
: -val
;
73 v1
= (FT_UInt32
)val
>> 16;
74 v2
= (FT_UInt32
)val
& 0xFFFF;
76 k1
= FT_TRIG_SCALE
>> 16; /* constant */
77 k2
= FT_TRIG_SCALE
& 0xFFFF; /* constant */
80 lo1
= k1
* v2
+ k2
* v1
; /* can't overflow */
82 lo2
= ( k2
* v2
) >> 16;
83 lo3
= ( lo1
>= lo2
) ? lo1
: lo2
;
92 return ( s
>= 0 ) ? val
: -val
;
95 #endif /* !FT_CONFIG_HAS_INT64 */
99 ft_trig_prenorm( FT_Vector
* vec
)
108 z
= ( ( x
>= 0 ) ? x
: - x
) | ( (y
>= 0) ? y
: -y
);
111 if ( z
< ( 1L << 27 ) )
117 } while ( z
< ( 1L << 27 ) );
122 else if ( z
> ( 1L << 28 ) )
128 } while ( z
> ( 1L << 28 ) );
139 ft_trig_pseudo_rotate( FT_Vector
* vec
,
143 FT_Fixed x
, y
, xtemp
;
144 const FT_Fixed
*arctanptr
;
150 /* Get angle between -90 and 90 degrees */
151 while ( theta
<= -FT_ANGLE_PI2
)
155 theta
+= FT_ANGLE_PI
;
158 while ( theta
> FT_ANGLE_PI2
)
162 theta
-= FT_ANGLE_PI
;
165 /* Initial pseudorotation, with left shift */
166 arctanptr
= ft_trig_arctan_table
;
170 xtemp
= x
+ ( y
<< 1 );
173 theta
+= *arctanptr
++;
177 xtemp
= x
- ( y
<< 1 );
180 theta
-= *arctanptr
++;
183 /* Subsequent pseudorotations, with right shifts */
189 xtemp
= x
+ ( y
>> i
);
192 theta
+= *arctanptr
++;
196 xtemp
= x
- ( y
>> i
);
199 theta
-= *arctanptr
++;
201 } while ( ++i
< FT_TRIG_MAX_ITERS
);
209 ft_trig_pseudo_polarize( FT_Vector
* vec
)
214 const FT_Fixed
*arctanptr
;
220 /* Get the vector into the right half plane */
226 theta
= 2 * FT_ANGLE_PI2
;
232 arctanptr
= ft_trig_arctan_table
;
236 /* Rotate positive */
240 theta
-= *arctanptr
++; /* Subtract angle */
244 /* Rotate negative */
248 theta
+= *arctanptr
++; /* Add angle */
256 /* Rotate positive */
260 theta
-= *arctanptr
++;
264 /* Rotate negative */
268 theta
+= *arctanptr
++;
270 } while ( ++i
< FT_TRIG_MAX_ITERS
);
274 theta
= ( theta
+ 16 ) & -32;
276 theta
= - (( -theta
+ 16 ) & -32);
283 /* documentation is in fttrigon.h */
285 FT_EXPORT_DEF( FT_Fixed
)
286 FT_Cos( FT_Angle angle
)
291 v
.x
= FT_TRIG_COSCALE
>> 2;
293 ft_trig_pseudo_rotate( &v
, angle
);
295 return v
.x
/ ( 1 << 12 );
299 /* documentation is in fttrigon.h */
301 FT_EXPORT_DEF( FT_Fixed
)
302 FT_Sin( FT_Angle angle
)
304 return FT_Cos( FT_ANGLE_PI2
- angle
);
308 /* documentation is in fttrigon.h */
310 FT_EXPORT_DEF( FT_Fixed
)
311 FT_Tan( FT_Angle angle
)
316 v
.x
= FT_TRIG_COSCALE
>> 2;
318 ft_trig_pseudo_rotate( &v
, angle
);
320 return FT_DivFix( v
.y
, v
.x
);
324 /* documentation is in fttrigon.h */
326 FT_EXPORT_DEF( FT_Angle
)
327 FT_Atan2( FT_Fixed dx
,
333 if ( dx
== 0 && dy
== 0 )
338 ft_trig_prenorm( &v
);
339 ft_trig_pseudo_polarize( &v
);
345 /* documentation is in fttrigon.h */
347 FT_EXPORT_DEF( void )
348 FT_Vector_Unit( FT_Vector
* vec
,
351 vec
->x
= FT_TRIG_COSCALE
>> 2;
353 ft_trig_pseudo_rotate( vec
, angle
);
359 /* documentation is in fttrigon.h */
361 FT_EXPORT_DEF( void )
362 FT_Vector_Rotate( FT_Vector
* vec
,
372 if ( angle
&& ( v
.x
!= 0 || v
.y
!= 0 ) )
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
);
381 vec
->x
= v
.x
>> shift
;
382 vec
->y
= v
.y
>> shift
;
387 vec
->x
= v
.x
<< shift
;
388 vec
->y
= v
.y
<< shift
;
394 /* documentation is in fttrigon.h */
396 FT_EXPORT_DEF( FT_Fixed
)
397 FT_Vector_Length( FT_Vector
* vec
)
405 /* handle trivial cases */
408 return ( v
.y
>= 0 ) ? v
.y
: -v
.y
;
412 return ( v
.x
>= 0 ) ? v
.x
: -v
.x
;
416 shift
= ft_trig_prenorm( &v
);
417 ft_trig_pseudo_polarize( &v
);
419 v
.x
= ft_trig_downscale( v
.x
);
422 return ( v
.x
+ ( 1 << ( shift
- 1 ) ) ) >> shift
;
424 return v
.x
<< -shift
;
428 /* documentation is in fttrigon.h */
430 FT_EXPORT_DEF( void )
431 FT_Vector_Polarize( FT_Vector
* vec
,
441 if ( v
.x
== 0 && v
.y
== 0 )
444 shift
= ft_trig_prenorm( &v
);
445 ft_trig_pseudo_polarize( &v
);
447 v
.x
= ft_trig_downscale( v
.x
);
449 *length
= ( shift
>= 0 ) ? ( v
.x
>> shift
) : ( v
.x
<< -shift
);