1049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/***************************************************************************/
2049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
3049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  fttrigon.c                                                             */
4049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
5049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*    FreeType trigonometric functions (body).                             */
6049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
7ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki/*  Copyright 2001-2015 by                                                 */
8049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
9049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
10049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  This file is part of the FreeType project, and may only be used,       */
11049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  modified, and distributed under the terms of the FreeType project      */
12049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
13049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  this file you indicate that you have read the license and              */
14049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*  understand and accept it fully.                                        */
15049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/*                                                                         */
16049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/***************************************************************************/
17049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
18727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  /*************************************************************************/
19727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  /*                                                                       */
20727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  /* This is a fixed-point CORDIC implementation of trigonometric          */
21727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  /* functions as well as transformations between Cartesian and polar      */
22727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  /* coordinates.  The angles are represented as 16.16 fixed-point values  */
23727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  /* in degrees, i.e., the angular resolution is 2^-16 degrees.  Note that */
24727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  /* only vectors longer than 2^16*180/pi (or at least 22 bits) on a       */
25727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  /* discrete Cartesian grid can have the same or better angular           */
26727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  /* resolution.  Therefore, to maintain this precision, some functions    */
27727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  /* require an interim upscaling of the vectors, whereas others operate   */
28727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  /* with 24-bit long vectors directly.                                    */
29727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  /*                                                                       */
30727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  /*************************************************************************/
31049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
32049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include <ft2build.h>
33049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include FT_INTERNAL_OBJECTS_H
34727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease#include FT_INTERNAL_CALC_H
35049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#include FT_TRIGONOMETRY_H
36049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
37049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
38727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  /* the Cordic shrink factor 0.858785336480436 * 2^32 */
39727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease#define FT_TRIG_SCALE      0xDBD95B16UL
40727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
41727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  /* the highest bit in overflow-safe vector components, */
42727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  /* MSB of 0.858785336480436 * sqrt(0.5) * 2^30         */
43727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease#define FT_TRIG_SAFE_MSB   29
44049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
45049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* this table was generated for FT_PI = 180L << 16, i.e. degrees */
46049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define FT_TRIG_MAX_ITERS  23
47049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
48ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki  static const FT_Angle
49727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease  ft_trig_arctan_table[] =
50049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
51727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    1740967L, 919879L, 466945L, 234379L, 117304L, 58666L, 29335L,
52727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    14668L, 7334L, 3667L, 1833L, 917L, 458L, 229L, 115L,
53049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    57L, 29L, 14L, 7L, 4L, 2L, 1L
54049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  };
55049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
56049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
57727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease#ifdef FT_LONG64
58049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
59049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* multiply a given value by the CORDIC shrink factor */
60049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Fixed
61049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  ft_trig_downscale( FT_Fixed  val )
62049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
63ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    FT_Int  s = 1;
64049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
65049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
66ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    if ( val < 0 )
67ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    {
68ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki       val = -val;
69ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki       s = -1;
70ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    }
71049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
72ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    /* 0x40000000 comes from regression analysis between true */
73ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    /* and CORDIC hypotenuse, so it minimizes the error       */
74ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    val = (FT_Fixed)( ( (FT_Int64)val * FT_TRIG_SCALE + 0x40000000UL ) >> 32 );
75049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
76ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    return s < 0 ? -val : val;
77049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
78049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
79727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease#else /* !FT_LONG64 */
80049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
81049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* multiply a given value by the CORDIC shrink factor */
82049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Fixed
83049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  ft_trig_downscale( FT_Fixed  val )
84049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
85ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    FT_Int     s = 1;
86ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    FT_UInt32  lo1, hi1, lo2, hi2, lo, hi, i1, i2;
87ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki
88ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki
89ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    if ( val < 0 )
90ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    {
91ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki       val = -val;
92ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki       s = -1;
93ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    }
94049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
95ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    lo1 = (FT_UInt32)val & 0x0000FFFFU;
96ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    hi1 = (FT_UInt32)val >> 16;
97ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    lo2 = FT_TRIG_SCALE & 0x0000FFFFU;
98ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    hi2 = FT_TRIG_SCALE >> 16;
99049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
100ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    lo = lo1 * lo2;
101ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    i1 = lo1 * hi2;
102ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    i2 = lo2 * hi1;
103ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    hi = hi1 * hi2;
104049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
105ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    /* Check carry overflow of i1 + i2 */
106ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    i1 += i2;
107ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    hi += (FT_UInt32)( i1 < i2 ) << 16;
108049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
109ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    hi += i1 >> 16;
110ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    i1  = i1 << 16;
111049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
112ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    /* Check carry overflow of i1 + lo */
113ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    lo += i1;
114ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    hi += ( lo < i1 );
115049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
116ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    /* 0x40000000 comes from regression analysis between true */
117ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    /* and CORDIC hypotenuse, so it minimizes the error       */
118049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
119ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    /* Check carry overflow of lo + 0x40000000 */
120ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    lo += 0x40000000UL;
121ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    hi += ( lo < 0x40000000UL );
122049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
123ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    val = (FT_Fixed)hi;
124049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
125ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    return s < 0 ? -val : val;
126049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
127049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
128727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease#endif /* !FT_LONG64 */
129049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
130049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
131ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki  /* undefined and never called for zero vector */
132049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static FT_Int
133049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  ft_trig_prenorm( FT_Vector*  vec )
134049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
135727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    FT_Pos  x, y;
136727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    FT_Int  shift;
137049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
138049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
139049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    x = vec->x;
140049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    y = vec->y;
141049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
142ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    shift = FT_MSB( (FT_UInt32)( FT_ABS( x ) | FT_ABS( y ) ) );
143049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
144727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    if ( shift <= FT_TRIG_SAFE_MSB )
145049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
146727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      shift  = FT_TRIG_SAFE_MSB - shift;
147727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      vec->x = (FT_Pos)( (FT_ULong)x << shift );
148727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      vec->y = (FT_Pos)( (FT_ULong)y << shift );
149049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
150049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
151049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
152727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      shift -= FT_TRIG_SAFE_MSB;
153049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      vec->x = x >> shift;
154049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      vec->y = y >> shift;
155049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      shift  = -shift;
156049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
157049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
158049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return shift;
159049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
160049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
161049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
162049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
163049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  ft_trig_pseudo_rotate( FT_Vector*  vec,
164049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                         FT_Angle    theta )
165049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
166049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int           i;
167727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    FT_Fixed         x, y, xtemp, b;
168ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    const FT_Angle  *arctanptr;
169049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
170049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
171049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    x = vec->x;
172049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    y = vec->y;
173049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
174727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    /* Rotate inside [-PI/4,PI/4] sector */
175727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    while ( theta < -FT_ANGLE_PI4 )
176049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
177727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      xtemp  =  y;
178727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      y      = -x;
179727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      x      =  xtemp;
180727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      theta +=  FT_ANGLE_PI2;
181049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
182049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
183727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    while ( theta > FT_ANGLE_PI4 )
184049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
185727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      xtemp  = -y;
186727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      y      =  x;
187727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      x      =  xtemp;
188727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      theta -=  FT_ANGLE_PI2;
189049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
190049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
191049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    arctanptr = ft_trig_arctan_table;
192049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
193727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    /* Pseudorotations, with right shifts */
194727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    for ( i = 1, b = 1; i < FT_TRIG_MAX_ITERS; b <<= 1, i++ )
195049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
196049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      if ( theta < 0 )
197049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
198727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        xtemp  = x + ( ( y + b ) >> i );
199727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        y      = y - ( ( x + b ) >> i );
200049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        x      = xtemp;
201049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        theta += *arctanptr++;
202049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
203049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
204049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
205727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        xtemp  = x - ( ( y + b ) >> i );
206727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        y      = y + ( ( x + b ) >> i );
207049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        x      = xtemp;
208049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project        theta -= *arctanptr++;
209049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
210727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    }
211049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
212049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    vec->x = x;
213049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    vec->y = y;
214049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
215049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
216049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
217049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  static void
218049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  ft_trig_pseudo_polarize( FT_Vector*  vec )
219049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
220727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    FT_Angle         theta;
221727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    FT_Int           i;
222727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    FT_Fixed         x, y, xtemp, b;
223ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    const FT_Angle  *arctanptr;
224049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
225049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
226049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    x = vec->x;
227049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    y = vec->y;
228049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
229727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    /* Get the vector into [-PI/4,PI/4] sector */
230727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    if ( y > x )
231049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
232727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      if ( y > -x )
233727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      {
234727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        theta =  FT_ANGLE_PI2;
235727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        xtemp =  y;
236727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        y     = -x;
237727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        x     =  xtemp;
238727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      }
239727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      else
240727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      {
241727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        theta =  y > 0 ? FT_ANGLE_PI : -FT_ANGLE_PI;
242727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        x     = -x;
243727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        y     = -y;
244727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      }
245049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
246049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
247049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
248727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      if ( y < -x )
249727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      {
250727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        theta = -FT_ANGLE_PI2;
251727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        xtemp = -y;
252727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        y     =  x;
253727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        x     =  xtemp;
254727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      }
255727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      else
256727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      {
257727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        theta = 0;
258727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      }
259049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
260049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
261727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    arctanptr = ft_trig_arctan_table;
262727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease
263727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    /* Pseudorotations, with right shifts */
264727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    for ( i = 1, b = 1; i < FT_TRIG_MAX_ITERS; b <<= 1, i++ )
265049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
266727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      if ( y > 0 )
267049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
268727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        xtemp  = x + ( ( y + b ) >> i );
269727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        y      = y - ( ( x + b ) >> i );
270727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        x      = xtemp;
271727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        theta += *arctanptr++;
272049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
273049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      else
274049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      {
275727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        xtemp  = x - ( ( y + b ) >> i );
276727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        y      = y + ( ( x + b ) >> i );
277727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        x      = xtemp;
278727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease        theta -= *arctanptr++;
279049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      }
280727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    }
281049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
282ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    /* round theta to acknowledge its error that mostly comes */
283ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    /* from accumulated rounding errors in the arctan table   */
284049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( theta >= 0 )
285ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki      theta = FT_PAD_ROUND( theta, 16 );
286049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else
287ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki      theta = -FT_PAD_ROUND( -theta, 16 );
288049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
289049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    vec->x = x;
290049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    vec->y = theta;
291049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
292049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
293049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
294049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* documentation is in fttrigon.h */
295049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
296049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_EXPORT_DEF( FT_Fixed )
297049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_Cos( FT_Angle  angle )
298049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
299049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector  v;
300049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
301049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
302ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    FT_Vector_Unit( &v, angle );
303049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
304ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    return v.x;
305049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
306049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
307049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
308049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* documentation is in fttrigon.h */
309049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
310049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_EXPORT_DEF( FT_Fixed )
311049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_Sin( FT_Angle  angle )
312049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
313ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    FT_Vector  v;
314ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki
315ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki
316ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    FT_Vector_Unit( &v, angle );
317ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki
318ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    return v.y;
319049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
320049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
321049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
322049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* documentation is in fttrigon.h */
323049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
324049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_EXPORT_DEF( FT_Fixed )
325049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_Tan( FT_Angle  angle )
326049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
327049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector  v;
328049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
329049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
330ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    FT_Vector_Unit( &v, angle );
331049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
332049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return FT_DivFix( v.y, v.x );
333049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
334049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
335049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
336049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* documentation is in fttrigon.h */
337049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
338049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_EXPORT_DEF( FT_Angle )
339049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_Atan2( FT_Fixed  dx,
340049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project            FT_Fixed  dy )
341049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
342049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector  v;
343049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
344049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
345049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( dx == 0 && dy == 0 )
346049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return 0;
347049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
348049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    v.x = dx;
349049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    v.y = dy;
350049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ft_trig_prenorm( &v );
351049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ft_trig_pseudo_polarize( &v );
352049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
353049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return v.y;
354049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
355049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
356049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
357049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* documentation is in fttrigon.h */
358049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
359049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_EXPORT_DEF( void )
360049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_Vector_Unit( FT_Vector*  vec,
361049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                  FT_Angle    angle )
362049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
363ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    if ( !vec )
364ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki      return;
365ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki
366727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    vec->x = FT_TRIG_SCALE >> 8;
367049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    vec->y = 0;
368049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ft_trig_pseudo_rotate( vec, angle );
369727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    vec->x = ( vec->x + 0x80L ) >> 8;
370727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    vec->y = ( vec->y + 0x80L ) >> 8;
371049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
372049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
373049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
374049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* these macros return 0 for positive numbers,
375049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project     and -1 for negative ones */
376049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define FT_SIGN_LONG( x )   ( (x) >> ( FT_SIZEOF_LONG * 8 - 1 ) )
377049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define FT_SIGN_INT( x )    ( (x) >> ( FT_SIZEOF_INT * 8 - 1 ) )
378049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define FT_SIGN_INT32( x )  ( (x) >> 31 )
379049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project#define FT_SIGN_INT16( x )  ( (x) >> 15 )
380049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
381049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
382049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* documentation is in fttrigon.h */
383049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
384049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_EXPORT_DEF( void )
385049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_Vector_Rotate( FT_Vector*  vec,
386049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                    FT_Angle    angle )
387049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
388049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int     shift;
389049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector  v;
390049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
391049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
392ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    if ( !vec || !angle )
393ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki      return;
394049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
395ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    v = *vec;
396049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
397ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    if ( v.x == 0 && v.y == 0 )
398ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki      return;
399049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
400ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    shift = ft_trig_prenorm( &v );
401ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    ft_trig_pseudo_rotate( &v, angle );
402ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    v.x = ft_trig_downscale( v.x );
403ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    v.y = ft_trig_downscale( v.y );
404049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
405ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    if ( shift > 0 )
406ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    {
407ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki      FT_Int32  half = (FT_Int32)1L << ( shift - 1 );
408ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki
409ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki
410ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki      vec->x = ( v.x + half + FT_SIGN_LONG( v.x ) ) >> shift;
411ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki      vec->y = ( v.y + half + FT_SIGN_LONG( v.y ) ) >> shift;
412ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    }
413ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    else
414ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    {
415ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki      shift  = -shift;
416ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki      vec->x = (FT_Pos)( (FT_ULong)v.x << shift );
417ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki      vec->y = (FT_Pos)( (FT_ULong)v.y << shift );
418049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
419049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
420049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
421049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
422049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* documentation is in fttrigon.h */
423049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
424049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_EXPORT_DEF( FT_Fixed )
425049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_Vector_Length( FT_Vector*  vec )
426049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
427049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int     shift;
428049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector  v;
429049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
430049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
431ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    if ( !vec )
432ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki      return 0;
433ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki
434049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    v = *vec;
435049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
436049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* handle trivial cases */
437049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( v.x == 0 )
438049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
439727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      return FT_ABS( v.y );
440049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
441049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    else if ( v.y == 0 )
442049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    {
443727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease      return FT_ABS( v.x );
444049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    }
445049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
446049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    /* general case */
447049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    shift = ft_trig_prenorm( &v );
448049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ft_trig_pseudo_polarize( &v );
449049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
450049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    v.x = ft_trig_downscale( v.x );
451049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
452049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( shift > 0 )
453ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki      return ( v.x + ( 1L << ( shift - 1 ) ) ) >> shift;
454049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
455727dee178a392d20eb050d0c446f2fcc29058fa1Victoria Lease    return (FT_Fixed)( (FT_UInt32)v.x << -shift );
456049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
457049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
458049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
459049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* documentation is in fttrigon.h */
460049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
461049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_EXPORT_DEF( void )
462049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_Vector_Polarize( FT_Vector*  vec,
463049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      FT_Fixed   *length,
464049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                      FT_Angle   *angle )
465049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
466049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Int     shift;
467049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector  v;
468049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
469049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
470ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    if ( !vec || !length || !angle )
471ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki      return;
472ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki
473049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    v = *vec;
474049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
475049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    if ( v.x == 0 && v.y == 0 )
476049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      return;
477049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
478049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    shift = ft_trig_prenorm( &v );
479049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    ft_trig_pseudo_polarize( &v );
480049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
481049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    v.x = ft_trig_downscale( v.x );
482049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
483ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    *length = shift >= 0 ?                      ( v.x >>  shift )
484ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki                         : (FT_Fixed)( (FT_UInt32)v.x << -shift );
485049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    *angle  = v.y;
486049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
487049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
488049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
489049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* documentation is in fttrigon.h */
490049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
491049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_EXPORT_DEF( void )
492049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_Vector_From_Polar( FT_Vector*  vec,
493049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                        FT_Fixed    length,
494049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                        FT_Angle    angle )
495049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
496ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    if ( !vec )
497ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki      return;
498ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki
499049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    vec->x = length;
500049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    vec->y = 0;
501049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
502049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Vector_Rotate( vec, angle );
503049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
504049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
505049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
506049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  /* documentation is in fttrigon.h */
507049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
508049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_EXPORT_DEF( FT_Angle )
509049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  FT_Angle_Diff( FT_Angle  angle1,
510049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project                 FT_Angle  angle2 )
511049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  {
512049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    FT_Angle  delta = angle2 - angle1;
513049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
514049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
515ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    while ( delta <= -FT_ANGLE_PI )
516049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      delta += FT_ANGLE_2PI;
517049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
518ec62c527eb34ee4481a0153ceb42dfd35d7e1d26Makoto Onuki    while ( delta > FT_ANGLE_PI )
519049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project      delta -= FT_ANGLE_2PI;
520049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
521049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project    return delta;
522049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project  }
523049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
524049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project
525049d6fea481044fcc000e7782e5bc7046fc70844The Android Open Source Project/* END */
526