shithub: freetype+ttf2subf

ref: 281679de8591f6884ea904c9c812e520ba3cc5dc
dir: /src/autofit/afangles.c/

View raw version
/***************************************************************************/
/*                                                                         */
/*  afangles.c                                                             */
/*                                                                         */
/*    Routines used to compute vector angles with limited accuracy         */
/*    and very high speed.  It also contains sorting routines (body).      */
/*                                                                         */
/*  Copyright 2003, 2004, 2005 by                                          */
/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
/*                                                                         */
/*  This file is part of the FreeType project, and may only be used,       */
/*  modified, and distributed under the terms of the FreeType project      */
/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
/*  this file you indicate that you have read the license and              */
/*  understand and accept it fully.                                        */
/*                                                                         */
/***************************************************************************/


#include "aftypes.h"


  FT_LOCAL_DEF( FT_Int )
  af_corner_is_flat( FT_Pos   x_in,
                     FT_Pos   y_in,
                     FT_Pos   x_out,
                     FT_Pos   y_out )
  {
    FT_Pos  ax = x_in;
    FT_Pos  ay = y_in;

    FT_Pos  d_in, d_out, d_corner;

    if ( ax < 0 ) ax = -ax;
    if ( ay < 0 ) ay = -ay;
    d_in = ax + ay;

    ax = x_out; if ( ax < 0 ) ax = -ax;
    ay = y_out; if ( ay < 0 ) ay = -ay;
    d_out = ax+ay;

    ax = x_out + x_in; if ( ax < 0 ) ax = -ax;
    ay = y_out + y_in; if ( ay < 0 ) ay = -ay;
    d_corner = ax+ay;

    return ( d_in + d_out - d_corner ) < (d_corner >> 4);
  }


  FT_LOCAL_DEF( FT_Int )
  af_corner_orientation( FT_Pos  x_in,
                         FT_Pos  y_in,
                         FT_Pos  x_out,
                         FT_Pos  y_out )
  {
    FT_Pos   delta;

    delta = x_in*y_out - y_in*x_out;

    if ( delta == 0 )
      return 0;
    else
      return 1 - 2*(delta < 0);
  }


  /* we're not using af_angle_atan anymore, but we keep the source
   * code below just in case :-)
   */
#if 0

 /* the trick here is to realize that we don't need an very accurate
  * angle approximation. We're going to use the result of af_angle_atan
  * to only compare the sign of angle differences, or see if its magnitude
  * is very small.
  *
  * the approximation (dy*PI/(|dx|+|dy|))) should be enough, and much
  * faster to compute.
  */
  FT_LOCAL_DEF( AF_Angle )
  af_angle_atan( FT_Fixed  dx,
                 FT_Fixed  dy )
  {
    AF_Angle  angle;
    FT_Fixed  ax = dx;
    FT_Fixed  ay = dy;

    if ( ax < 0 ) ax = -ax;
    if ( ay < 0 ) ay = -ay;

    ax += ay;

    if ( ax == 0 )
      angle = 0;
    else
    {
      angle = (AF_ANGLE_PI2*dy)/(ax+ay);
      if ( dx < 0 )
      {
        if ( angle >= 0 )
          angle = AF_ANGLE_PI - angle;
        else
          angle = -AF_ANGLE_PI - angle;
      }
    }

    return angle;
  }

#elif 0

  /* the following table has been automatically generated with */
  /* the `mather.py' Python script                             */

#define AF_ATAN_BITS  8

  static const FT_Byte  af_arctan[1L << AF_ATAN_BITS] =
  {
     0,  0,  1,  1,  1,  2,  2,  2,
     3,  3,  3,  3,  4,  4,  4,  5,
     5,  5,  6,  6,  6,  7,  7,  7,
     8,  8,  8,  9,  9,  9, 10, 10,
    10, 10, 11, 11, 11, 12, 12, 12,
    13, 13, 13, 14, 14, 14, 14, 15,
    15, 15, 16, 16, 16, 17, 17, 17,
    18, 18, 18, 18, 19, 19, 19, 20,
    20, 20, 21, 21, 21, 21, 22, 22,
    22, 23, 23, 23, 24, 24, 24, 24,
    25, 25, 25, 26, 26, 26, 26, 27,
    27, 27, 28, 28, 28, 28, 29, 29,
    29, 30, 30, 30, 30, 31, 31, 31,
    31, 32, 32, 32, 33, 33, 33, 33,
    34, 34, 34, 34, 35, 35, 35, 35,
    36, 36, 36, 36, 37, 37, 37, 38,
    38, 38, 38, 39, 39, 39, 39, 40,
    40, 40, 40, 41, 41, 41, 41, 42,
    42, 42, 42, 42, 43, 43, 43, 43,
    44, 44, 44, 44, 45, 45, 45, 45,
    46, 46, 46, 46, 46, 47, 47, 47,
    47, 48, 48, 48, 48, 48, 49, 49,
    49, 49, 50, 50, 50, 50, 50, 51,
    51, 51, 51, 51, 52, 52, 52, 52,
    52, 53, 53, 53, 53, 53, 54, 54,
    54, 54, 54, 55, 55, 55, 55, 55,
    56, 56, 56, 56, 56, 57, 57, 57,
    57, 57, 57, 58, 58, 58, 58, 58,
    59, 59, 59, 59, 59, 59, 60, 60,
    60, 60, 60, 61, 61, 61, 61, 61,
    61, 62, 62, 62, 62, 62, 62, 63,
    63, 63, 63, 63, 63, 64, 64, 64
  };


  FT_LOCAL_DEF( AF_Angle )
  af_angle_atan( FT_Fixed  dx,
                 FT_Fixed  dy )
  {
    AF_Angle  angle;


    /* check trivial cases */
    if ( dy == 0 )
    {
      angle = 0;
      if ( dx < 0 )
        angle = AF_ANGLE_PI;
      return angle;
    }
    else if ( dx == 0 )
    {
      angle = AF_ANGLE_PI2;
      if ( dy < 0 )
        angle = -AF_ANGLE_PI2;
      return angle;
    }

    angle = 0;
    if ( dx < 0 )
    {
      dx = -dx;
      dy = -dy;
      angle = AF_ANGLE_PI;
    }

    if ( dy < 0 )
    {
      FT_Pos  tmp;


      tmp = dx;
      dx  = -dy;
      dy  = tmp;
      angle -= AF_ANGLE_PI2;
    }

    if ( dx == 0 && dy == 0 )
      return 0;

    if ( dx == dy )
      angle += AF_ANGLE_PI4;
    else if ( dx > dy )
      angle += af_arctan[FT_DivFix( dy, dx ) >> ( 16 - AF_ATAN_BITS )];
    else
      angle += AF_ANGLE_PI2 -
               af_arctan[FT_DivFix( dx, dy ) >> ( 16 - AF_ATAN_BITS )];

    if ( angle > AF_ANGLE_PI )
      angle -= AF_ANGLE_2PI;

    return angle;
  }


#endif


  FT_LOCAL_DEF( void )
  af_sort_pos( FT_UInt  count,
               FT_Pos*  table )
  {
    FT_UInt  i, j;
    FT_Pos   swap;


    for ( i = 1; i < count; i++ )
    {
      for ( j = i; j > 0; j-- )
      {
        if ( table[j] > table[j - 1] )
          break;

        swap         = table[j];
        table[j]     = table[j - 1];
        table[j - 1] = swap;
      }
    }
  }


  FT_LOCAL_DEF( void )
  af_sort_widths( FT_UInt   count,
                  AF_Width  table )
  {
    FT_UInt      i, j;
    AF_WidthRec  swap;


    for ( i = 1; i < count; i++ )
    {
      for ( j = i; j > 0; j-- )
      {
        if ( table[j].org > table[j - 1].org )
          break;

        swap         = table[j];
        table[j]     = table[j - 1];
        table[j - 1] = swap;
      }
    }
  }


/* END */