fttrigon.c
上传用户:yisoukefu
上传日期:2020-08-09
资源大小:39506k
文件大小:11k
源码类别:

其他游戏

开发平台:

Visual C++

  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. #include <ft2build.h>
  18. #include FT_INTERNAL_OBJECTS_H
  19. #include FT_TRIGONOMETRY_H
  20.   /* the following is 0.2715717684432231 * 2^30 */
  21. #define FT_TRIG_COSCALE  0x11616E8EUL
  22.   /* this table was generated for FT_PI = 180L << 16, i.e. degrees */
  23. #define FT_TRIG_MAX_ITERS  23
  24.   static const FT_Fixed
  25.   ft_trig_arctan_table[24] =
  26.   {
  27.     4157273L, 2949120L, 1740967L, 919879L, 466945L, 234379L, 117304L,
  28.     58666L, 29335L, 14668L, 7334L, 3667L, 1833L, 917L, 458L, 229L, 115L,
  29.     57L, 29L, 14L, 7L, 4L, 2L, 1L
  30.   };
  31.   /* the Cordic shrink factor, multiplied by 2^32 */
  32. #define FT_TRIG_SCALE    1166391785UL  /* 0x4585BA38UL */
  33. #ifdef FT_CONFIG_HAS_INT64
  34.   /* multiply a given value by the CORDIC shrink factor */
  35.   static FT_Fixed
  36.   ft_trig_downscale( FT_Fixed  val )
  37.   {
  38.     FT_Fixed  s;
  39.     FT_Int64  v;
  40.     s   = val;
  41.     val = ( val >= 0 ) ? val : -val;
  42.     v   = ( val * (FT_Int64)FT_TRIG_SCALE ) + 0x100000000UL;
  43.     val = (FT_Fixed)( v >> 32 );
  44.     return ( s >= 0 ) ? val : -val;
  45.   }
  46. #else /* !FT_CONFIG_HAS_INT64 */
  47.   /* multiply a given value by the CORDIC shrink factor */
  48.   static FT_Fixed
  49.   ft_trig_downscale( FT_Fixed  val )
  50.   {
  51.     FT_Fixed   s;
  52.     FT_UInt32  v1, v2, k1, k2, hi, lo1, lo2, lo3;
  53.     s   = val;
  54.     val = ( val >= 0 ) ? val : -val;
  55.     v1 = (FT_UInt32)val >> 16;
  56.     v2 = (FT_UInt32)val & 0xFFFFL;
  57.     k1 = FT_TRIG_SCALE >> 16;       /* constant */
  58.     k2 = FT_TRIG_SCALE & 0xFFFFL;   /* constant */
  59.     hi   = k1 * v1;
  60.     lo1  = k1 * v2 + k2 * v1;       /* can't overflow */
  61.     lo2  = ( k2 * v2 ) >> 16;
  62.     lo3  = ( lo1 >= lo2 ) ? lo1 : lo2;
  63.     lo1 += lo2;
  64.     hi  += lo1 >> 16;
  65.     if ( lo1 < lo3 )
  66.       hi += 0x10000UL;
  67.     val  = (FT_Fixed)hi;
  68.     return ( s >= 0 ) ? val : -val;
  69.   }
  70. #endif /* !FT_CONFIG_HAS_INT64 */
  71.   static FT_Int
  72.   ft_trig_prenorm( FT_Vector*  vec )
  73.   {
  74.     FT_Fixed  x, y, z;
  75.     FT_Int    shift;
  76.     x = vec->x;
  77.     y = vec->y;
  78.     z     = ( ( x >= 0 ) ? x : - x ) | ( (y >= 0) ? y : -y );
  79.     shift = 0;
  80. #if 1
  81.     /* determine msb bit index in `shift' */
  82.     if ( z >= ( 1L << 16 ) )
  83.     {
  84.       z     >>= 16;
  85.       shift  += 16;
  86.     }
  87.     if ( z >= ( 1L << 8 ) )
  88.     {
  89.       z     >>= 8;
  90.       shift  += 8;
  91.     }
  92.     if ( z >= ( 1L << 4 ) )
  93.     {
  94.       z     >>= 4;
  95.       shift  += 4;
  96.     }
  97.     if ( z >= ( 1L << 2 ) )
  98.     {
  99.       z     >>= 2;
  100.       shift  += 2;
  101.     }
  102.     if ( z >= ( 1L << 1 ) )
  103.     {
  104.       z    >>= 1;
  105.       shift += 1;
  106.     }
  107.     if ( shift <= 27 )
  108.     {
  109.       shift  = 27 - shift;
  110.       vec->x = x << shift;
  111.       vec->y = y << shift;
  112.     }
  113.     else
  114.     {
  115.       shift -= 27;
  116.       vec->x = x >> shift;
  117.       vec->y = y >> shift;
  118.       shift  = -shift;
  119.     }
  120. #else /* 0 */
  121.     if ( z < ( 1L << 27 ) )
  122.     {
  123.       do
  124.       {
  125.         shift++;
  126.         z <<= 1;
  127.       } while ( z < ( 1L << 27 ) );
  128.       vec->x = x << shift;
  129.       vec->y = y << shift;
  130.     }
  131.     else if ( z > ( 1L << 28 ) )
  132.     {
  133.       do
  134.       {
  135.         shift++;
  136.         z >>= 1;
  137.       } while ( z > ( 1L << 28 ) );
  138.       vec->x = x >> shift;
  139.       vec->y = y >> shift;
  140.       shift  = -shift;
  141.     }
  142. #endif /* 0 */
  143.     return shift;
  144.   }
  145.   static void
  146.   ft_trig_pseudo_rotate( FT_Vector*  vec,
  147.                          FT_Angle    theta )
  148.   {
  149.     FT_Int           i;
  150.     FT_Fixed         x, y, xtemp;
  151.     const FT_Fixed  *arctanptr;
  152.     x = vec->x;
  153.     y = vec->y;
  154.     /* Get angle between -90 and 90 degrees */
  155.     while ( theta <= -FT_ANGLE_PI2 )
  156.     {
  157.       x = -x;
  158.       y = -y;
  159.       theta += FT_ANGLE_PI;
  160.     }
  161.     while ( theta > FT_ANGLE_PI2 )
  162.     {
  163.       x = -x;
  164.       y = -y;
  165.       theta -= FT_ANGLE_PI;
  166.     }
  167.     /* Initial pseudorotation, with left shift */
  168.     arctanptr = ft_trig_arctan_table;
  169.     if ( theta < 0 )
  170.     {
  171.       xtemp  = x + ( y << 1 );
  172.       y      = y - ( x << 1 );
  173.       x      = xtemp;
  174.       theta += *arctanptr++;
  175.     }
  176.     else
  177.     {
  178.       xtemp  = x - ( y << 1 );
  179.       y      = y + ( x << 1 );
  180.       x      = xtemp;
  181.       theta -= *arctanptr++;
  182.     }
  183.     /* Subsequent pseudorotations, with right shifts */
  184.     i = 0;
  185.     do
  186.     {
  187.       if ( theta < 0 )
  188.       {
  189.         xtemp  = x + ( y >> i );
  190.         y      = y - ( x >> i );
  191.         x      = xtemp;
  192.         theta += *arctanptr++;
  193.       }
  194.       else
  195.       {
  196.         xtemp  = x - ( y >> i );
  197.         y      = y + ( x >> i );
  198.         x      = xtemp;
  199.         theta -= *arctanptr++;
  200.       }
  201.     } while ( ++i < FT_TRIG_MAX_ITERS );
  202.     vec->x = x;
  203.     vec->y = y;
  204.   }
  205.   static void
  206.   ft_trig_pseudo_polarize( FT_Vector*  vec )
  207.   {
  208.     FT_Fixed         theta;
  209.     FT_Fixed         yi, i;
  210.     FT_Fixed         x, y;
  211.     const FT_Fixed  *arctanptr;
  212.     x = vec->x;
  213.     y = vec->y;
  214.     /* Get the vector into the right half plane */
  215.     theta = 0;
  216.     if ( x < 0 )
  217.     {
  218.       x = -x;
  219.       y = -y;
  220.       theta = 2 * FT_ANGLE_PI2;
  221.     }
  222.     if ( y > 0 )
  223.       theta = - theta;
  224.     arctanptr = ft_trig_arctan_table;
  225.     if ( y < 0 )
  226.     {
  227.       /* Rotate positive */
  228.       yi     = y + ( x << 1 );
  229.       x      = x - ( y << 1 );
  230.       y      = yi;
  231.       theta -= *arctanptr++;  /* Subtract angle */
  232.     }
  233.     else
  234.     {
  235.       /* Rotate negative */
  236.       yi     = y - ( x << 1 );
  237.       x      = x + ( y << 1 );
  238.       y      = yi;
  239.       theta += *arctanptr++;  /* Add angle */
  240.     }
  241.     i = 0;
  242.     do
  243.     {
  244.       if ( y < 0 )
  245.       {
  246.         /* Rotate positive */
  247.         yi     = y + ( x >> i );
  248.         x      = x - ( y >> i );
  249.         y      = yi;
  250.         theta -= *arctanptr++;
  251.       }
  252.       else
  253.       {
  254.         /* Rotate negative */
  255.         yi     = y - ( x >> i );
  256.         x      = x + ( y >> i );
  257.         y      = yi;
  258.         theta += *arctanptr++;
  259.       }
  260.     } while ( ++i < FT_TRIG_MAX_ITERS );
  261.     /* round theta */
  262.     if ( theta >= 0 )
  263.       theta = FT_PAD_ROUND( theta, 32 );
  264.     else
  265.       theta = -FT_PAD_ROUND( -theta, 32 );
  266.     vec->x = x;
  267.     vec->y = theta;
  268.   }
  269.   /* documentation is in fttrigon.h */
  270.   FT_EXPORT_DEF( FT_Fixed )
  271.   FT_Cos( FT_Angle  angle )
  272.   {
  273.     FT_Vector  v;
  274.     v.x = FT_TRIG_COSCALE >> 2;
  275.     v.y = 0;
  276.     ft_trig_pseudo_rotate( &v, angle );
  277.     return v.x / ( 1 << 12 );
  278.   }
  279.   /* documentation is in fttrigon.h */
  280.   FT_EXPORT_DEF( FT_Fixed )
  281.   FT_Sin( FT_Angle  angle )
  282.   {
  283.     return FT_Cos( FT_ANGLE_PI2 - angle );
  284.   }
  285.   /* documentation is in fttrigon.h */
  286.   FT_EXPORT_DEF( FT_Fixed )
  287.   FT_Tan( FT_Angle  angle )
  288.   {
  289.     FT_Vector  v;
  290.     v.x = FT_TRIG_COSCALE >> 2;
  291.     v.y = 0;
  292.     ft_trig_pseudo_rotate( &v, angle );
  293.     return FT_DivFix( v.y, v.x );
  294.   }
  295.   /* documentation is in fttrigon.h */
  296.   FT_EXPORT_DEF( FT_Angle )
  297.   FT_Atan2( FT_Fixed  dx,
  298.             FT_Fixed  dy )
  299.   {
  300.     FT_Vector  v;
  301.     if ( dx == 0 && dy == 0 )
  302.       return 0;
  303.     v.x = dx;
  304.     v.y = dy;
  305.     ft_trig_prenorm( &v );
  306.     ft_trig_pseudo_polarize( &v );
  307.     return v.y;
  308.   }
  309.   /* documentation is in fttrigon.h */
  310.   FT_EXPORT_DEF( void )
  311.   FT_Vector_Unit( FT_Vector*  vec,
  312.                   FT_Angle    angle )
  313.   {
  314.     vec->x = FT_TRIG_COSCALE >> 2;
  315.     vec->y = 0;
  316.     ft_trig_pseudo_rotate( vec, angle );
  317.     vec->x >>= 12;
  318.     vec->y >>= 12;
  319.   }
  320.   /* these macros return 0 for positive numbers,
  321.      and -1 for negative ones */
  322. #define FT_SIGN_LONG( x )   ( (x) >> ( FT_SIZEOF_LONG * 8 - 1 ) )
  323. #define FT_SIGN_INT( x )    ( (x) >> ( FT_SIZEOF_INT * 8 - 1 ) )
  324. #define FT_SIGN_INT32( x )  ( (x) >> 31 )
  325. #define FT_SIGN_INT16( x )  ( (x) >> 15 )
  326.   /* documentation is in fttrigon.h */
  327.   FT_EXPORT_DEF( void )
  328.   FT_Vector_Rotate( FT_Vector*  vec,
  329.                     FT_Angle    angle )
  330.   {
  331.     FT_Int     shift;
  332.     FT_Vector  v;
  333.     v.x   = vec->x;
  334.     v.y   = vec->y;
  335.     if ( angle && ( v.x != 0 || v.y != 0 ) )
  336.     {
  337.       shift = ft_trig_prenorm( &v );
  338.       ft_trig_pseudo_rotate( &v, angle );
  339.       v.x = ft_trig_downscale( v.x );
  340.       v.y = ft_trig_downscale( v.y );
  341.       if ( shift > 0 )
  342.       {
  343.         FT_Int32  half = 1L << ( shift - 1 );
  344.         vec->x = ( v.x + half + FT_SIGN_LONG( v.x ) ) >> shift;
  345.         vec->y = ( v.y + half + FT_SIGN_LONG( v.y ) ) >> shift;
  346.       }
  347.       else
  348.       {
  349.         shift  = -shift;
  350.         vec->x = v.x << shift;
  351.         vec->y = v.y << shift;
  352.       }
  353.     }
  354.   }
  355.   /* documentation is in fttrigon.h */
  356.   FT_EXPORT_DEF( FT_Fixed )
  357.   FT_Vector_Length( FT_Vector*  vec )
  358.   {
  359.     FT_Int     shift;
  360.     FT_Vector  v;
  361.     v = *vec;
  362.     /* handle trivial cases */
  363.     if ( v.x == 0 )
  364.     {
  365.       return ( v.y >= 0 ) ? v.y : -v.y;
  366.     }
  367.     else if ( v.y == 0 )
  368.     {
  369.       return ( v.x >= 0 ) ? v.x : -v.x;
  370.     }
  371.     /* general case */
  372.     shift = ft_trig_prenorm( &v );
  373.     ft_trig_pseudo_polarize( &v );
  374.     v.x = ft_trig_downscale( v.x );
  375.     if ( shift > 0 )
  376.       return ( v.x + ( 1 << ( shift - 1 ) ) ) >> shift;
  377.     return v.x << -shift;
  378.   }
  379.   /* documentation is in fttrigon.h */
  380.   FT_EXPORT_DEF( void )
  381.   FT_Vector_Polarize( FT_Vector*  vec,
  382.                       FT_Fixed   *length,
  383.                       FT_Angle   *angle )
  384.   {
  385.     FT_Int     shift;
  386.     FT_Vector  v;
  387.     v = *vec;
  388.     if ( v.x == 0 && v.y == 0 )
  389.       return;
  390.     shift = ft_trig_prenorm( &v );
  391.     ft_trig_pseudo_polarize( &v );
  392.     v.x = ft_trig_downscale( v.x );
  393.     *length = ( shift >= 0 ) ? ( v.x >> shift ) : ( v.x << -shift );
  394.     *angle  = v.y;
  395.   }
  396.   /* documentation is in fttrigon.h */
  397.   FT_EXPORT_DEF( void )
  398.   FT_Vector_From_Polar( FT_Vector*  vec,
  399.                         FT_Fixed    length,
  400.                         FT_Angle    angle )
  401.   {
  402.     vec->x = length;
  403.     vec->y = 0;
  404.     FT_Vector_Rotate( vec, angle );
  405.   }
  406.   /* documentation is in fttrigon.h */
  407.   FT_EXPORT_DEF( FT_Angle )
  408.   FT_Angle_Diff( FT_Angle  angle1,
  409.                  FT_Angle  angle2 )
  410.   {
  411.     FT_Angle  delta = angle2 - angle1;
  412.     delta %= FT_ANGLE_2PI;
  413.     if ( delta < 0 )
  414.       delta += FT_ANGLE_2PI;
  415.     if ( delta > FT_ANGLE_PI )
  416.       delta -= FT_ANGLE_2PI;
  417.     return delta;
  418.   }
  419. /* END */