blob: 4212a7906b9c25b15eef78d3b6602f509c0b6c50 [file] [log] [blame]
Werner Lembergec6ddd52001-05-12 18:04:08 +00001/***************************************************************************/
2/* */
3/* fttrigon.c */
4/* */
5/* FreeType trigonometric functions (body). */
6/* */
Werner Lemberg1ec39632004-11-24 07:08:21 +00007/* Copyright 2001, 2002, 2003, 2004 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
Werner Lembergec6ddd52001-05-12 18:04:08 +0000112 if ( z < ( 1L << 27 ) )
David Turnerebe85f52001-05-11 14:25:57 +0000113 {
114 do
115 {
116 shift++;
117 z <<= 1;
Werner Lembergec6ddd52001-05-12 18:04:08 +0000118 } while ( z < ( 1L << 27 ) );
Werner Lemberg415235d2001-06-28 17:49:10 +0000119
Werner Lembergec6ddd52001-05-12 18:04:08 +0000120 vec->x = x << shift;
121 vec->y = y << shift;
David Turnerebe85f52001-05-11 14:25:57 +0000122 }
Werner Lembergec6ddd52001-05-12 18:04:08 +0000123 else if ( z > ( 1L << 28 ) )
David Turnerebe85f52001-05-11 14:25:57 +0000124 {
125 do
126 {
127 shift++;
128 z >>= 1;
Werner Lembergec6ddd52001-05-12 18:04:08 +0000129 } while ( z > ( 1L << 28 ) );
David Turnerebe85f52001-05-11 14:25:57 +0000130
Werner Lembergec6ddd52001-05-12 18:04:08 +0000131 vec->x = x >> shift;
132 vec->y = y >> shift;
David Turnerebe85f52001-05-11 14:25:57 +0000133 shift = -shift;
134 }
135 return shift;
136 }
Werner Lemberg415235d2001-06-28 17:49:10 +0000137
David Turnerebe85f52001-05-11 14:25:57 +0000138
Werner Lembergf814d0f2001-06-27 16:18:10 +0000139 static void
140 ft_trig_pseudo_rotate( FT_Vector* vec,
141 FT_Angle theta )
David Turnerebe85f52001-05-11 14:25:57 +0000142 {
Werner Lembergec6ddd52001-05-12 18:04:08 +0000143 FT_Int i;
144 FT_Fixed x, y, xtemp;
145 const FT_Fixed *arctanptr;
146
David Turnerebe85f52001-05-11 14:25:57 +0000147
148 x = vec->x;
149 y = vec->y;
150
151 /* Get angle between -90 and 90 degrees */
Werner Lembergec6ddd52001-05-12 18:04:08 +0000152 while ( theta <= -FT_ANGLE_PI2 )
David Turnerebe85f52001-05-11 14:25:57 +0000153 {
154 x = -x;
155 y = -y;
156 theta += FT_ANGLE_PI;
157 }
Werner Lembergec6ddd52001-05-12 18:04:08 +0000158
159 while ( theta > FT_ANGLE_PI2 )
David Turnerebe85f52001-05-11 14:25:57 +0000160 {
161 x = -x;
Werner Lemberg415235d2001-06-28 17:49:10 +0000162 y = -y;
David Turnerebe85f52001-05-11 14:25:57 +0000163 theta -= FT_ANGLE_PI;
164 }
165
166 /* Initial pseudorotation, with left shift */
167 arctanptr = ft_trig_arctan_table;
Werner Lembergec6ddd52001-05-12 18:04:08 +0000168
169 if ( theta < 0 )
David Turnerebe85f52001-05-11 14:25:57 +0000170 {
Werner Lembergec6ddd52001-05-12 18:04:08 +0000171 xtemp = x + ( y << 1 );
172 y = y - ( x << 1 );
David Turnerebe85f52001-05-11 14:25:57 +0000173 x = xtemp;
174 theta += *arctanptr++;
175 }
176 else
177 {
Werner Lembergec6ddd52001-05-12 18:04:08 +0000178 xtemp = x - ( y << 1 );
179 y = y + ( x << 1 );
David Turnerebe85f52001-05-11 14:25:57 +0000180 x = xtemp;
181 theta -= *arctanptr++;
182 }
183
184 /* Subsequent pseudorotations, with right shifts */
185 i = 0;
186 do
187 {
Werner Lembergec6ddd52001-05-12 18:04:08 +0000188 if ( theta < 0 )
David Turnerebe85f52001-05-11 14:25:57 +0000189 {
Werner Lembergec6ddd52001-05-12 18:04:08 +0000190 xtemp = x + ( y >> i );
191 y = y - ( x >> i );
192 x = xtemp;
David Turnerebe85f52001-05-11 14:25:57 +0000193 theta += *arctanptr++;
194 }
195 else
196 {
Werner Lembergec6ddd52001-05-12 18:04:08 +0000197 xtemp = x - ( y >> i );
198 y = y + ( x >> i );
David Turnerebe85f52001-05-11 14:25:57 +0000199 x = xtemp;
200 theta -= *arctanptr++;
201 }
Werner Lembergec6ddd52001-05-12 18:04:08 +0000202 } while ( ++i < FT_TRIG_MAX_ITERS );
David Turnerebe85f52001-05-11 14:25:57 +0000203
204 vec->x = x;
205 vec->y = y;
206 }
207
208
Werner Lembergf814d0f2001-06-27 16:18:10 +0000209 static void
210 ft_trig_pseudo_polarize( FT_Vector* vec )
David Turnerebe85f52001-05-11 14:25:57 +0000211 {
Werner Lembergec6ddd52001-05-12 18:04:08 +0000212 FT_Fixed theta;
213 FT_Fixed yi, i;
214 FT_Fixed x, y;
215 const FT_Fixed *arctanptr;
216
David Turnerebe85f52001-05-11 14:25:57 +0000217
218 x = vec->x;
219 y = vec->y;
220
221 /* Get the vector into the right half plane */
222 theta = 0;
Werner Lembergec6ddd52001-05-12 18:04:08 +0000223 if ( x < 0 )
David Turnerebe85f52001-05-11 14:25:57 +0000224 {
225 x = -x;
226 y = -y;
227 theta = 2 * FT_ANGLE_PI2;
228 }
229
Werner Lembergec6ddd52001-05-12 18:04:08 +0000230 if ( y > 0 )
David Turnerebe85f52001-05-11 14:25:57 +0000231 theta = - theta;
232
233 arctanptr = ft_trig_arctan_table;
Werner Lembergec6ddd52001-05-12 18:04:08 +0000234
235 if ( y < 0 )
David Turnerebe85f52001-05-11 14:25:57 +0000236 {
237 /* Rotate positive */
Werner Lembergec6ddd52001-05-12 18:04:08 +0000238 yi = y + ( x << 1 );
239 x = x - ( y << 1 );
240 y = yi;
David Turnerebe85f52001-05-11 14:25:57 +0000241 theta -= *arctanptr++; /* Subtract angle */
242 }
243 else
244 {
245 /* Rotate negative */
Werner Lembergec6ddd52001-05-12 18:04:08 +0000246 yi = y - ( x << 1 );
247 x = x + ( y << 1 );
248 y = yi;
David Turnerebe85f52001-05-11 14:25:57 +0000249 theta += *arctanptr++; /* Add angle */
250 }
251
252 i = 0;
253 do
254 {
Werner Lembergec6ddd52001-05-12 18:04:08 +0000255 if ( y < 0 )
David Turnerebe85f52001-05-11 14:25:57 +0000256 {
257 /* Rotate positive */
Werner Lembergec6ddd52001-05-12 18:04:08 +0000258 yi = y + ( x >> i );
259 x = x - ( y >> i );
260 y = yi;
David Turnerebe85f52001-05-11 14:25:57 +0000261 theta -= *arctanptr++;
262 }
263 else
264 {
265 /* Rotate negative */
Werner Lembergec6ddd52001-05-12 18:04:08 +0000266 yi = y - ( x >> i );
267 x = x + ( y >> i );
268 y = yi;
David Turnerebe85f52001-05-11 14:25:57 +0000269 theta += *arctanptr++;
270 }
Werner Lembergec6ddd52001-05-12 18:04:08 +0000271 } while ( ++i < FT_TRIG_MAX_ITERS );
David Turnerebe85f52001-05-11 14:25:57 +0000272
273 /* round theta */
274 if ( theta >= 0 )
David Turner87c0d302003-12-24 01:10:46 +0000275 theta = FT_PAD_ROUND( theta, 32 );
David Turnerebe85f52001-05-11 14:25:57 +0000276 else
David Turner87c0d302003-12-24 01:10:46 +0000277 theta = - FT_PAD_ROUND( -theta, 32 );
David Turnerebe85f52001-05-11 14:25:57 +0000278
279 vec->x = x;
280 vec->y = theta;
281 }
282
283
Werner Lembergec6ddd52001-05-12 18:04:08 +0000284 /* documentation is in fttrigon.h */
285
Werner Lembergf814d0f2001-06-27 16:18:10 +0000286 FT_EXPORT_DEF( FT_Fixed )
287 FT_Cos( FT_Angle angle )
David Turnerebe85f52001-05-11 14:25:57 +0000288 {
289 FT_Vector v;
Werner Lemberg415235d2001-06-28 17:49:10 +0000290
Werner Lembergec6ddd52001-05-12 18:04:08 +0000291
David Turnerebe85f52001-05-11 14:25:57 +0000292 v.x = FT_TRIG_COSCALE >> 2;
293 v.y = 0;
294 ft_trig_pseudo_rotate( &v, angle );
Werner Lemberg415235d2001-06-28 17:49:10 +0000295
Werner Lemberg5da9dd72001-12-16 08:17:33 +0000296 return v.x / ( 1 << 12 );
David Turnerebe85f52001-05-11 14:25:57 +0000297 }
298
299
Werner Lembergec6ddd52001-05-12 18:04:08 +0000300 /* documentation is in fttrigon.h */
301
Werner Lembergf814d0f2001-06-27 16:18:10 +0000302 FT_EXPORT_DEF( FT_Fixed )
303 FT_Sin( FT_Angle angle )
David Turnerebe85f52001-05-11 14:25:57 +0000304 {
Werner Lembergec6ddd52001-05-12 18:04:08 +0000305 return FT_Cos( FT_ANGLE_PI2 - angle );
David Turnerebe85f52001-05-11 14:25:57 +0000306 }
307
308
Werner Lembergec6ddd52001-05-12 18:04:08 +0000309 /* documentation is in fttrigon.h */
310
Werner Lembergf814d0f2001-06-27 16:18:10 +0000311 FT_EXPORT_DEF( FT_Fixed )
312 FT_Tan( FT_Angle angle )
David Turnerebe85f52001-05-11 14:25:57 +0000313 {
314 FT_Vector v;
Werner Lemberg415235d2001-06-28 17:49:10 +0000315
Werner Lembergec6ddd52001-05-12 18:04:08 +0000316
David Turnerebe85f52001-05-11 14:25:57 +0000317 v.x = FT_TRIG_COSCALE >> 2;
318 v.y = 0;
319 ft_trig_pseudo_rotate( &v, angle );
Werner Lemberg415235d2001-06-28 17:49:10 +0000320
David Turnerebe85f52001-05-11 14:25:57 +0000321 return FT_DivFix( v.y, v.x );
322 }
323
324
Werner Lembergec6ddd52001-05-12 18:04:08 +0000325 /* documentation is in fttrigon.h */
David Turnerebe85f52001-05-11 14:25:57 +0000326
Werner Lembergf814d0f2001-06-27 16:18:10 +0000327 FT_EXPORT_DEF( FT_Angle )
328 FT_Atan2( FT_Fixed dx,
329 FT_Fixed dy )
David Turnerebe85f52001-05-11 14:25:57 +0000330 {
331 FT_Vector v;
Werner Lemberg415235d2001-06-28 17:49:10 +0000332
Werner Lembergec6ddd52001-05-12 18:04:08 +0000333
David Turnerebe85f52001-05-11 14:25:57 +0000334 if ( dx == 0 && dy == 0 )
335 return 0;
336
337 v.x = dx;
Werner Lemberg415235d2001-06-28 17:49:10 +0000338 v.y = dy;
David Turnerebe85f52001-05-11 14:25:57 +0000339 ft_trig_prenorm( &v );
340 ft_trig_pseudo_polarize( &v );
Werner Lembergec6ddd52001-05-12 18:04:08 +0000341
David Turnerebe85f52001-05-11 14:25:57 +0000342 return v.y;
343 }
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( void )
349 FT_Vector_Unit( FT_Vector* vec,
350 FT_Angle angle )
David Turnerebe85f52001-05-11 14:25:57 +0000351 {
Werner Lembergec6ddd52001-05-12 18:04:08 +0000352 vec->x = FT_TRIG_COSCALE >> 2;
353 vec->y = 0;
354 ft_trig_pseudo_rotate( vec, angle );
355 vec->x >>= 12;
356 vec->y >>= 12;
David Turnerebe85f52001-05-11 14:25:57 +0000357 }
358
359
Werner Lemberg4f107452003-05-17 12:07:45 +0000360 /* these macros return 0 for positive numbers,
361 and -1 for negative ones */
362#define FT_SIGN_LONG( x ) ( (x) >> ( FT_SIZEOF_LONG * 8 - 1 ) )
363#define FT_SIGN_INT( x ) ( (x) >> ( FT_SIZEOF_INT * 8 - 1 ) )
364#define FT_SIGN_INT32( x ) ( (x) >> 31 )
365#define FT_SIGN_INT16( x ) ( (x) >> 15 )
366
367
Werner Lembergec6ddd52001-05-12 18:04:08 +0000368 /* documentation is in fttrigon.h */
369
Werner Lembergf814d0f2001-06-27 16:18:10 +0000370 FT_EXPORT_DEF( void )
371 FT_Vector_Rotate( FT_Vector* vec,
372 FT_Angle angle )
David Turnerebe85f52001-05-11 14:25:57 +0000373 {
374 FT_Int shift;
375 FT_Vector v;
Werner Lemberg415235d2001-06-28 17:49:10 +0000376
Werner Lembergec6ddd52001-05-12 18:04:08 +0000377
Werner Lemberg4f107452003-05-17 12:07:45 +0000378 v.x = vec->x;
379 v.y = vec->y;
Werner Lembergec6ddd52001-05-12 18:04:08 +0000380
David Turnerebe85f52001-05-11 14:25:57 +0000381 if ( angle && ( v.x != 0 || v.y != 0 ) )
382 {
383 shift = ft_trig_prenorm( &v );
384 ft_trig_pseudo_rotate( &v, angle );
385 v.x = ft_trig_downscale( v.x );
386 v.y = ft_trig_downscale( v.y );
Werner Lemberg415235d2001-06-28 17:49:10 +0000387
Werner Lemberg4f107452003-05-17 12:07:45 +0000388 if ( shift > 0 )
David Turnerebe85f52001-05-11 14:25:57 +0000389 {
Werner Lemberg4f107452003-05-17 12:07:45 +0000390 FT_Int32 half = 1L << ( shift - 1 );
391
392
393 vec->x = ( v.x + half + FT_SIGN_LONG( v.x ) ) >> shift;
394 vec->y = ( v.y + half + FT_SIGN_LONG( v.y ) ) >> shift;
David Turnerebe85f52001-05-11 14:25:57 +0000395 }
396 else
397 {
398 shift = -shift;
399 vec->x = v.x << shift;
400 vec->y = v.y << shift;
401 }
402 }
403 }
404
405
Werner Lembergec6ddd52001-05-12 18:04:08 +0000406 /* documentation is in fttrigon.h */
407
Werner Lembergf814d0f2001-06-27 16:18:10 +0000408 FT_EXPORT_DEF( FT_Fixed )
409 FT_Vector_Length( FT_Vector* vec )
David Turnerebe85f52001-05-11 14:25:57 +0000410 {
Werner Lembergec6ddd52001-05-12 18:04:08 +0000411 FT_Int shift;
412 FT_Vector v;
Werner Lemberg415235d2001-06-28 17:49:10 +0000413
Werner Lembergec6ddd52001-05-12 18:04:08 +0000414
David Turnerebe85f52001-05-11 14:25:57 +0000415 v = *vec;
416
Werner Lemberg415235d2001-06-28 17:49:10 +0000417 /* handle trivial cases */
David Turnerebe85f52001-05-11 14:25:57 +0000418 if ( v.x == 0 )
419 {
420 return ( v.y >= 0 ) ? v.y : -v.y;
421 }
422 else if ( v.y == 0 )
423 {
424 return ( v.x >= 0 ) ? v.x : -v.x;
425 }
426
427 /* general case */
428 shift = ft_trig_prenorm( &v );
429 ft_trig_pseudo_polarize( &v );
Werner Lemberg415235d2001-06-28 17:49:10 +0000430
David Turnerebe85f52001-05-11 14:25:57 +0000431 v.x = ft_trig_downscale( v.x );
Werner Lemberg04728a82002-04-02 14:50:31 +0000432
433 if ( shift > 0 )
434 return ( v.x + ( 1 << ( shift - 1 ) ) ) >> shift;
435
436 return v.x << -shift;
Werner Lemberg415235d2001-06-28 17:49:10 +0000437 }
David Turnerebe85f52001-05-11 14:25:57 +0000438
439
Werner Lembergec6ddd52001-05-12 18:04:08 +0000440 /* documentation is in fttrigon.h */
441
Werner Lembergf814d0f2001-06-27 16:18:10 +0000442 FT_EXPORT_DEF( void )
443 FT_Vector_Polarize( FT_Vector* vec,
444 FT_Fixed *length,
445 FT_Angle *angle )
David Turnerebe85f52001-05-11 14:25:57 +0000446 {
Werner Lembergec6ddd52001-05-12 18:04:08 +0000447 FT_Int shift;
448 FT_Vector v;
449
Werner Lemberg415235d2001-06-28 17:49:10 +0000450
David Turnerebe85f52001-05-11 14:25:57 +0000451 v = *vec;
Werner Lemberg415235d2001-06-28 17:49:10 +0000452
David Turnerebe85f52001-05-11 14:25:57 +0000453 if ( v.x == 0 && v.y == 0 )
454 return;
Werner Lemberg415235d2001-06-28 17:49:10 +0000455
David Turnerebe85f52001-05-11 14:25:57 +0000456 shift = ft_trig_prenorm( &v );
457 ft_trig_pseudo_polarize( &v );
Werner Lemberg415235d2001-06-28 17:49:10 +0000458
David Turnerebe85f52001-05-11 14:25:57 +0000459 v.x = ft_trig_downscale( v.x );
460
Werner Lembergec6ddd52001-05-12 18:04:08 +0000461 *length = ( shift >= 0 ) ? ( v.x >> shift ) : ( v.x << -shift );
David Turnerebe85f52001-05-11 14:25:57 +0000462 *angle = v.y;
Werner Lemberg415235d2001-06-28 17:49:10 +0000463 }
David Turnerebe85f52001-05-11 14:25:57 +0000464
465
David Turnerb7e18ef2002-06-26 22:05:05 +0000466 /* documentation is in fttrigon.h */
467
David Turner0d73b0c2002-06-26 23:45:21 +0000468 FT_EXPORT_DEF( void )
469 FT_Vector_From_Polar( FT_Vector* vec,
470 FT_Fixed length,
471 FT_Angle angle )
472 {
473 vec->x = length;
474 vec->y = 0;
475
476 FT_Vector_Rotate( vec, angle );
477 }
478
479
480 /* documentation is in fttrigon.h */
481
David Turnerb7e18ef2002-06-26 22:05:05 +0000482 FT_EXPORT_DEF( FT_Angle )
David Turnerac90c0e2002-07-01 21:35:17 +0000483 FT_Angle_Diff( FT_Angle angle1,
484 FT_Angle angle2 )
David Turnerb7e18ef2002-06-26 22:05:05 +0000485 {
486 FT_Angle delta = angle2 - angle1;
David Turner0d73b0c2002-06-26 23:45:21 +0000487
Werner Lemberg1ec39632004-11-24 07:08:21 +0000488
David Turnerb7e18ef2002-06-26 22:05:05 +0000489 delta %= FT_ANGLE_2PI;
David Turner20e33152003-01-07 22:54:02 +0000490 if ( delta < 0 )
491 delta += FT_ANGLE_2PI;
David Turnerb7e18ef2002-06-26 22:05:05 +0000492
493 if ( delta > FT_ANGLE_PI )
494 delta -= FT_ANGLE_2PI;
David Turner0d73b0c2002-06-26 23:45:21 +0000495
David Turnerb7e18ef2002-06-26 22:05:05 +0000496 return delta;
David Turner0d73b0c2002-06-26 23:45:21 +0000497 }
David Turnerb7e18ef2002-06-26 22:05:05 +0000498
499
Werner Lembergec6ddd52001-05-12 18:04:08 +0000500/* END */