Edit

kc3-lang/freetype/src/autofit/afangles.c

Branch :

  • Show log

    Commit

  • Author : Werner Lemberg
    Date : 2020-01-19 17:05:19
    Hash : e5038be7
    Message : Update all copyright notices.

  • src/autofit/afangles.c
  • /****************************************************************************
     *
     * afangles.c
     *
     *   Routines used to compute vector angles with limited accuracy
     *   and very high speed.  It also contains sorting routines (body).
     *
     * Copyright (C) 2003-2020 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"
    
    
      /*
       * We are 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 a very accurate angle
       * approximation.  We are going to use the result of `af_angle_atan' to
       * only compare the sign of angle differences, or check whether 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 /* 0 */
    
    
      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_and_quantize_widths( FT_UInt*  count,
                                   AF_Width  table,
                                   FT_Pos    threshold )
      {
        FT_UInt      i, j;
        FT_UInt      cur_idx;
        FT_Pos       cur_val;
        FT_Pos       sum;
        AF_WidthRec  swap;
    
    
        if ( *count == 1 )
          return;
    
        /* sort */
        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;
          }
        }
    
        cur_idx = 0;
        cur_val = table[cur_idx].org;
    
        /* compute and use mean values for clusters not larger than  */
        /* `threshold'; this is very primitive and might not yield   */
        /* the best result, but normally, using reference character  */
        /* `o', `*count' is 2, so the code below is fully sufficient */
        for ( i = 1; i < *count; i++ )
        {
          if ( table[i].org - cur_val > threshold ||
               i == *count - 1                    )
          {
            sum = 0;
    
            /* fix loop for end of array */
            if ( table[i].org - cur_val <= threshold &&
                 i == *count - 1                     )
              i++;
    
            for ( j = cur_idx; j < i; j++ )
            {
              sum         += table[j].org;
              table[j].org = 0;
            }
            table[cur_idx].org = sum / (FT_Pos)j;
    
            if ( i < *count - 1 )
            {
              cur_idx = i + 1;
              cur_val = table[cur_idx].org;
            }
          }
        }
    
        cur_idx = 1;
    
        /* compress array to remove zero values */
        for ( i = 1; i < *count; i++ )
        {
          if ( table[i].org )
            table[cur_idx++] = table[i];
        }
    
        *count = cur_idx;
      }
    
    
    /* END */