PageRenderTime 38ms CodeModel.GetById 13ms app.highlight 21ms RepoModel.GetById 1ms app.codeStats 0ms

/modules/freetype2/src/base/fttrigon.c

http://github.com/zpao/v8monkey
C | 546 lines | 373 code | 127 blank | 46 comment | 45 complexity | 3609d7603f55593b9303d7a2d528dac0 MD5 | raw file
  1/***************************************************************************/
  2/*                                                                         */
  3/*  fttrigon.c                                                             */
  4/*                                                                         */
  5/*    FreeType trigonometric functions (body).                             */
  6/*                                                                         */
  7/*  Copyright 2001, 2002, 2003, 2004, 2005 by                              */
  8/*  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
 19#include <ft2build.h>
 20#include FT_INTERNAL_OBJECTS_H
 21#include FT_TRIGONOMETRY_H
 22
 23
 24  /* the following is 0.2715717684432231 * 2^30 */
 25#define FT_TRIG_COSCALE  0x11616E8EUL
 26
 27  /* this table was generated for FT_PI = 180L << 16, i.e. degrees */
 28#define FT_TRIG_MAX_ITERS  23
 29
 30  static const FT_Fixed
 31  ft_trig_arctan_table[24] =
 32  {
 33    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
 36  };
 37
 38  /* the Cordic shrink factor, multiplied by 2^32 */
 39#define FT_TRIG_SCALE    1166391785UL  /* 0x4585BA38UL */
 40
 41
 42#ifdef FT_CONFIG_HAS_INT64
 43
 44  /* multiply a given value by the CORDIC shrink factor */
 45  static FT_Fixed
 46  ft_trig_downscale( FT_Fixed  val )
 47  {
 48    FT_Fixed  s;
 49    FT_Int64  v;
 50
 51
 52    s   = val;
 53    val = ( val >= 0 ) ? val : -val;
 54
 55    v   = ( val * (FT_Int64)FT_TRIG_SCALE ) + 0x100000000UL;
 56    val = (FT_Fixed)( v >> 32 );
 57
 58    return ( s >= 0 ) ? val : -val;
 59  }
 60
 61#else /* !FT_CONFIG_HAS_INT64 */
 62
 63  /* multiply a given value by the CORDIC shrink factor */
 64  static FT_Fixed
 65  ft_trig_downscale( FT_Fixed  val )
 66  {
 67    FT_Fixed   s;
 68    FT_UInt32  v1, v2, k1, k2, hi, lo1, lo2, lo3;
 69
 70
 71    s   = val;
 72    val = ( val >= 0 ) ? val : -val;
 73
 74    v1 = (FT_UInt32)val >> 16;
 75    v2 = (FT_UInt32)(val & 0xFFFFL);
 76
 77    k1 = (FT_UInt32)FT_TRIG_SCALE >> 16;       /* constant */
 78    k2 = (FT_UInt32)(FT_TRIG_SCALE & 0xFFFFL);   /* constant */
 79
 80    hi   = k1 * v1;
 81    lo1  = k1 * v2 + k2 * v1;       /* can't overflow */
 82
 83    lo2  = ( k2 * v2 ) >> 16;
 84    lo3  = ( lo1 >= lo2 ) ? lo1 : lo2;
 85    lo1 += lo2;
 86
 87    hi  += lo1 >> 16;
 88    if ( lo1 < lo3 )
 89      hi += (FT_UInt32)0x10000UL;
 90
 91    val  = (FT_Fixed)hi;
 92
 93    return ( s >= 0 ) ? val : -val;
 94  }
 95
 96#endif /* !FT_CONFIG_HAS_INT64 */
 97
 98
 99  static FT_Int
100  ft_trig_prenorm( FT_Vector*  vec )
101  {
102    FT_Fixed  x, y, z;
103    FT_Int    shift;
104
105
106    x = vec->x;
107    y = vec->y;
108
109    z     = ( ( x >= 0 ) ? x : - x ) | ( (y >= 0) ? y : -y );
110    shift = 0;
111
112#if 1
113    /* determine msb bit index in `shift' */
114    if ( z >= ( 1L << 16 ) )
115    {
116      z     >>= 16;
117      shift  += 16;
118    }
119    if ( z >= ( 1L << 8 ) )
120    {
121      z     >>= 8;
122      shift  += 8;
123    }
124    if ( z >= ( 1L << 4 ) )
125    {
126      z     >>= 4;
127      shift  += 4;
128    }
129    if ( z >= ( 1L << 2 ) )
130    {
131      z     >>= 2;
132      shift  += 2;
133    }
134    if ( z >= ( 1L << 1 ) )
135    {
136      z    >>= 1;
137      shift += 1;
138    }
139
140    if ( shift <= 27 )
141    {
142      shift  = 27 - shift;
143      vec->x = x << shift;
144      vec->y = y << shift;
145    }
146    else
147    {
148      shift -= 27;
149      vec->x = x >> shift;
150      vec->y = y >> shift;
151      shift  = -shift;
152    }
153
154#else /* 0 */
155
156    if ( z < ( 1L << 27 ) )
157    {
158      do
159      {
160        shift++;
161        z <<= 1;
162      } while ( z < ( 1L << 27 ) );
163      vec->x = x << shift;
164      vec->y = y << shift;
165    }
166    else if ( z > ( 1L << 28 ) )
167    {
168      do
169      {
170        shift++;
171        z >>= 1;
172      } while ( z > ( 1L << 28 ) );
173
174      vec->x = x >> shift;
175      vec->y = y >> shift;
176      shift  = -shift;
177    }
178
179#endif /* 0 */
180
181    return shift;
182  }
183
184
185  static void
186  ft_trig_pseudo_rotate( FT_Vector*  vec,
187                         FT_Angle    theta )
188  {
189    FT_Int           i;
190    FT_Fixed         x, y, xtemp;
191    const FT_Fixed  *arctanptr;
192
193
194    x = vec->x;
195    y = vec->y;
196
197    /* Get angle between -90 and 90 degrees */
198    while ( theta <= -FT_ANGLE_PI2 )
199    {
200      x = -x;
201      y = -y;
202      theta += FT_ANGLE_PI;
203    }
204
205    while ( theta > FT_ANGLE_PI2 )
206    {
207      x = -x;
208      y = -y;
209      theta -= FT_ANGLE_PI;
210    }
211
212    /* Initial pseudorotation, with left shift */
213    arctanptr = ft_trig_arctan_table;
214
215    if ( theta < 0 )
216    {
217      xtemp  = x + ( y << 1 );
218      y      = y - ( x << 1 );
219      x      = xtemp;
220      theta += *arctanptr++;
221    }
222    else
223    {
224      xtemp  = x - ( y << 1 );
225      y      = y + ( x << 1 );
226      x      = xtemp;
227      theta -= *arctanptr++;
228    }
229
230    /* Subsequent pseudorotations, with right shifts */
231    i = 0;
232    do
233    {
234      if ( theta < 0 )
235      {
236        xtemp  = x + ( y >> i );
237        y      = y - ( x >> i );
238        x      = xtemp;
239        theta += *arctanptr++;
240      }
241      else
242      {
243        xtemp  = x - ( y >> i );
244        y      = y + ( x >> i );
245        x      = xtemp;
246        theta -= *arctanptr++;
247      }
248    } while ( ++i < FT_TRIG_MAX_ITERS );
249
250    vec->x = x;
251    vec->y = y;
252  }
253
254
255  static void
256  ft_trig_pseudo_polarize( FT_Vector*  vec )
257  {
258    FT_Fixed         theta;
259    FT_Fixed         yi, i;
260    FT_Fixed         x, y;
261    const FT_Fixed  *arctanptr;
262
263
264    x = vec->x;
265    y = vec->y;
266
267    /* Get the vector into the right half plane */
268    theta = 0;
269    if ( x < 0 )
270    {
271      x = -x;
272      y = -y;
273      theta = 2 * FT_ANGLE_PI2;
274    }
275
276    if ( y > 0 )
277      theta = - theta;
278
279    arctanptr = ft_trig_arctan_table;
280
281    if ( y < 0 )
282    {
283      /* Rotate positive */
284      yi     = y + ( x << 1 );
285      x      = x - ( y << 1 );
286      y      = yi;
287      theta -= *arctanptr++;  /* Subtract angle */
288    }
289    else
290    {
291      /* Rotate negative */
292      yi     = y - ( x << 1 );
293      x      = x + ( y << 1 );
294      y      = yi;
295      theta += *arctanptr++;  /* Add angle */
296    }
297
298    i = 0;
299    do
300    {
301      if ( y < 0 )
302      {
303        /* Rotate positive */
304        yi     = y + ( x >> i );
305        x      = x - ( y >> i );
306        y      = yi;
307        theta -= *arctanptr++;
308      }
309      else
310      {
311        /* Rotate negative */
312        yi     = y - ( x >> i );
313        x      = x + ( y >> i );
314        y      = yi;
315        theta += *arctanptr++;
316      }
317    } while ( ++i < FT_TRIG_MAX_ITERS );
318
319    /* round theta */
320    if ( theta >= 0 )
321      theta = FT_PAD_ROUND( theta, 32 );
322    else
323      theta = -FT_PAD_ROUND( -theta, 32 );
324
325    vec->x = x;
326    vec->y = theta;
327  }
328
329
330  /* documentation is in fttrigon.h */
331
332  FT_EXPORT_DEF( FT_Fixed )
333  FT_Cos( FT_Angle  angle )
334  {
335    FT_Vector  v;
336
337
338    v.x = FT_TRIG_COSCALE >> 2;
339    v.y = 0;
340    ft_trig_pseudo_rotate( &v, angle );
341
342    return v.x / ( 1 << 12 );
343  }
344
345
346  /* documentation is in fttrigon.h */
347
348  FT_EXPORT_DEF( FT_Fixed )
349  FT_Sin( FT_Angle  angle )
350  {
351    return FT_Cos( FT_ANGLE_PI2 - angle );
352  }
353
354
355  /* documentation is in fttrigon.h */
356
357  FT_EXPORT_DEF( FT_Fixed )
358  FT_Tan( FT_Angle  angle )
359  {
360    FT_Vector  v;
361
362
363    v.x = FT_TRIG_COSCALE >> 2;
364    v.y = 0;
365    ft_trig_pseudo_rotate( &v, angle );
366
367    return FT_DivFix( v.y, v.x );
368  }
369
370
371  /* documentation is in fttrigon.h */
372
373  FT_EXPORT_DEF( FT_Angle )
374  FT_Atan2( FT_Fixed  dx,
375            FT_Fixed  dy )
376  {
377    FT_Vector  v;
378
379
380    if ( dx == 0 && dy == 0 )
381      return 0;
382
383    v.x = dx;
384    v.y = dy;
385    ft_trig_prenorm( &v );
386    ft_trig_pseudo_polarize( &v );
387
388    return v.y;
389  }
390
391
392  /* documentation is in fttrigon.h */
393
394  FT_EXPORT_DEF( void )
395  FT_Vector_Unit( FT_Vector*  vec,
396                  FT_Angle    angle )
397  {
398    vec->x = FT_TRIG_COSCALE >> 2;
399    vec->y = 0;
400    ft_trig_pseudo_rotate( vec, angle );
401    vec->x >>= 12;
402    vec->y >>= 12;
403  }
404
405
406  /* these macros return 0 for positive numbers,
407     and -1 for negative ones */
408#define FT_SIGN_LONG( x )   ( (x) >> ( FT_SIZEOF_LONG * 8 - 1 ) )
409#define FT_SIGN_INT( x )    ( (x) >> ( FT_SIZEOF_INT * 8 - 1 ) )
410#define FT_SIGN_INT32( x )  ( (x) >> 31 )
411#define FT_SIGN_INT16( x )  ( (x) >> 15 )
412
413
414  /* documentation is in fttrigon.h */
415
416  FT_EXPORT_DEF( void )
417  FT_Vector_Rotate( FT_Vector*  vec,
418                    FT_Angle    angle )
419  {
420    FT_Int     shift;
421    FT_Vector  v;
422
423
424    v.x   = vec->x;
425    v.y   = vec->y;
426
427    if ( angle && ( v.x != 0 || v.y != 0 ) )
428    {
429      shift = ft_trig_prenorm( &v );
430      ft_trig_pseudo_rotate( &v, angle );
431      v.x = ft_trig_downscale( v.x );
432      v.y = ft_trig_downscale( v.y );
433
434      if ( shift > 0 )
435      {
436        FT_Int32  half = (FT_Int32)1L << ( shift - 1 );
437
438
439        vec->x = ( v.x + half + FT_SIGN_LONG( v.x ) ) >> shift;
440        vec->y = ( v.y + half + FT_SIGN_LONG( v.y ) ) >> shift;
441      }
442      else
443      {
444        shift  = -shift;
445        vec->x = v.x << shift;
446        vec->y = v.y << shift;
447      }
448    }
449  }
450
451
452  /* documentation is in fttrigon.h */
453
454  FT_EXPORT_DEF( FT_Fixed )
455  FT_Vector_Length( FT_Vector*  vec )
456  {
457    FT_Int     shift;
458    FT_Vector  v;
459
460
461    v = *vec;
462
463    /* handle trivial cases */
464    if ( v.x == 0 )
465    {
466      return ( v.y >= 0 ) ? v.y : -v.y;
467    }
468    else if ( v.y == 0 )
469    {
470      return ( v.x >= 0 ) ? v.x : -v.x;
471    }
472
473    /* general case */
474    shift = ft_trig_prenorm( &v );
475    ft_trig_pseudo_polarize( &v );
476
477    v.x = ft_trig_downscale( v.x );
478
479    if ( shift > 0 )
480      return ( v.x + ( 1 << ( shift - 1 ) ) ) >> shift;
481
482    return v.x << -shift;
483  }
484
485
486  /* documentation is in fttrigon.h */
487
488  FT_EXPORT_DEF( void )
489  FT_Vector_Polarize( FT_Vector*  vec,
490                      FT_Fixed   *length,
491                      FT_Angle   *angle )
492  {
493    FT_Int     shift;
494    FT_Vector  v;
495
496
497    v = *vec;
498
499    if ( v.x == 0 && v.y == 0 )
500      return;
501
502    shift = ft_trig_prenorm( &v );
503    ft_trig_pseudo_polarize( &v );
504
505    v.x = ft_trig_downscale( v.x );
506
507    *length = ( shift >= 0 ) ? ( v.x >> shift ) : ( v.x << -shift );
508    *angle  = v.y;
509  }
510
511
512  /* documentation is in fttrigon.h */
513
514  FT_EXPORT_DEF( void )
515  FT_Vector_From_Polar( FT_Vector*  vec,
516                        FT_Fixed    length,
517                        FT_Angle    angle )
518  {
519    vec->x = length;
520    vec->y = 0;
521
522    FT_Vector_Rotate( vec, angle );
523  }
524
525
526  /* documentation is in fttrigon.h */
527
528  FT_EXPORT_DEF( FT_Angle )
529  FT_Angle_Diff( FT_Angle  angle1,
530                 FT_Angle  angle2 )
531  {
532    FT_Angle  delta = angle2 - angle1;
533
534
535    delta %= FT_ANGLE_2PI;
536    if ( delta < 0 )
537      delta += FT_ANGLE_2PI;
538
539    if ( delta > FT_ANGLE_PI )
540      delta -= FT_ANGLE_2PI;
541
542    return delta;
543  }
544
545
546/* END */