1ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/***************************************************************************/
2ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*                                                                         */
3ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*  fttrigon.c                                                             */
4ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*                                                                         */
5ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*    FreeType trigonometric functions (body).                             */
6ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*                                                                         */
7ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*  Copyright 2001-2005, 2012-2013 by                                      */
8ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
9ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*                                                                         */
10ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*  This file is part of the FreeType project, and may only be used,       */
11ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*  modified, and distributed under the terms of the FreeType project      */
12ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
13ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*  this file you indicate that you have read the license and              */
14ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*  understand and accept it fully.                                        */
15ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/*                                                                         */
16ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/***************************************************************************/
17ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
18ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*************************************************************************/
19ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*                                                                       */
20ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* This is a fixed-point CORDIC implementation of trigonometric          */
21ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* functions as well as transformations between Cartesian and polar      */
22ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* coordinates.  The angles are represented as 16.16 fixed-point values  */
23ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* in degrees, i.e., the angular resolution is 2^-16 degrees.  Note that */
24ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* only vectors longer than 2^16*180/pi (or at least 22 bits) on a       */
25ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* discrete Cartesian grid can have the same or better angular           */
26ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* resolution.  Therefore, to maintain this precision, some functions    */
27ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* require an interim upscaling of the vectors, whereas others operate   */
28ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* with 24-bit long vectors directly.                                    */
29ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*                                                                       */
30ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /*************************************************************************/
31ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
32ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../include/ft2build.h"
33ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../include/freetype/internal/ftobjs.h"
34ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../include/freetype/internal/ftcalc.h"
35ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#include "../../include/freetype/fttrigon.h"
36ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
37ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
38ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* the Cordic shrink factor 0.858785336480436 * 2^32 */
39ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FT_TRIG_SCALE      0xDBD95B16UL
40ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
41ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* the highest bit in overflow-safe vector components, */
42ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* MSB of 0.858785336480436 * sqrt(0.5) * 2^30         */
43ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FT_TRIG_SAFE_MSB   29
44ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
45ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* this table was generated for FT_PI = 180L << 16, i.e. degrees */
46ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FT_TRIG_MAX_ITERS  23
47ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
48ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  static const FT_Fixed
49ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  ft_trig_arctan_table[] =
50ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
51ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    1740967L, 919879L, 466945L, 234379L, 117304L, 58666L, 29335L,
52ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    14668L, 7334L, 3667L, 1833L, 917L, 458L, 229L, 115L,
53ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    57L, 29L, 14L, 7L, 4L, 2L, 1L
54ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  };
55ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
56ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
57ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#ifdef FT_LONG64
58ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
59ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* multiply a given value by the CORDIC shrink factor */
60ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  static FT_Fixed
61ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  ft_trig_downscale( FT_Fixed  val )
62ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
63ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Fixed  s;
64ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Int64  v;
65ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
66ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
67ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    s   = val;
68ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    val = FT_ABS( val );
69ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
70ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    v   = ( val * (FT_Int64)FT_TRIG_SCALE ) + 0x100000000UL;
71ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    val = (FT_Fixed)( v >> 32 );
72ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
73ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return ( s >= 0 ) ? val : -val;
74ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
75ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
76ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#else /* !FT_LONG64 */
77ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
78ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* multiply a given value by the CORDIC shrink factor */
79ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  static FT_Fixed
80ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  ft_trig_downscale( FT_Fixed  val )
81ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
82ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Fixed   s;
83ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_UInt32  v1, v2, k1, k2, hi, lo1, lo2, lo3;
84ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
85ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
86ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    s   = val;
87ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    val = FT_ABS( val );
88ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
89ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    v1 = (FT_UInt32)val >> 16;
90ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    v2 = (FT_UInt32)( val & 0xFFFFL );
91ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
92ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    k1 = (FT_UInt32)FT_TRIG_SCALE >> 16;           /* constant */
93ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    k2 = (FT_UInt32)( FT_TRIG_SCALE & 0xFFFFL );   /* constant */
94ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
95ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    hi   = k1 * v1;
96ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    lo1  = k1 * v2 + k2 * v1;       /* can't overflow */
97ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
98ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    lo2  = ( k2 * v2 ) >> 16;
99ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    lo3  = FT_MAX( lo1, lo2 );
100ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    lo1 += lo2;
101ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
102ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    hi  += lo1 >> 16;
103ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( lo1 < lo3 )
104ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      hi += (FT_UInt32)0x10000UL;
105ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
106ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    val  = (FT_Fixed)hi;
107ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
108ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return ( s >= 0 ) ? val : -val;
109ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
110ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
111ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#endif /* !FT_LONG64 */
112ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
113ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
114ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  static FT_Int
115ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  ft_trig_prenorm( FT_Vector*  vec )
116ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
117ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Pos  x, y;
118ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Int  shift;
119ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
120ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
121ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    x = vec->x;
122ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    y = vec->y;
123ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
124ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    shift = FT_MSB( FT_ABS( x ) | FT_ABS( y ) );
125ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
126ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( shift <= FT_TRIG_SAFE_MSB )
127ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
128ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      shift  = FT_TRIG_SAFE_MSB - shift;
129ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      vec->x = (FT_Pos)( (FT_ULong)x << shift );
130ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      vec->y = (FT_Pos)( (FT_ULong)y << shift );
131ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
132ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else
133ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
134ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      shift -= FT_TRIG_SAFE_MSB;
135ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      vec->x = x >> shift;
136ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      vec->y = y >> shift;
137ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      shift  = -shift;
138ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
139ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
140ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return shift;
141ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
142ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
143ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
144ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  static void
145ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  ft_trig_pseudo_rotate( FT_Vector*  vec,
146ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                         FT_Angle    theta )
147ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
148ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Int           i;
149ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Fixed         x, y, xtemp, b;
150ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    const FT_Fixed  *arctanptr;
151ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
152ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
153ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    x = vec->x;
154ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    y = vec->y;
155ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
156ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* Rotate inside [-PI/4,PI/4] sector */
157ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    while ( theta < -FT_ANGLE_PI4 )
158ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
159ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      xtemp  =  y;
160ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      y      = -x;
161ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      x      =  xtemp;
162ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      theta +=  FT_ANGLE_PI2;
163ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
164ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
165ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    while ( theta > FT_ANGLE_PI4 )
166ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
167ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      xtemp  = -y;
168ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      y      =  x;
169ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      x      =  xtemp;
170ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      theta -=  FT_ANGLE_PI2;
171ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
172ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
173ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    arctanptr = ft_trig_arctan_table;
174ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
175ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* Pseudorotations, with right shifts */
176ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for ( i = 1, b = 1; i < FT_TRIG_MAX_ITERS; b <<= 1, i++ )
177ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
178ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( theta < 0 )
179ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
180ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        xtemp  = x + ( ( y + b ) >> i );
181ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        y      = y - ( ( x + b ) >> i );
182ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        x      = xtemp;
183ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        theta += *arctanptr++;
184ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
185ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      else
186ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
187ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        xtemp  = x - ( ( y + b ) >> i );
188ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        y      = y + ( ( x + b ) >> i );
189ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        x      = xtemp;
190ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        theta -= *arctanptr++;
191ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
192ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
193ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
194ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    vec->x = x;
195ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    vec->y = y;
196ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
197ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
198ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
199ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  static void
200ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  ft_trig_pseudo_polarize( FT_Vector*  vec )
201ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
202ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Angle         theta;
203ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Int           i;
204ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Fixed         x, y, xtemp, b;
205ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    const FT_Fixed  *arctanptr;
206ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
207ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
208ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    x = vec->x;
209ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    y = vec->y;
210ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
211ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* Get the vector into [-PI/4,PI/4] sector */
212ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( y > x )
213ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
214ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( y > -x )
215ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
216ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        theta =  FT_ANGLE_PI2;
217ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        xtemp =  y;
218ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        y     = -x;
219ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        x     =  xtemp;
220ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
221ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      else
222ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
223ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        theta =  y > 0 ? FT_ANGLE_PI : -FT_ANGLE_PI;
224ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        x     = -x;
225ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        y     = -y;
226ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
227ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
228ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else
229ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
230ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( y < -x )
231ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
232ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        theta = -FT_ANGLE_PI2;
233ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        xtemp = -y;
234ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        y     =  x;
235ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        x     =  xtemp;
236ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
237ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      else
238ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
239ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        theta = 0;
240ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
241ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
242ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
243ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    arctanptr = ft_trig_arctan_table;
244ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
245ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* Pseudorotations, with right shifts */
246ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    for ( i = 1, b = 1; i < FT_TRIG_MAX_ITERS; b <<= 1, i++ )
247ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
248ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( y > 0 )
249ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
250ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        xtemp  = x + ( ( y + b ) >> i );
251ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        y      = y - ( ( x + b ) >> i );
252ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        x      = xtemp;
253ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        theta += *arctanptr++;
254ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
255ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      else
256ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
257ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        xtemp  = x - ( ( y + b ) >> i );
258ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        y      = y + ( ( x + b ) >> i );
259ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        x      = xtemp;
260ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        theta -= *arctanptr++;
261ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
262ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
263ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
264ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* round theta */
265ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( theta >= 0 )
266ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      theta = FT_PAD_ROUND( theta, 32 );
267ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else
268ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      theta = -FT_PAD_ROUND( -theta, 32 );
269ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
270ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    vec->x = x;
271ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    vec->y = theta;
272ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
273ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
274ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
275ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* documentation is in fttrigon.h */
276ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
277ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_EXPORT_DEF( FT_Fixed )
278ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_Cos( FT_Angle  angle )
279ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
280ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Vector  v;
281ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
282ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
283ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    v.x = FT_TRIG_SCALE >> 8;
284ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    v.y = 0;
285ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    ft_trig_pseudo_rotate( &v, angle );
286ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
287ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return ( v.x + 0x80L ) >> 8;
288ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
289ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
290ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
291ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* documentation is in fttrigon.h */
292ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
293ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_EXPORT_DEF( FT_Fixed )
294ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_Sin( FT_Angle  angle )
295ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
296ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return FT_Cos( FT_ANGLE_PI2 - angle );
297ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
298ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
299ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
300ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* documentation is in fttrigon.h */
301ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
302ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_EXPORT_DEF( FT_Fixed )
303ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_Tan( FT_Angle  angle )
304ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
305ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Vector  v;
306ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
307ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
308ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    v.x = FT_TRIG_SCALE >> 8;
309ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    v.y = 0;
310ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    ft_trig_pseudo_rotate( &v, angle );
311ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
312ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return FT_DivFix( v.y, v.x );
313ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
314ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
315ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
316ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* documentation is in fttrigon.h */
317ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
318ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_EXPORT_DEF( FT_Angle )
319ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_Atan2( FT_Fixed  dx,
320ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov            FT_Fixed  dy )
321ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
322ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Vector  v;
323ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
324ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
325ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( dx == 0 && dy == 0 )
326ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      return 0;
327ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
328ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    v.x = dx;
329ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    v.y = dy;
330ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    ft_trig_prenorm( &v );
331ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    ft_trig_pseudo_polarize( &v );
332ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
333ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return v.y;
334ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
335ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
336ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
337ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* documentation is in fttrigon.h */
338ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
339ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_EXPORT_DEF( void )
340ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_Vector_Unit( FT_Vector*  vec,
341ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                  FT_Angle    angle )
342ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
343ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    vec->x = FT_TRIG_SCALE >> 8;
344ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    vec->y = 0;
345ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    ft_trig_pseudo_rotate( vec, angle );
346ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    vec->x = ( vec->x + 0x80L ) >> 8;
347ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    vec->y = ( vec->y + 0x80L ) >> 8;
348ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
349ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
350ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
351ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* these macros return 0 for positive numbers,
352ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov     and -1 for negative ones */
353ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FT_SIGN_LONG( x )   ( (x) >> ( FT_SIZEOF_LONG * 8 - 1 ) )
354ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FT_SIGN_INT( x )    ( (x) >> ( FT_SIZEOF_INT * 8 - 1 ) )
355ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FT_SIGN_INT32( x )  ( (x) >> 31 )
356ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov#define FT_SIGN_INT16( x )  ( (x) >> 15 )
357ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
358ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
359ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* documentation is in fttrigon.h */
360ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
361ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_EXPORT_DEF( void )
362ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_Vector_Rotate( FT_Vector*  vec,
363ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                    FT_Angle    angle )
364ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
365ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Int     shift;
366ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Vector  v;
367ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
368ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
369ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    v.x   = vec->x;
370ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    v.y   = vec->y;
371ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
372ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( angle && ( v.x != 0 || v.y != 0 ) )
373ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
374ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      shift = ft_trig_prenorm( &v );
375ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      ft_trig_pseudo_rotate( &v, angle );
376ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      v.x = ft_trig_downscale( v.x );
377ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      v.y = ft_trig_downscale( v.y );
378ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
379ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      if ( shift > 0 )
380ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
381ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        FT_Int32  half = (FT_Int32)1L << ( shift - 1 );
382ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
383ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
384ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        vec->x = ( v.x + half + FT_SIGN_LONG( v.x ) ) >> shift;
385ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        vec->y = ( v.y + half + FT_SIGN_LONG( v.y ) ) >> shift;
386ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
387ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      else
388ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      {
389ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        shift  = -shift;
390ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        vec->x = (FT_Pos)( (FT_ULong)v.x << shift );
391ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov        vec->y = (FT_Pos)( (FT_ULong)v.y << shift );
392ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      }
393ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
394ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
395ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
396ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
397ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* documentation is in fttrigon.h */
398ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
399ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_EXPORT_DEF( FT_Fixed )
400ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_Vector_Length( FT_Vector*  vec )
401ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
402ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Int     shift;
403ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Vector  v;
404ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
405ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
406ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    v = *vec;
407ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
408ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* handle trivial cases */
409ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( v.x == 0 )
410ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
411ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      return FT_ABS( v.y );
412ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
413ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    else if ( v.y == 0 )
414ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    {
415ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      return FT_ABS( v.x );
416ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    }
417ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
418ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    /* general case */
419ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    shift = ft_trig_prenorm( &v );
420ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    ft_trig_pseudo_polarize( &v );
421ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
422ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    v.x = ft_trig_downscale( v.x );
423ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
424ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( shift > 0 )
425ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      return ( v.x + ( 1 << ( shift - 1 ) ) ) >> shift;
426ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
427ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return (FT_Fixed)( (FT_UInt32)v.x << -shift );
428ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
429ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
430ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
431ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* documentation is in fttrigon.h */
432ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
433ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_EXPORT_DEF( void )
434ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_Vector_Polarize( FT_Vector*  vec,
435ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                      FT_Fixed   *length,
436ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                      FT_Angle   *angle )
437ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
438ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Int     shift;
439ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Vector  v;
440ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
441ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
442ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    v = *vec;
443ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
444ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( v.x == 0 && v.y == 0 )
445ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      return;
446ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
447ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    shift = ft_trig_prenorm( &v );
448ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    ft_trig_pseudo_polarize( &v );
449ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
450ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    v.x = ft_trig_downscale( v.x );
451ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
452ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *length = ( shift >= 0 ) ?                      ( v.x >>  shift )
453ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                             : (FT_Fixed)( (FT_UInt32)v.x << -shift );
454ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    *angle  = v.y;
455ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
456ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
457ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
458ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* documentation is in fttrigon.h */
459ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
460ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_EXPORT_DEF( void )
461ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_Vector_From_Polar( FT_Vector*  vec,
462ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        FT_Fixed    length,
463ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                        FT_Angle    angle )
464ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
465ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    vec->x = length;
466ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    vec->y = 0;
467ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
468ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Vector_Rotate( vec, angle );
469ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
470ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
471ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
472ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  /* documentation is in fttrigon.h */
473ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
474ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_EXPORT_DEF( FT_Angle )
475ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  FT_Angle_Diff( FT_Angle  angle1,
476ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov                 FT_Angle  angle2 )
477ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  {
478ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    FT_Angle  delta = angle2 - angle1;
479ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
480ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
481ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    delta %= FT_ANGLE_2PI;
482ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( delta < 0 )
483ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      delta += FT_ANGLE_2PI;
484ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
485ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    if ( delta > FT_ANGLE_PI )
486ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov      delta -= FT_ANGLE_2PI;
487ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
488ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return delta;
489ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  }
490ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
491ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
492ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov/* END */
493