Home | History | Annotate | Download | only in autofit
      1 /***************************************************************************/
      2 /*                                                                         */
      3 /*  afangles.c                                                             */
      4 /*                                                                         */
      5 /*    Routines used to compute vector angles with limited accuracy         */
      6 /*    and very high speed.  It also contains sorting routines (body).      */
      7 /*                                                                         */
      8 /*  Copyright 2003-2017 by                                                 */
      9 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
     10 /*                                                                         */
     11 /*  This file is part of the FreeType project, and may only be used,       */
     12 /*  modified, and distributed under the terms of the FreeType project      */
     13 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
     14 /*  this file you indicate that you have read the license and              */
     15 /*  understand and accept it fully.                                        */
     16 /*                                                                         */
     17 /***************************************************************************/
     18 
     19 
     20 #include "aftypes.h"
     21 
     22 
     23   /*
     24    *  We are not using `af_angle_atan' anymore, but we keep the source
     25    *  code below just in case...
     26    */
     27 
     28 
     29 #if 0
     30 
     31 
     32   /*
     33    *  The trick here is to realize that we don't need a very accurate angle
     34    *  approximation.  We are going to use the result of `af_angle_atan' to
     35    *  only compare the sign of angle differences, or check whether its
     36    *  magnitude is very small.
     37    *
     38    *  The approximation
     39    *
     40    *    dy * PI / (|dx|+|dy|)
     41    *
     42    *  should be enough, and much faster to compute.
     43    */
     44   FT_LOCAL_DEF( AF_Angle )
     45   af_angle_atan( FT_Fixed  dx,
     46                  FT_Fixed  dy )
     47   {
     48     AF_Angle  angle;
     49     FT_Fixed  ax = dx;
     50     FT_Fixed  ay = dy;
     51 
     52 
     53     if ( ax < 0 )
     54       ax = -ax;
     55     if ( ay < 0 )
     56       ay = -ay;
     57 
     58     ax += ay;
     59 
     60     if ( ax == 0 )
     61       angle = 0;
     62     else
     63     {
     64       angle = ( AF_ANGLE_PI2 * dy ) / ( ax + ay );
     65       if ( dx < 0 )
     66       {
     67         if ( angle >= 0 )
     68           angle = AF_ANGLE_PI - angle;
     69         else
     70           angle = -AF_ANGLE_PI - angle;
     71       }
     72     }
     73 
     74     return angle;
     75   }
     76 
     77 
     78 #elif 0
     79 
     80 
     81   /* the following table has been automatically generated with */
     82   /* the `mather.py' Python script                             */
     83 
     84 #define AF_ATAN_BITS  8
     85 
     86   static const FT_Byte  af_arctan[1L << AF_ATAN_BITS] =
     87   {
     88      0,  0,  1,  1,  1,  2,  2,  2,
     89      3,  3,  3,  3,  4,  4,  4,  5,
     90      5,  5,  6,  6,  6,  7,  7,  7,
     91      8,  8,  8,  9,  9,  9, 10, 10,
     92     10, 10, 11, 11, 11, 12, 12, 12,
     93     13, 13, 13, 14, 14, 14, 14, 15,
     94     15, 15, 16, 16, 16, 17, 17, 17,
     95     18, 18, 18, 18, 19, 19, 19, 20,
     96     20, 20, 21, 21, 21, 21, 22, 22,
     97     22, 23, 23, 23, 24, 24, 24, 24,
     98     25, 25, 25, 26, 26, 26, 26, 27,
     99     27, 27, 28, 28, 28, 28, 29, 29,
    100     29, 30, 30, 30, 30, 31, 31, 31,
    101     31, 32, 32, 32, 33, 33, 33, 33,
    102     34, 34, 34, 34, 35, 35, 35, 35,
    103     36, 36, 36, 36, 37, 37, 37, 38,
    104     38, 38, 38, 39, 39, 39, 39, 40,
    105     40, 40, 40, 41, 41, 41, 41, 42,
    106     42, 42, 42, 42, 43, 43, 43, 43,
    107     44, 44, 44, 44, 45, 45, 45, 45,
    108     46, 46, 46, 46, 46, 47, 47, 47,
    109     47, 48, 48, 48, 48, 48, 49, 49,
    110     49, 49, 50, 50, 50, 50, 50, 51,
    111     51, 51, 51, 51, 52, 52, 52, 52,
    112     52, 53, 53, 53, 53, 53, 54, 54,
    113     54, 54, 54, 55, 55, 55, 55, 55,
    114     56, 56, 56, 56, 56, 57, 57, 57,
    115     57, 57, 57, 58, 58, 58, 58, 58,
    116     59, 59, 59, 59, 59, 59, 60, 60,
    117     60, 60, 60, 61, 61, 61, 61, 61,
    118     61, 62, 62, 62, 62, 62, 62, 63,
    119     63, 63, 63, 63, 63, 64, 64, 64
    120   };
    121 
    122 
    123   FT_LOCAL_DEF( AF_Angle )
    124   af_angle_atan( FT_Fixed  dx,
    125                  FT_Fixed  dy )
    126   {
    127     AF_Angle  angle;
    128 
    129 
    130     /* check trivial cases */
    131     if ( dy == 0 )
    132     {
    133       angle = 0;
    134       if ( dx < 0 )
    135         angle = AF_ANGLE_PI;
    136       return angle;
    137     }
    138     else if ( dx == 0 )
    139     {
    140       angle = AF_ANGLE_PI2;
    141       if ( dy < 0 )
    142         angle = -AF_ANGLE_PI2;
    143       return angle;
    144     }
    145 
    146     angle = 0;
    147     if ( dx < 0 )
    148     {
    149       dx = -dx;
    150       dy = -dy;
    151       angle = AF_ANGLE_PI;
    152     }
    153 
    154     if ( dy < 0 )
    155     {
    156       FT_Pos  tmp;
    157 
    158 
    159       tmp = dx;
    160       dx  = -dy;
    161       dy  = tmp;
    162       angle -= AF_ANGLE_PI2;
    163     }
    164 
    165     if ( dx == 0 && dy == 0 )
    166       return 0;
    167 
    168     if ( dx == dy )
    169       angle += AF_ANGLE_PI4;
    170     else if ( dx > dy )
    171       angle += af_arctan[FT_DivFix( dy, dx ) >> ( 16 - AF_ATAN_BITS )];
    172     else
    173       angle += AF_ANGLE_PI2 -
    174                af_arctan[FT_DivFix( dx, dy ) >> ( 16 - AF_ATAN_BITS )];
    175 
    176     if ( angle > AF_ANGLE_PI )
    177       angle -= AF_ANGLE_2PI;
    178 
    179     return angle;
    180   }
    181 
    182 
    183 #endif /* 0 */
    184 
    185 
    186   FT_LOCAL_DEF( void )
    187   af_sort_pos( FT_UInt  count,
    188                FT_Pos*  table )
    189   {
    190     FT_UInt  i, j;
    191     FT_Pos   swap;
    192 
    193 
    194     for ( i = 1; i < count; i++ )
    195     {
    196       for ( j = i; j > 0; j-- )
    197       {
    198         if ( table[j] >= table[j - 1] )
    199           break;
    200 
    201         swap         = table[j];
    202         table[j]     = table[j - 1];
    203         table[j - 1] = swap;
    204       }
    205     }
    206   }
    207 
    208 
    209   FT_LOCAL_DEF( void )
    210   af_sort_and_quantize_widths( FT_UInt*  count,
    211                                AF_Width  table,
    212                                FT_Pos    threshold )
    213   {
    214     FT_UInt      i, j;
    215     FT_UInt      cur_idx;
    216     FT_Pos       cur_val;
    217     FT_Pos       sum;
    218     AF_WidthRec  swap;
    219 
    220 
    221     if ( *count == 1 )
    222       return;
    223 
    224     /* sort */
    225     for ( i = 1; i < *count; i++ )
    226     {
    227       for ( j = i; j > 0; j-- )
    228       {
    229         if ( table[j].org >= table[j - 1].org )
    230           break;
    231 
    232         swap         = table[j];
    233         table[j]     = table[j - 1];
    234         table[j - 1] = swap;
    235       }
    236     }
    237 
    238     cur_idx = 0;
    239     cur_val = table[cur_idx].org;
    240 
    241     /* compute and use mean values for clusters not larger than  */
    242     /* `threshold'; this is very primitive and might not yield   */
    243     /* the best result, but normally, using reference character  */
    244     /* `o', `*count' is 2, so the code below is fully sufficient */
    245     for ( i = 1; i < *count; i++ )
    246     {
    247       if ( table[i].org - cur_val > threshold ||
    248            i == *count - 1                    )
    249       {
    250         sum = 0;
    251 
    252         /* fix loop for end of array */
    253         if ( table[i].org - cur_val <= threshold &&
    254              i == *count - 1                     )
    255           i++;
    256 
    257         for ( j = cur_idx; j < i; j++ )
    258         {
    259           sum         += table[j].org;
    260           table[j].org = 0;
    261         }
    262         table[cur_idx].org = sum / (FT_Pos)j;
    263 
    264         if ( i < *count - 1 )
    265         {
    266           cur_idx = i + 1;
    267           cur_val = table[cur_idx].org;
    268         }
    269       }
    270     }
    271 
    272     cur_idx = 1;
    273 
    274     /* compress array to remove zero values */
    275     for ( i = 1; i < *count; i++ )
    276     {
    277       if ( table[i].org )
    278         table[cur_idx++] = table[i];
    279     }
    280 
    281     *count = cur_idx;
    282   }
    283 
    284 
    285 /* END */
    286