Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

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