blob: 9f513946b830eabb25a34a2620a308a87045967e [file] [log] [blame]
Werner Lembergec6ddd52001-05-12 18:04:08 +00001/***************************************************************************/
2/* */
3/* fttrigon.c */
4/* */
5/* FreeType trigonometric functions (body). */
6/* */
Werner Lembergcee37a32005-11-12 07:34:40 +00007/* Copyright 2001, 2002, 2003, 2004, 2005 by */
Werner Lembergec6ddd52001-05-12 18:04:08 +00008/* 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
David Turnerebe85f52001-05-11 14:25:57 +000019#include <ft2build.h>
Werner Lemberg80cfbd72003-12-26 07:26:08 +000020#include FT_INTERNAL_OBJECTS_H
David Turnerebe85f52001-05-11 14:25:57 +000021#include FT_TRIGONOMETRY_H
22
Werner Lembergec6ddd52001-05-12 18:04:08 +000023
24 /* the following is 0.2715717684432231 * 2^30 */
25#define FT_TRIG_COSCALE 0x11616E8EUL
David Turnerebe85f52001-05-11 14:25:57 +000026
27 /* this table was generated for FT_PI = 180L << 16, i.e. degrees */
Werner Lembergec6ddd52001-05-12 18:04:08 +000028#define FT_TRIG_MAX_ITERS 23
David Turnerebe85f52001-05-11 14:25:57 +000029
30 static const FT_Fixed
Werner Lembergec6ddd52001-05-12 18:04:08 +000031 ft_trig_arctan_table[24] =
David Turnerebe85f52001-05-11 14:25:57 +000032 {
Werner Lembergcf24d512001-06-18 14:23:45 +000033 4157273L, 2949120L, 1740967L, 919879L, 466945L, 234379L, 117304L,
34 58666L, 29335L, 14668L, 7334L, 3667L, 1833L, 917L, 458L, 229L, 115L,
35 57L, 29L, 14L, 7L, 4L, 2L, 1L
David Turnerebe85f52001-05-11 14:25:57 +000036 };
37
Werner Lembergec6ddd52001-05-12 18:04:08 +000038 /* the Cordic shrink factor, multiplied by 2^32 */
39#define FT_TRIG_SCALE 1166391785UL /* 0x4585BA38UL */
David Turnerebe85f52001-05-11 14:25:57 +000040
David Turnerebe85f52001-05-11 14:25:57 +000041
42#ifdef FT_CONFIG_HAS_INT64
43
Werner Lembergec6ddd52001-05-12 18:04:08 +000044 /* multiply a given value by the CORDIC shrink factor */
Werner Lembergf814d0f2001-06-27 16:18:10 +000045 static FT_Fixed
46 ft_trig_downscale( FT_Fixed val )
David Turnerebe85f52001-05-11 14:25:57 +000047 {
48 FT_Fixed s;
49 FT_Int64 v;
50
Werner Lembergec6ddd52001-05-12 18:04:08 +000051
David Turnerebe85f52001-05-11 14:25:57 +000052 s = val;
Werner Lembergec6ddd52001-05-12 18:04:08 +000053 val = ( val >= 0 ) ? val : -val;
Werner Lemberg415235d2001-06-28 17:49:10 +000054
Werner Lembergec6ddd52001-05-12 18:04:08 +000055 v = ( val * (FT_Int64)FT_TRIG_SCALE ) + 0x100000000UL;
56 val = (FT_Fixed)( v >> 32 );
David Turnerebe85f52001-05-11 14:25:57 +000057
58 return ( s >= 0 ) ? val : -val;
59 }
60
61#else /* !FT_CONFIG_HAS_INT64 */
62
Werner Lembergec6ddd52001-05-12 18:04:08 +000063 /* multiply a given value by the CORDIC shrink factor */
Werner Lembergf814d0f2001-06-27 16:18:10 +000064 static FT_Fixed
65 ft_trig_downscale( FT_Fixed val )
David Turnerebe85f52001-05-11 14:25:57 +000066 {
67 FT_Fixed s;
68 FT_UInt32 v1, v2, k1, k2, hi, lo1, lo2, lo3;
Werner Lemberg415235d2001-06-28 17:49:10 +000069
Werner Lembergec6ddd52001-05-12 18:04:08 +000070
David Turnerebe85f52001-05-11 14:25:57 +000071 s = val;
72 val = ( val >= 0 ) ? val : -val;
73
74 v1 = (FT_UInt32)val >> 16;
Werner Lemberg43ba0842003-06-23 19:26:53 +000075 v2 = (FT_UInt32)val & 0xFFFFL;
Werner Lemberg415235d2001-06-28 17:49:10 +000076
Werner Lembergec6ddd52001-05-12 18:04:08 +000077 k1 = FT_TRIG_SCALE >> 16; /* constant */
Werner Lemberg43ba0842003-06-23 19:26:53 +000078 k2 = FT_TRIG_SCALE & 0xFFFFL; /* constant */
David Turnerebe85f52001-05-11 14:25:57 +000079
Werner Lembergec6ddd52001-05-12 18:04:08 +000080 hi = k1 * v1;
81 lo1 = k1 * v2 + k2 * v1; /* can't overflow */
Werner Lemberg415235d2001-06-28 17:49:10 +000082
Werner Lembergec6ddd52001-05-12 18:04:08 +000083 lo2 = ( k2 * v2 ) >> 16;
David Turnerebe85f52001-05-11 14:25:57 +000084 lo3 = ( lo1 >= lo2 ) ? lo1 : lo2;
85 lo1 += lo2;
86
87 hi += lo1 >> 16;
Werner Lembergec6ddd52001-05-12 18:04:08 +000088 if ( lo1 < lo3 )
89 hi += 0x10000UL;
David Turnerebe85f52001-05-11 14:25:57 +000090
91 val = (FT_Fixed)hi;
92
93 return ( s >= 0 ) ? val : -val;
94 }
95
96#endif /* !FT_CONFIG_HAS_INT64 */
97
98
Werner Lembergf814d0f2001-06-27 16:18:10 +000099 static FT_Int
100 ft_trig_prenorm( FT_Vector* vec )
David Turnerebe85f52001-05-11 14:25:57 +0000101 {
102 FT_Fixed x, y, z;
103 FT_Int shift;
104
Werner Lembergec6ddd52001-05-12 18:04:08 +0000105
David Turnerebe85f52001-05-11 14:25:57 +0000106 x = vec->x;
107 y = vec->y;
Werner Lemberg415235d2001-06-28 17:49:10 +0000108
Werner Lembergec6ddd52001-05-12 18:04:08 +0000109 z = ( ( x >= 0 ) ? x : - x ) | ( (y >= 0) ? y : -y );
David Turnerebe85f52001-05-11 14:25:57 +0000110 shift = 0;
Werner Lemberg415235d2001-06-28 17:49:10 +0000111
David Turner9fbd2ab2005-10-28 16:14:14 +0000112#if 1
Werner Lembergcee37a32005-11-12 07:34:40 +0000113 /* determine msb bit index in `shift' */
114 if ( z >= ( 1L << 16 ) )
David Turner9fbd2ab2005-10-28 16:14:14 +0000115 {
116 z >>= 16;
117 shift += 16;
118 }
Werner Lembergcee37a32005-11-12 07:34:40 +0000119 if ( z >= ( 1L << 8 ) )
David Turner9fbd2ab2005-10-28 16:14:14 +0000120 {
121 z >>= 8;
122 shift += 8;
123 }
Werner Lembergcee37a32005-11-12 07:34:40 +0000124 if ( z >= ( 1L << 4 ) )
David Turner9fbd2ab2005-10-28 16:14:14 +0000125 {
126 z >>= 4;
127 shift += 4;
128 }
Werner Lembergcee37a32005-11-12 07:34:40 +0000129 if ( z >= ( 1L << 2 ) )
David Turner9fbd2ab2005-10-28 16:14:14 +0000130 {
131 z >>= 2;
132 shift += 2;
133 }
David Turnerf7cc1812005-11-15 17:30:56 +0000134 if ( z >= ( 1L << 1 ) )
David Turner9fbd2ab2005-10-28 16:14:14 +0000135 {
David Turnerf7cc1812005-11-15 17:30:56 +0000136 z >>= 1;
137 shift += 1;
138 }
139
140 if ( shift <= 27 )
141 {
142 shift = 27 - shift;
David Turner9fbd2ab2005-10-28 16:14:14 +0000143 vec->x = x << shift;
144 vec->y = y << shift;
145 }
David Turnerf7cc1812005-11-15 17:30:56 +0000146 else
David Turner9fbd2ab2005-10-28 16:14:14 +0000147 {
David Turnerf7cc1812005-11-15 17:30:56 +0000148 shift -= 27;
David Turner9fbd2ab2005-10-28 16:14:14 +0000149 vec->x = x >> shift;
150 vec->y = y >> shift;
151 shift = -shift;
152 }
Werner Lembergcee37a32005-11-12 07:34:40 +0000153
154#else /* 0 */
155
Werner Lembergec6ddd52001-05-12 18:04:08 +0000156 if ( z < ( 1L << 27 ) )
David Turnerebe85f52001-05-11 14:25:57 +0000157 {
158 do
159 {
160 shift++;
161 z <<= 1;
Werner Lembergec6ddd52001-05-12 18:04:08 +0000162 } while ( z < ( 1L << 27 ) );
Werner Lembergec6ddd52001-05-12 18:04:08 +0000163 vec->x = x << shift;
164 vec->y = y << shift;
David Turnerebe85f52001-05-11 14:25:57 +0000165 }
Werner Lembergec6ddd52001-05-12 18:04:08 +0000166 else if ( z > ( 1L << 28 ) )
David Turnerebe85f52001-05-11 14:25:57 +0000167 {
168 do
169 {
170 shift++;
171 z >>= 1;
Werner Lembergec6ddd52001-05-12 18:04:08 +0000172 } while ( z > ( 1L << 28 ) );
David Turnerebe85f52001-05-11 14:25:57 +0000173
Werner Lembergec6ddd52001-05-12 18:04:08 +0000174 vec->x = x >> shift;
175 vec->y = y >> shift;
David Turnerebe85f52001-05-11 14:25:57 +0000176 shift = -shift;
177 }
Werner Lembergcee37a32005-11-12 07:34:40 +0000178
179#endif /* 0 */
180
David Turnerebe85f52001-05-11 14:25:57 +0000181 return shift;
182 }
Werner Lemberg415235d2001-06-28 17:49:10 +0000183
David Turnerebe85f52001-05-11 14:25:57 +0000184
Werner Lembergf814d0f2001-06-27 16:18:10 +0000185 static void
186 ft_trig_pseudo_rotate( FT_Vector* vec,
187 FT_Angle theta )
David Turnerebe85f52001-05-11 14:25:57 +0000188 {
Werner Lembergec6ddd52001-05-12 18:04:08 +0000189 FT_Int i;
190 FT_Fixed x, y, xtemp;
191 const FT_Fixed *arctanptr;
192
David Turnerebe85f52001-05-11 14:25:57 +0000193
194 x = vec->x;
195 y = vec->y;
196
197 /* Get angle between -90 and 90 degrees */
Werner Lembergec6ddd52001-05-12 18:04:08 +0000198 while ( theta <= -FT_ANGLE_PI2 )
David Turnerebe85f52001-05-11 14:25:57 +0000199 {
200 x = -x;
201 y = -y;
202 theta += FT_ANGLE_PI;
203 }
Werner Lembergec6ddd52001-05-12 18:04:08 +0000204
205 while ( theta > FT_ANGLE_PI2 )
David Turnerebe85f52001-05-11 14:25:57 +0000206 {
207 x = -x;
Werner Lemberg415235d2001-06-28 17:49:10 +0000208 y = -y;
David Turnerebe85f52001-05-11 14:25:57 +0000209 theta -= FT_ANGLE_PI;
210 }
211
212 /* Initial pseudorotation, with left shift */
213 arctanptr = ft_trig_arctan_table;
Werner Lembergec6ddd52001-05-12 18:04:08 +0000214
215 if ( theta < 0 )
David Turnerebe85f52001-05-11 14:25:57 +0000216 {
Werner Lembergec6ddd52001-05-12 18:04:08 +0000217 xtemp = x + ( y << 1 );
218 y = y - ( x << 1 );
David Turnerebe85f52001-05-11 14:25:57 +0000219 x = xtemp;
220 theta += *arctanptr++;
221 }
222 else
223 {
Werner Lembergec6ddd52001-05-12 18:04:08 +0000224 xtemp = x - ( y << 1 );
225 y = y + ( x << 1 );
David Turnerebe85f52001-05-11 14:25:57 +0000226 x = xtemp;
227 theta -= *arctanptr++;
228 }
229
230 /* Subsequent pseudorotations, with right shifts */
231 i = 0;
232 do
233 {
Werner Lembergec6ddd52001-05-12 18:04:08 +0000234 if ( theta < 0 )
David Turnerebe85f52001-05-11 14:25:57 +0000235 {
Werner Lembergec6ddd52001-05-12 18:04:08 +0000236 xtemp = x + ( y >> i );
237 y = y - ( x >> i );
238 x = xtemp;
David Turnerebe85f52001-05-11 14:25:57 +0000239 theta += *arctanptr++;
240 }
241 else
242 {
Werner Lembergec6ddd52001-05-12 18:04:08 +0000243 xtemp = x - ( y >> i );
244 y = y + ( x >> i );
David Turnerebe85f52001-05-11 14:25:57 +0000245 x = xtemp;
246 theta -= *arctanptr++;
247 }
Werner Lembergec6ddd52001-05-12 18:04:08 +0000248 } while ( ++i < FT_TRIG_MAX_ITERS );
David Turnerebe85f52001-05-11 14:25:57 +0000249
250 vec->x = x;
251 vec->y = y;
252 }
253
254
Werner Lembergf814d0f2001-06-27 16:18:10 +0000255 static void
256 ft_trig_pseudo_polarize( FT_Vector* vec )
David Turnerebe85f52001-05-11 14:25:57 +0000257 {
Werner Lembergec6ddd52001-05-12 18:04:08 +0000258 FT_Fixed theta;
259 FT_Fixed yi, i;
260 FT_Fixed x, y;
261 const FT_Fixed *arctanptr;
262
David Turnerebe85f52001-05-11 14:25:57 +0000263
264 x = vec->x;
265 y = vec->y;
266
267 /* Get the vector into the right half plane */
268 theta = 0;
Werner Lembergec6ddd52001-05-12 18:04:08 +0000269 if ( x < 0 )
David Turnerebe85f52001-05-11 14:25:57 +0000270 {
271 x = -x;
272 y = -y;
273 theta = 2 * FT_ANGLE_PI2;
274 }
275
Werner Lembergec6ddd52001-05-12 18:04:08 +0000276 if ( y > 0 )
David Turnerebe85f52001-05-11 14:25:57 +0000277 theta = - theta;
278
279 arctanptr = ft_trig_arctan_table;
Werner Lembergec6ddd52001-05-12 18:04:08 +0000280
281 if ( y < 0 )
David Turnerebe85f52001-05-11 14:25:57 +0000282 {
283 /* Rotate positive */
Werner Lembergec6ddd52001-05-12 18:04:08 +0000284 yi = y + ( x << 1 );
285 x = x - ( y << 1 );
286 y = yi;
David Turnerebe85f52001-05-11 14:25:57 +0000287 theta -= *arctanptr++; /* Subtract angle */
288 }
289 else
290 {
291 /* Rotate negative */
Werner Lembergec6ddd52001-05-12 18:04:08 +0000292 yi = y - ( x << 1 );
293 x = x + ( y << 1 );
294 y = yi;
David Turnerebe85f52001-05-11 14:25:57 +0000295 theta += *arctanptr++; /* Add angle */
296 }
297
298 i = 0;
299 do
300 {
Werner Lembergec6ddd52001-05-12 18:04:08 +0000301 if ( y < 0 )
David Turnerebe85f52001-05-11 14:25:57 +0000302 {
303 /* Rotate positive */
Werner Lembergec6ddd52001-05-12 18:04:08 +0000304 yi = y + ( x >> i );
305 x = x - ( y >> i );
306 y = yi;
David Turnerebe85f52001-05-11 14:25:57 +0000307 theta -= *arctanptr++;
308 }
309 else
310 {
311 /* Rotate negative */
Werner Lembergec6ddd52001-05-12 18:04:08 +0000312 yi = y - ( x >> i );
313 x = x + ( y >> i );
314 y = yi;
David Turnerebe85f52001-05-11 14:25:57 +0000315 theta += *arctanptr++;
316 }
Werner Lembergec6ddd52001-05-12 18:04:08 +0000317 } while ( ++i < FT_TRIG_MAX_ITERS );
David Turnerebe85f52001-05-11 14:25:57 +0000318
319 /* round theta */
320 if ( theta >= 0 )
David Turner87c0d302003-12-24 01:10:46 +0000321 theta = FT_PAD_ROUND( theta, 32 );
David Turnerebe85f52001-05-11 14:25:57 +0000322 else
Werner Lembergf13516c2005-03-03 17:09:08 +0000323 theta = -FT_PAD_ROUND( -theta, 32 );
David Turnerebe85f52001-05-11 14:25:57 +0000324
325 vec->x = x;
326 vec->y = theta;
327 }
328
329
Werner Lembergec6ddd52001-05-12 18:04:08 +0000330 /* documentation is in fttrigon.h */
331
Werner Lembergf814d0f2001-06-27 16:18:10 +0000332 FT_EXPORT_DEF( FT_Fixed )
333 FT_Cos( FT_Angle angle )
David Turnerebe85f52001-05-11 14:25:57 +0000334 {
335 FT_Vector v;
Werner Lemberg415235d2001-06-28 17:49:10 +0000336
Werner Lembergec6ddd52001-05-12 18:04:08 +0000337
David Turnerebe85f52001-05-11 14:25:57 +0000338 v.x = FT_TRIG_COSCALE >> 2;
339 v.y = 0;
340 ft_trig_pseudo_rotate( &v, angle );
Werner Lemberg415235d2001-06-28 17:49:10 +0000341
Werner Lemberg5da9dd72001-12-16 08:17:33 +0000342 return v.x / ( 1 << 12 );
David Turnerebe85f52001-05-11 14:25:57 +0000343 }
344
345
Werner Lembergec6ddd52001-05-12 18:04:08 +0000346 /* documentation is in fttrigon.h */
347
Werner Lembergf814d0f2001-06-27 16:18:10 +0000348 FT_EXPORT_DEF( FT_Fixed )
349 FT_Sin( FT_Angle angle )
David Turnerebe85f52001-05-11 14:25:57 +0000350 {
Werner Lembergec6ddd52001-05-12 18:04:08 +0000351 return FT_Cos( FT_ANGLE_PI2 - angle );
David Turnerebe85f52001-05-11 14:25:57 +0000352 }
353
354
Werner Lembergec6ddd52001-05-12 18:04:08 +0000355 /* documentation is in fttrigon.h */
356
Werner Lembergf814d0f2001-06-27 16:18:10 +0000357 FT_EXPORT_DEF( FT_Fixed )
358 FT_Tan( FT_Angle angle )
David Turnerebe85f52001-05-11 14:25:57 +0000359 {
360 FT_Vector v;
Werner Lemberg415235d2001-06-28 17:49:10 +0000361
Werner Lembergec6ddd52001-05-12 18:04:08 +0000362
David Turnerebe85f52001-05-11 14:25:57 +0000363 v.x = FT_TRIG_COSCALE >> 2;
364 v.y = 0;
365 ft_trig_pseudo_rotate( &v, angle );
Werner Lemberg415235d2001-06-28 17:49:10 +0000366
David Turnerebe85f52001-05-11 14:25:57 +0000367 return FT_DivFix( v.y, v.x );
368 }
369
370
Werner Lembergec6ddd52001-05-12 18:04:08 +0000371 /* documentation is in fttrigon.h */
David Turnerebe85f52001-05-11 14:25:57 +0000372
Werner Lembergf814d0f2001-06-27 16:18:10 +0000373 FT_EXPORT_DEF( FT_Angle )
374 FT_Atan2( FT_Fixed dx,
375 FT_Fixed dy )
David Turnerebe85f52001-05-11 14:25:57 +0000376 {
377 FT_Vector v;
Werner Lemberg415235d2001-06-28 17:49:10 +0000378
Werner Lembergec6ddd52001-05-12 18:04:08 +0000379
David Turnerebe85f52001-05-11 14:25:57 +0000380 if ( dx == 0 && dy == 0 )
381 return 0;
382
383 v.x = dx;
Werner Lemberg415235d2001-06-28 17:49:10 +0000384 v.y = dy;
David Turnerebe85f52001-05-11 14:25:57 +0000385 ft_trig_prenorm( &v );
386 ft_trig_pseudo_polarize( &v );
Werner Lembergec6ddd52001-05-12 18:04:08 +0000387
David Turnerebe85f52001-05-11 14:25:57 +0000388 return v.y;
389 }
390
391
Werner Lembergec6ddd52001-05-12 18:04:08 +0000392 /* documentation is in fttrigon.h */
393
Werner Lembergf814d0f2001-06-27 16:18:10 +0000394 FT_EXPORT_DEF( void )
395 FT_Vector_Unit( FT_Vector* vec,
396 FT_Angle angle )
David Turnerebe85f52001-05-11 14:25:57 +0000397 {
Werner Lembergec6ddd52001-05-12 18:04:08 +0000398 vec->x = FT_TRIG_COSCALE >> 2;
399 vec->y = 0;
400 ft_trig_pseudo_rotate( vec, angle );
401 vec->x >>= 12;
402 vec->y >>= 12;
David Turnerebe85f52001-05-11 14:25:57 +0000403 }
404
405
Werner Lemberg4f107452003-05-17 12:07:45 +0000406 /* these macros return 0 for positive numbers,
407 and -1 for negative ones */
408#define FT_SIGN_LONG( x ) ( (x) >> ( FT_SIZEOF_LONG * 8 - 1 ) )
409#define FT_SIGN_INT( x ) ( (x) >> ( FT_SIZEOF_INT * 8 - 1 ) )
410#define FT_SIGN_INT32( x ) ( (x) >> 31 )
411#define FT_SIGN_INT16( x ) ( (x) >> 15 )
412
413
Werner Lembergec6ddd52001-05-12 18:04:08 +0000414 /* documentation is in fttrigon.h */
415
Werner Lembergf814d0f2001-06-27 16:18:10 +0000416 FT_EXPORT_DEF( void )
417 FT_Vector_Rotate( FT_Vector* vec,
418 FT_Angle angle )
David Turnerebe85f52001-05-11 14:25:57 +0000419 {
420 FT_Int shift;
421 FT_Vector v;
Werner Lemberg415235d2001-06-28 17:49:10 +0000422
Werner Lembergec6ddd52001-05-12 18:04:08 +0000423
Werner Lemberg4f107452003-05-17 12:07:45 +0000424 v.x = vec->x;
425 v.y = vec->y;
Werner Lembergec6ddd52001-05-12 18:04:08 +0000426
David Turnerebe85f52001-05-11 14:25:57 +0000427 if ( angle && ( v.x != 0 || v.y != 0 ) )
428 {
429 shift = ft_trig_prenorm( &v );
430 ft_trig_pseudo_rotate( &v, angle );
431 v.x = ft_trig_downscale( v.x );
432 v.y = ft_trig_downscale( v.y );
Werner Lemberg415235d2001-06-28 17:49:10 +0000433
Werner Lemberg4f107452003-05-17 12:07:45 +0000434 if ( shift > 0 )
David Turnerebe85f52001-05-11 14:25:57 +0000435 {
Werner Lemberg4f107452003-05-17 12:07:45 +0000436 FT_Int32 half = 1L << ( shift - 1 );
437
438
439 vec->x = ( v.x + half + FT_SIGN_LONG( v.x ) ) >> shift;
440 vec->y = ( v.y + half + FT_SIGN_LONG( v.y ) ) >> shift;
David Turnerebe85f52001-05-11 14:25:57 +0000441 }
442 else
443 {
444 shift = -shift;
445 vec->x = v.x << shift;
446 vec->y = v.y << shift;
447 }
448 }
449 }
450
451
Werner Lembergec6ddd52001-05-12 18:04:08 +0000452 /* documentation is in fttrigon.h */
453
Werner Lembergf814d0f2001-06-27 16:18:10 +0000454 FT_EXPORT_DEF( FT_Fixed )
455 FT_Vector_Length( FT_Vector* vec )
David Turnerebe85f52001-05-11 14:25:57 +0000456 {
Werner Lembergec6ddd52001-05-12 18:04:08 +0000457 FT_Int shift;
458 FT_Vector v;
Werner Lemberg415235d2001-06-28 17:49:10 +0000459
Werner Lembergec6ddd52001-05-12 18:04:08 +0000460
David Turnerebe85f52001-05-11 14:25:57 +0000461 v = *vec;
462
Werner Lemberg415235d2001-06-28 17:49:10 +0000463 /* handle trivial cases */
David Turnerebe85f52001-05-11 14:25:57 +0000464 if ( v.x == 0 )
465 {
466 return ( v.y >= 0 ) ? v.y : -v.y;
467 }
468 else if ( v.y == 0 )
469 {
470 return ( v.x >= 0 ) ? v.x : -v.x;
471 }
472
473 /* general case */
474 shift = ft_trig_prenorm( &v );
475 ft_trig_pseudo_polarize( &v );
Werner Lemberg415235d2001-06-28 17:49:10 +0000476
David Turnerebe85f52001-05-11 14:25:57 +0000477 v.x = ft_trig_downscale( v.x );
Werner Lemberg04728a82002-04-02 14:50:31 +0000478
479 if ( shift > 0 )
480 return ( v.x + ( 1 << ( shift - 1 ) ) ) >> shift;
481
482 return v.x << -shift;
Werner Lemberg415235d2001-06-28 17:49:10 +0000483 }
David Turnerebe85f52001-05-11 14:25:57 +0000484
485
Werner Lembergec6ddd52001-05-12 18:04:08 +0000486 /* documentation is in fttrigon.h */
487
Werner Lembergf814d0f2001-06-27 16:18:10 +0000488 FT_EXPORT_DEF( void )
489 FT_Vector_Polarize( FT_Vector* vec,
490 FT_Fixed *length,
491 FT_Angle *angle )
David Turnerebe85f52001-05-11 14:25:57 +0000492 {
Werner Lembergec6ddd52001-05-12 18:04:08 +0000493 FT_Int shift;
494 FT_Vector v;
495
Werner Lemberg415235d2001-06-28 17:49:10 +0000496
David Turnerebe85f52001-05-11 14:25:57 +0000497 v = *vec;
Werner Lemberg415235d2001-06-28 17:49:10 +0000498
David Turnerebe85f52001-05-11 14:25:57 +0000499 if ( v.x == 0 && v.y == 0 )
500 return;
Werner Lemberg415235d2001-06-28 17:49:10 +0000501
David Turnerebe85f52001-05-11 14:25:57 +0000502 shift = ft_trig_prenorm( &v );
503 ft_trig_pseudo_polarize( &v );
Werner Lemberg415235d2001-06-28 17:49:10 +0000504
David Turnerebe85f52001-05-11 14:25:57 +0000505 v.x = ft_trig_downscale( v.x );
506
Werner Lembergec6ddd52001-05-12 18:04:08 +0000507 *length = ( shift >= 0 ) ? ( v.x >> shift ) : ( v.x << -shift );
David Turnerebe85f52001-05-11 14:25:57 +0000508 *angle = v.y;
Werner Lemberg415235d2001-06-28 17:49:10 +0000509 }
David Turnerebe85f52001-05-11 14:25:57 +0000510
511
David Turnerb7e18ef2002-06-26 22:05:05 +0000512 /* documentation is in fttrigon.h */
513
David Turner0d73b0c2002-06-26 23:45:21 +0000514 FT_EXPORT_DEF( void )
515 FT_Vector_From_Polar( FT_Vector* vec,
516 FT_Fixed length,
517 FT_Angle angle )
518 {
519 vec->x = length;
520 vec->y = 0;
521
522 FT_Vector_Rotate( vec, angle );
523 }
524
525
526 /* documentation is in fttrigon.h */
527
David Turnerb7e18ef2002-06-26 22:05:05 +0000528 FT_EXPORT_DEF( FT_Angle )
David Turnerac90c0e2002-07-01 21:35:17 +0000529 FT_Angle_Diff( FT_Angle angle1,
530 FT_Angle angle2 )
David Turnerb7e18ef2002-06-26 22:05:05 +0000531 {
532 FT_Angle delta = angle2 - angle1;
David Turner0d73b0c2002-06-26 23:45:21 +0000533
Werner Lemberg1ec39632004-11-24 07:08:21 +0000534
David Turnerb7e18ef2002-06-26 22:05:05 +0000535 delta %= FT_ANGLE_2PI;
David Turner20e33152003-01-07 22:54:02 +0000536 if ( delta < 0 )
537 delta += FT_ANGLE_2PI;
David Turnerb7e18ef2002-06-26 22:05:05 +0000538
539 if ( delta > FT_ANGLE_PI )
540 delta -= FT_ANGLE_2PI;
David Turner0d73b0c2002-06-26 23:45:21 +0000541
David Turnerb7e18ef2002-06-26 22:05:05 +0000542 return delta;
David Turner0d73b0c2002-06-26 23:45:21 +0000543 }
David Turnerb7e18ef2002-06-26 22:05:05 +0000544
545
Werner Lembergec6ddd52001-05-12 18:04:08 +0000546/* END */