misc/libfreetype/src/autofit/afhints.c
changeset 9372 915436ff64ab
parent 9371 f3840de881bd
child 9373 b769a8e38cbd
--- a/misc/libfreetype/src/autofit/afhints.c	Thu Jul 25 23:16:06 2013 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1208 +0,0 @@
-/***************************************************************************/
-/*                                                                         */
-/*  afhints.c                                                              */
-/*                                                                         */
-/*    Auto-fitter hinting routines (body).                                 */
-/*                                                                         */
-/*  Copyright 2003-2007, 2009-2011 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 "afhints.h"
-#include "aferrors.h"
-#include FT_INTERNAL_CALC_H
-
-
-  /* Get new segment for given axis. */
-
-  FT_LOCAL_DEF( FT_Error )
-  af_axis_hints_new_segment( AF_AxisHints  axis,
-                             FT_Memory     memory,
-                             AF_Segment   *asegment )
-  {
-    FT_Error    error   = AF_Err_Ok;
-    AF_Segment  segment = NULL;
-
-
-    if ( axis->num_segments >= axis->max_segments )
-    {
-      FT_Int  old_max = axis->max_segments;
-      FT_Int  new_max = old_max;
-      FT_Int  big_max = (FT_Int)( FT_INT_MAX / sizeof ( *segment ) );
-
-
-      if ( old_max >= big_max )
-      {
-        error = AF_Err_Out_Of_Memory;
-        goto Exit;
-      }
-
-      new_max += ( new_max >> 2 ) + 4;
-      if ( new_max < old_max || new_max > big_max )
-        new_max = big_max;
-
-      if ( FT_RENEW_ARRAY( axis->segments, old_max, new_max ) )
-        goto Exit;
-
-      axis->max_segments = new_max;
-    }
-
-    segment = axis->segments + axis->num_segments++;
-
-  Exit:
-    *asegment = segment;
-    return error;
-  }
-
-
-  /* Get new edge for given axis, direction, and position. */
-
-  FT_LOCAL( FT_Error )
-  af_axis_hints_new_edge( AF_AxisHints  axis,
-                          FT_Int        fpos,
-                          AF_Direction  dir,
-                          FT_Memory     memory,
-                          AF_Edge      *aedge )
-  {
-    FT_Error  error = AF_Err_Ok;
-    AF_Edge   edge  = NULL;
-    AF_Edge   edges;
-
-
-    if ( axis->num_edges >= axis->max_edges )
-    {
-      FT_Int  old_max = axis->max_edges;
-      FT_Int  new_max = old_max;
-      FT_Int  big_max = (FT_Int)( FT_INT_MAX / sizeof ( *edge ) );
-
-
-      if ( old_max >= big_max )
-      {
-        error = AF_Err_Out_Of_Memory;
-        goto Exit;
-      }
-
-      new_max += ( new_max >> 2 ) + 4;
-      if ( new_max < old_max || new_max > big_max )
-        new_max = big_max;
-
-      if ( FT_RENEW_ARRAY( axis->edges, old_max, new_max ) )
-        goto Exit;
-
-      axis->max_edges = new_max;
-    }
-
-    edges = axis->edges;
-    edge  = edges + axis->num_edges;
-
-    while ( edge > edges )
-    {
-      if ( edge[-1].fpos < fpos )
-        break;
-
-      /* we want the edge with same position and minor direction */
-      /* to appear before those in the major one in the list     */
-      if ( edge[-1].fpos == fpos && dir == axis->major_dir )
-        break;
-
-      edge[0] = edge[-1];
-      edge--;
-    }
-
-    axis->num_edges++;
-
-    FT_ZERO( edge );
-    edge->fpos = (FT_Short)fpos;
-    edge->dir  = (FT_Char)dir;
-
-  Exit:
-    *aedge = edge;
-    return error;
-  }
-
-
-#ifdef FT_DEBUG_AUTOFIT
-
-#include FT_CONFIG_STANDARD_LIBRARY_H
-
-  static const char*
-  af_dir_str( AF_Direction  dir )
-  {
-    const char*  result;
-
-
-    switch ( dir )
-    {
-    case AF_DIR_UP:
-      result = "up";
-      break;
-    case AF_DIR_DOWN:
-      result = "down";
-      break;
-    case AF_DIR_LEFT:
-      result = "left";
-      break;
-    case AF_DIR_RIGHT:
-      result = "right";
-      break;
-    default:
-      result = "none";
-    }
-
-    return result;
-  }
-
-
-#define AF_INDEX_NUM( ptr, base )  ( (ptr) ? ( (ptr) - (base) ) : -1 )
-
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-  void
-  af_glyph_hints_dump_points( AF_GlyphHints  hints )
-  {
-    AF_Point  points = hints->points;
-    AF_Point  limit  = points + hints->num_points;
-    AF_Point  point;
-
-
-    printf( "Table of points:\n" );
-    printf(   "  [ index |  xorg |  yorg | xscale | yscale"
-              " |  xfit |  yfit |  flags ]\n" );
-
-    for ( point = points; point < limit; point++ )
-    {
-      printf( "  [ %5d | %5d | %5d | %6.2f | %6.2f"
-              " | %5.2f | %5.2f | %c%c%c%c%c%c ]\n",
-              point - points,
-              point->fx,
-              point->fy,
-              point->ox / 64.0,
-              point->oy / 64.0,
-              point->x / 64.0,
-              point->y / 64.0,
-              ( point->flags & AF_FLAG_WEAK_INTERPOLATION ) ? 'w' : ' ',
-              ( point->flags & AF_FLAG_INFLECTION )         ? 'i' : ' ',
-              ( point->flags & AF_FLAG_EXTREMA_X )          ? '<' : ' ',
-              ( point->flags & AF_FLAG_EXTREMA_Y )          ? 'v' : ' ',
-              ( point->flags & AF_FLAG_ROUND_X )            ? '(' : ' ',
-              ( point->flags & AF_FLAG_ROUND_Y )            ? 'u' : ' ');
-    }
-    printf( "\n" );
-  }
-#ifdef __cplusplus
-  }
-#endif
-
-
-  static const char*
-  af_edge_flags_to_string( AF_Edge_Flags  flags )
-  {
-    static char  temp[32];
-    int          pos = 0;
-
-
-    if ( flags & AF_EDGE_ROUND )
-    {
-      ft_memcpy( temp + pos, "round", 5 );
-      pos += 5;
-    }
-    if ( flags & AF_EDGE_SERIF )
-    {
-      if ( pos > 0 )
-        temp[pos++] = ' ';
-      ft_memcpy( temp + pos, "serif", 5 );
-      pos += 5;
-    }
-    if ( pos == 0 )
-      return "normal";
-
-    temp[pos] = 0;
-
-    return temp;
-  }
-
-
-  /* Dump the array of linked segments. */
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-  void
-  af_glyph_hints_dump_segments( AF_GlyphHints  hints )
-  {
-    FT_Int  dimension;
-
-
-    for ( dimension = 1; dimension >= 0; dimension-- )
-    {
-      AF_AxisHints  axis     = &hints->axis[dimension];
-      AF_Segment    segments = axis->segments;
-      AF_Segment    limit    = segments + axis->num_segments;
-      AF_Segment    seg;
-
-
-      printf ( "Table of %s segments:\n",
-               dimension == AF_DIMENSION_HORZ ? "vertical" : "horizontal" );
-      printf ( "  [ index |  pos  |  dir  | link | serif |"
-               " height | extra |    flags    ]\n" );
-
-      for ( seg = segments; seg < limit; seg++ )
-      {
-        printf ( "  [ %5d | %5.2g | %5s | %4d | %5d | %6d | %5d | %11s ]\n",
-                 seg - segments,
-                 dimension == AF_DIMENSION_HORZ ? (int)seg->first->ox / 64.0
-                                                : (int)seg->first->oy / 64.0,
-                 af_dir_str( (AF_Direction)seg->dir ),
-                 AF_INDEX_NUM( seg->link, segments ),
-                 AF_INDEX_NUM( seg->serif, segments ),
-                 seg->height,
-                 seg->height - ( seg->max_coord - seg->min_coord ),
-                 af_edge_flags_to_string( seg->flags ) );
-      }
-      printf( "\n" );
-    }
-  }
-#ifdef __cplusplus
-  }
-#endif
-
-
-  /* Dump the array of linked edges. */
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-  void
-  af_glyph_hints_dump_edges( AF_GlyphHints  hints )
-  {
-    FT_Int  dimension;
-
-
-    for ( dimension = 1; dimension >= 0; dimension-- )
-    {
-      AF_AxisHints  axis  = &hints->axis[dimension];
-      AF_Edge       edges = axis->edges;
-      AF_Edge       limit = edges + axis->num_edges;
-      AF_Edge       edge;
-
-
-      /*
-       *  note: AF_DIMENSION_HORZ corresponds to _vertical_ edges
-       *        since they have a constant X coordinate.
-       */
-      printf ( "Table of %s edges:\n",
-               dimension == AF_DIMENSION_HORZ ? "vertical" : "horizontal" );
-      printf ( "  [ index |  pos  |  dir  | link |"
-               " serif | blue | opos  |  pos  |    flags    ]\n" );
-
-      for ( edge = edges; edge < limit; edge++ )
-      {
-        printf ( "  [ %5d | %5.2g | %5s | %4d |"
-                 " %5d |   %c  | %5.2f | %5.2f | %11s ]\n",
-                 edge - edges,
-                 (int)edge->opos / 64.0,
-                 af_dir_str( (AF_Direction)edge->dir ),
-                 AF_INDEX_NUM( edge->link, edges ),
-                 AF_INDEX_NUM( edge->serif, edges ),
-                 edge->blue_edge ? 'y' : 'n',
-                 edge->opos / 64.0,
-                 edge->pos / 64.0,
-                 af_edge_flags_to_string( edge->flags ) );
-      }
-      printf( "\n" );
-    }
-  }
-#ifdef __cplusplus
-  }
-#endif
-
-#else /* !FT_DEBUG_AUTOFIT */
-
-  /* these empty stubs are only used to link the `ftgrid' test program */
-  /* if debugging is disabled                                          */
-
-#ifdef __cplusplus
-  extern "C" {
-#endif
-
-  void
-  af_glyph_hints_dump_points( AF_GlyphHints  hints )
-  {
-    FT_UNUSED( hints );
-  }
-
-
-  void
-  af_glyph_hints_dump_segments( AF_GlyphHints  hints )
-  {
-    FT_UNUSED( hints );
-  }
-
-
-  void
-  af_glyph_hints_dump_edges( AF_GlyphHints  hints )
-  {
-    FT_UNUSED( hints );
-  }
-
-#ifdef __cplusplus
-  }
-#endif
-
-#endif /* !FT_DEBUG_AUTOFIT */
-
-
-  /* Compute the direction value of a given vector. */
-
-  FT_LOCAL_DEF( AF_Direction )
-  af_direction_compute( FT_Pos  dx,
-                        FT_Pos  dy )
-  {
-    FT_Pos        ll, ss;  /* long and short arm lengths */
-    AF_Direction  dir;     /* candidate direction        */
-
-
-    if ( dy >= dx )
-    {
-      if ( dy >= -dx )
-      {
-        dir = AF_DIR_UP;
-        ll  = dy;
-        ss  = dx;
-      }
-      else
-      {
-        dir = AF_DIR_LEFT;
-        ll  = -dx;
-        ss  = dy;
-      }
-    }
-    else /* dy < dx */
-    {
-      if ( dy >= -dx )
-      {
-        dir = AF_DIR_RIGHT;
-        ll  = dx;
-        ss  = dy;
-      }
-      else
-      {
-        dir = AF_DIR_DOWN;
-        ll  = dy;
-        ss  = dx;
-      }
-    }
-
-    /* return no direction if arm lengths differ too much */
-    /* (value 14 is heuristic)                            */
-    ss *= 14;
-    if ( FT_ABS( ll ) <= FT_ABS( ss ) )
-      dir = AF_DIR_NONE;
-
-    return dir;
-  }
-
-
-  FT_LOCAL_DEF( void )
-  af_glyph_hints_init( AF_GlyphHints  hints,
-                       FT_Memory      memory )
-  {
-    FT_ZERO( hints );
-    hints->memory = memory;
-  }
-
-
-  FT_LOCAL_DEF( void )
-  af_glyph_hints_done( AF_GlyphHints  hints )
-  {
-    if ( hints && hints->memory )
-    {
-      FT_Memory  memory = hints->memory;
-      int        dim;
-
-
-      /*
-       *  note that we don't need to free the segment and edge
-       *  buffers since they are really within the hints->points array
-       */
-      for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
-      {
-        AF_AxisHints  axis = &hints->axis[dim];
-
-
-        axis->num_segments = 0;
-        axis->max_segments = 0;
-        FT_FREE( axis->segments );
-
-        axis->num_edges = 0;
-        axis->max_edges = 0;
-        FT_FREE( axis->edges );
-      }
-
-      FT_FREE( hints->contours );
-      hints->max_contours = 0;
-      hints->num_contours = 0;
-
-      FT_FREE( hints->points );
-      hints->num_points = 0;
-      hints->max_points = 0;
-
-      hints->memory = NULL;
-    }
-  }
-
-
-  /* Reset metrics. */
-
-  FT_LOCAL_DEF( void )
-  af_glyph_hints_rescale( AF_GlyphHints     hints,
-                          AF_ScriptMetrics  metrics )
-  {
-    hints->metrics      = metrics;
-    hints->scaler_flags = metrics->scaler.flags;
-  }
-
-
-  /* Recompute all AF_Point in AF_GlyphHints from the definitions */
-  /* in a source outline.                                         */
-
-  FT_LOCAL_DEF( FT_Error )
-  af_glyph_hints_reload( AF_GlyphHints  hints,
-                         FT_Outline*    outline )
-  {
-    FT_Error   error   = AF_Err_Ok;
-    AF_Point   points;
-    FT_UInt    old_max, new_max;
-    FT_Fixed   x_scale = hints->x_scale;
-    FT_Fixed   y_scale = hints->y_scale;
-    FT_Pos     x_delta = hints->x_delta;
-    FT_Pos     y_delta = hints->y_delta;
-    FT_Memory  memory  = hints->memory;
-
-
-    hints->num_points   = 0;
-    hints->num_contours = 0;
-
-    hints->axis[0].num_segments = 0;
-    hints->axis[0].num_edges    = 0;
-    hints->axis[1].num_segments = 0;
-    hints->axis[1].num_edges    = 0;
-
-    /* first of all, reallocate the contours array if necessary */
-    new_max = (FT_UInt)outline->n_contours;
-    old_max = hints->max_contours;
-    if ( new_max > old_max )
-    {
-      new_max = ( new_max + 3 ) & ~3; /* round up to a multiple of 4 */
-
-      if ( FT_RENEW_ARRAY( hints->contours, old_max, new_max ) )
-        goto Exit;
-
-      hints->max_contours = new_max;
-    }
-
-    /*
-     *  then reallocate the points arrays if necessary --
-     *  note that we reserve two additional point positions, used to
-     *  hint metrics appropriately
-     */
-    new_max = (FT_UInt)( outline->n_points + 2 );
-    old_max = hints->max_points;
-    if ( new_max > old_max )
-    {
-      new_max = ( new_max + 2 + 7 ) & ~7; /* round up to a multiple of 8 */
-
-      if ( FT_RENEW_ARRAY( hints->points, old_max, new_max ) )
-        goto Exit;
-
-      hints->max_points = new_max;
-    }
-
-    hints->num_points   = outline->n_points;
-    hints->num_contours = outline->n_contours;
-
-    /* We can't rely on the value of `FT_Outline.flags' to know the fill   */
-    /* direction used for a glyph, given that some fonts are broken (e.g., */
-    /* the Arphic ones).  We thus recompute it each time we need to.       */
-    /*                                                                     */
-    hints->axis[AF_DIMENSION_HORZ].major_dir = AF_DIR_UP;
-    hints->axis[AF_DIMENSION_VERT].major_dir = AF_DIR_LEFT;
-
-    if ( FT_Outline_Get_Orientation( outline ) == FT_ORIENTATION_POSTSCRIPT )
-    {
-      hints->axis[AF_DIMENSION_HORZ].major_dir = AF_DIR_DOWN;
-      hints->axis[AF_DIMENSION_VERT].major_dir = AF_DIR_RIGHT;
-    }
-
-    hints->x_scale = x_scale;
-    hints->y_scale = y_scale;
-    hints->x_delta = x_delta;
-    hints->y_delta = y_delta;
-
-    hints->xmin_delta = 0;
-    hints->xmax_delta = 0;
-
-    points = hints->points;
-    if ( hints->num_points == 0 )
-      goto Exit;
-
-    {
-      AF_Point  point;
-      AF_Point  point_limit = points + hints->num_points;
-
-
-      /* compute coordinates & Bezier flags, next and prev */
-      {
-        FT_Vector*  vec           = outline->points;
-        char*       tag           = outline->tags;
-        AF_Point    end           = points + outline->contours[0];
-        AF_Point    prev          = end;
-        FT_Int      contour_index = 0;
-
-
-        for ( point = points; point < point_limit; point++, vec++, tag++ )
-        {
-          point->fx = (FT_Short)vec->x;
-          point->fy = (FT_Short)vec->y;
-          point->ox = point->x = FT_MulFix( vec->x, x_scale ) + x_delta;
-          point->oy = point->y = FT_MulFix( vec->y, y_scale ) + y_delta;
-
-          switch ( FT_CURVE_TAG( *tag ) )
-          {
-          case FT_CURVE_TAG_CONIC:
-            point->flags = AF_FLAG_CONIC;
-            break;
-          case FT_CURVE_TAG_CUBIC:
-            point->flags = AF_FLAG_CUBIC;
-            break;
-          default:
-            point->flags = AF_FLAG_NONE;
-          }
-
-          point->prev = prev;
-          prev->next  = point;
-          prev        = point;
-
-          if ( point == end )
-          {
-            if ( ++contour_index < outline->n_contours )
-            {
-              end  = points + outline->contours[contour_index];
-              prev = end;
-            }
-          }
-        }
-      }
-
-      /* set up the contours array */
-      {
-        AF_Point*  contour       = hints->contours;
-        AF_Point*  contour_limit = contour + hints->num_contours;
-        short*     end           = outline->contours;
-        short      idx           = 0;
-
-
-        for ( ; contour < contour_limit; contour++, end++ )
-        {
-          contour[0] = points + idx;
-          idx        = (short)( end[0] + 1 );
-        }
-      }
-
-      /* compute directions of in & out vectors */
-      {
-        AF_Point      first  = points;
-        AF_Point      prev   = NULL;
-        FT_Pos        in_x   = 0;
-        FT_Pos        in_y   = 0;
-        AF_Direction  in_dir = AF_DIR_NONE;
-
-
-        for ( point = points; point < point_limit; point++ )
-        {
-          AF_Point  next;
-          FT_Pos    out_x, out_y;
-
-
-          if ( point == first )
-          {
-            prev   = first->prev;
-            in_x   = first->fx - prev->fx;
-            in_y   = first->fy - prev->fy;
-            in_dir = af_direction_compute( in_x, in_y );
-            first  = prev + 1;
-          }
-
-          point->in_dir = (FT_Char)in_dir;
-
-          next  = point->next;
-          out_x = next->fx - point->fx;
-          out_y = next->fy - point->fy;
-
-          in_dir         = af_direction_compute( out_x, out_y );
-          point->out_dir = (FT_Char)in_dir;
-
-          /* check for weak points */
-
-          if ( point->flags & ( AF_FLAG_CONIC | AF_FLAG_CUBIC ) )
-          {
-          Is_Weak_Point:
-            point->flags |= AF_FLAG_WEAK_INTERPOLATION;
-          }
-          else if ( point->out_dir == point->in_dir )
-          {
-            if ( point->out_dir != AF_DIR_NONE )
-              goto Is_Weak_Point;
-
-            if ( ft_corner_is_flat( in_x, in_y, out_x, out_y ) )
-              goto Is_Weak_Point;
-          }
-          else if ( point->in_dir == -point->out_dir )
-            goto Is_Weak_Point;
-
-          in_x = out_x;
-          in_y = out_y;
-          prev = point;
-        }
-      }
-    }
-
-  Exit:
-    return error;
-  }
-
-
-  /* Store the hinted outline in an FT_Outline structure. */
-
-  FT_LOCAL_DEF( void )
-  af_glyph_hints_save( AF_GlyphHints  hints,
-                       FT_Outline*    outline )
-  {
-    AF_Point    point = hints->points;
-    AF_Point    limit = point + hints->num_points;
-    FT_Vector*  vec   = outline->points;
-    char*       tag   = outline->tags;
-
-
-    for ( ; point < limit; point++, vec++, tag++ )
-    {
-      vec->x = point->x;
-      vec->y = point->y;
-
-      if ( point->flags & AF_FLAG_CONIC )
-        tag[0] = FT_CURVE_TAG_CONIC;
-      else if ( point->flags & AF_FLAG_CUBIC )
-        tag[0] = FT_CURVE_TAG_CUBIC;
-      else
-        tag[0] = FT_CURVE_TAG_ON;
-    }
-  }
-
-
-  /****************************************************************
-   *
-   *                     EDGE POINT GRID-FITTING
-   *
-   ****************************************************************/
-
-
-  /* Align all points of an edge to the same coordinate value, */
-  /* either horizontally or vertically.                        */
-
-  FT_LOCAL_DEF( void )
-  af_glyph_hints_align_edge_points( AF_GlyphHints  hints,
-                                    AF_Dimension   dim )
-  {
-    AF_AxisHints  axis          = & hints->axis[dim];
-    AF_Segment    segments      = axis->segments;
-    AF_Segment    segment_limit = segments + axis->num_segments;
-    AF_Segment    seg;
-
-
-    if ( dim == AF_DIMENSION_HORZ )
-    {
-      for ( seg = segments; seg < segment_limit; seg++ )
-      {
-        AF_Edge   edge = seg->edge;
-        AF_Point  point, first, last;
-
-
-        if ( edge == NULL )
-          continue;
-
-        first = seg->first;
-        last  = seg->last;
-        point = first;
-        for (;;)
-        {
-          point->x      = edge->pos;
-          point->flags |= AF_FLAG_TOUCH_X;
-
-          if ( point == last )
-            break;
-
-          point = point->next;
-        }
-      }
-    }
-    else
-    {
-      for ( seg = segments; seg < segment_limit; seg++ )
-      {
-        AF_Edge   edge = seg->edge;
-        AF_Point  point, first, last;
-
-
-        if ( edge == NULL )
-          continue;
-
-        first = seg->first;
-        last  = seg->last;
-        point = first;
-        for (;;)
-        {
-          point->y      = edge->pos;
-          point->flags |= AF_FLAG_TOUCH_Y;
-
-          if ( point == last )
-            break;
-
-          point = point->next;
-        }
-      }
-    }
-  }
-
-
-  /****************************************************************
-   *
-   *                    STRONG POINT INTERPOLATION
-   *
-   ****************************************************************/
-
-
-  /* Hint the strong points -- this is equivalent to the TrueType `IP' */
-  /* hinting instruction.                                              */
-
-  FT_LOCAL_DEF( void )
-  af_glyph_hints_align_strong_points( AF_GlyphHints  hints,
-                                      AF_Dimension   dim )
-  {
-    AF_Point      points      = hints->points;
-    AF_Point      point_limit = points + hints->num_points;
-    AF_AxisHints  axis        = &hints->axis[dim];
-    AF_Edge       edges       = axis->edges;
-    AF_Edge       edge_limit  = edges + axis->num_edges;
-    AF_Flags      touch_flag;
-
-
-    if ( dim == AF_DIMENSION_HORZ )
-      touch_flag = AF_FLAG_TOUCH_X;
-    else
-      touch_flag  = AF_FLAG_TOUCH_Y;
-
-    if ( edges < edge_limit )
-    {
-      AF_Point  point;
-      AF_Edge   edge;
-
-
-      for ( point = points; point < point_limit; point++ )
-      {
-        FT_Pos  u, ou, fu;  /* point position */
-        FT_Pos  delta;
-
-
-        if ( point->flags & touch_flag )
-          continue;
-
-        /* if this point is candidate to weak interpolation, we       */
-        /* interpolate it after all strong points have been processed */
-
-        if (  ( point->flags & AF_FLAG_WEAK_INTERPOLATION ) &&
-             !( point->flags & AF_FLAG_INFLECTION )         )
-          continue;
-
-        if ( dim == AF_DIMENSION_VERT )
-        {
-          u  = point->fy;
-          ou = point->oy;
-        }
-        else
-        {
-          u  = point->fx;
-          ou = point->ox;
-        }
-
-        fu = u;
-
-        /* is the point before the first edge? */
-        edge  = edges;
-        delta = edge->fpos - u;
-        if ( delta >= 0 )
-        {
-          u = edge->pos - ( edge->opos - ou );
-          goto Store_Point;
-        }
-
-        /* is the point after the last edge? */
-        edge  = edge_limit - 1;
-        delta = u - edge->fpos;
-        if ( delta >= 0 )
-        {
-          u = edge->pos + ( ou - edge->opos );
-          goto Store_Point;
-        }
-
-        {
-          FT_PtrDist  min, max, mid;
-          FT_Pos      fpos;
-
-
-          /* find enclosing edges */
-          min = 0;
-          max = edge_limit - edges;
-
-#if 1
-          /* for a small number of edges, a linear search is better */
-          if ( max <= 8 )
-          {
-            FT_PtrDist  nn;
-
-
-            for ( nn = 0; nn < max; nn++ )
-              if ( edges[nn].fpos >= u )
-                break;
-
-            if ( edges[nn].fpos == u )
-            {
-              u = edges[nn].pos;
-              goto Store_Point;
-            }
-            min = nn;
-          }
-          else
-#endif
-          while ( min < max )
-          {
-            mid  = ( max + min ) >> 1;
-            edge = edges + mid;
-            fpos = edge->fpos;
-
-            if ( u < fpos )
-              max = mid;
-            else if ( u > fpos )
-              min = mid + 1;
-            else
-            {
-              /* we are on the edge */
-              u = edge->pos;
-              goto Store_Point;
-            }
-          }
-
-          /* point is not on an edge */
-          {
-            AF_Edge  before = edges + min - 1;
-            AF_Edge  after  = edges + min + 0;
-
-
-            /* assert( before && after && before != after ) */
-            if ( before->scale == 0 )
-              before->scale = FT_DivFix( after->pos - before->pos,
-                                         after->fpos - before->fpos );
-
-            u = before->pos + FT_MulFix( fu - before->fpos,
-                                         before->scale );
-          }
-        }
-
-      Store_Point:
-        /* save the point position */
-        if ( dim == AF_DIMENSION_HORZ )
-          point->x = u;
-        else
-          point->y = u;
-
-        point->flags |= touch_flag;
-      }
-    }
-  }
-
-
-  /****************************************************************
-   *
-   *                    WEAK POINT INTERPOLATION
-   *
-   ****************************************************************/
-
-
-  /* Shift the original coordinates of all points between `p1' and */
-  /* `p2' to get hinted coordinates, using the same difference as  */
-  /* given by `ref'.                                               */
-
-  static void
-  af_iup_shift( AF_Point  p1,
-                AF_Point  p2,
-                AF_Point  ref )
-  {
-    AF_Point  p;
-    FT_Pos    delta = ref->u - ref->v;
-
-
-    if ( delta == 0 )
-      return;
-
-    for ( p = p1; p < ref; p++ )
-      p->u = p->v + delta;
-
-    for ( p = ref + 1; p <= p2; p++ )
-      p->u = p->v + delta;
-  }
-
-
-  /* Interpolate the original coordinates of all points between `p1' and  */
-  /* `p2' to get hinted coordinates, using `ref1' and `ref2' as the       */
-  /* reference points.  The `u' and `v' members are the current and       */
-  /* original coordinate values, respectively.                            */
-  /*                                                                      */
-  /* Details can be found in the TrueType bytecode specification.         */
-
-  static void
-  af_iup_interp( AF_Point  p1,
-                 AF_Point  p2,
-                 AF_Point  ref1,
-                 AF_Point  ref2 )
-  {
-    AF_Point  p;
-    FT_Pos    u;
-    FT_Pos    v1 = ref1->v;
-    FT_Pos    v2 = ref2->v;
-    FT_Pos    d1 = ref1->u - v1;
-    FT_Pos    d2 = ref2->u - v2;
-
-
-    if ( p1 > p2 )
-      return;
-
-    if ( v1 == v2 )
-    {
-      for ( p = p1; p <= p2; p++ )
-      {
-        u = p->v;
-
-        if ( u <= v1 )
-          u += d1;
-        else
-          u += d2;
-
-        p->u = u;
-      }
-      return;
-    }
-
-    if ( v1 < v2 )
-    {
-      for ( p = p1; p <= p2; p++ )
-      {
-        u = p->v;
-
-        if ( u <= v1 )
-          u += d1;
-        else if ( u >= v2 )
-          u += d2;
-        else
-          u = ref1->u + FT_MulDiv( u - v1, ref2->u - ref1->u, v2 - v1 );
-
-        p->u = u;
-      }
-    }
-    else
-    {
-      for ( p = p1; p <= p2; p++ )
-      {
-        u = p->v;
-
-        if ( u <= v2 )
-          u += d2;
-        else if ( u >= v1 )
-          u += d1;
-        else
-          u = ref1->u + FT_MulDiv( u - v1, ref2->u - ref1->u, v2 - v1 );
-
-        p->u = u;
-      }
-    }
-  }
-
-
-  /* Hint the weak points -- this is equivalent to the TrueType `IUP' */
-  /* hinting instruction.                                             */
-
-  FT_LOCAL_DEF( void )
-  af_glyph_hints_align_weak_points( AF_GlyphHints  hints,
-                                    AF_Dimension   dim )
-  {
-    AF_Point   points        = hints->points;
-    AF_Point   point_limit   = points + hints->num_points;
-    AF_Point*  contour       = hints->contours;
-    AF_Point*  contour_limit = contour + hints->num_contours;
-    AF_Flags   touch_flag;
-    AF_Point   point;
-    AF_Point   end_point;
-    AF_Point   first_point;
-
-
-    /* PASS 1: Move segment points to edge positions */
-
-    if ( dim == AF_DIMENSION_HORZ )
-    {
-      touch_flag = AF_FLAG_TOUCH_X;
-
-      for ( point = points; point < point_limit; point++ )
-      {
-        point->u = point->x;
-        point->v = point->ox;
-      }
-    }
-    else
-    {
-      touch_flag = AF_FLAG_TOUCH_Y;
-
-      for ( point = points; point < point_limit; point++ )
-      {
-        point->u = point->y;
-        point->v = point->oy;
-      }
-    }
-
-    point = points;
-
-    for ( ; contour < contour_limit; contour++ )
-    {
-      AF_Point  first_touched, last_touched;
-
-
-      point       = *contour;
-      end_point   = point->prev;
-      first_point = point;
-
-      /* find first touched point */
-      for (;;)
-      {
-        if ( point > end_point )  /* no touched point in contour */
-          goto NextContour;
-
-        if ( point->flags & touch_flag )
-          break;
-
-        point++;
-      }
-
-      first_touched = point;
-      last_touched  = point;
-
-      for (;;)
-      {
-        FT_ASSERT( point <= end_point                 &&
-                   ( point->flags & touch_flag ) != 0 );
-
-        /* skip any touched neighbours */
-        while ( point < end_point                    &&
-                ( point[1].flags & touch_flag ) != 0 )
-          point++;
-
-        last_touched = point;
-
-        /* find the next touched point, if any */
-        point++;
-        for (;;)
-        {
-          if ( point > end_point )
-            goto EndContour;
-
-          if ( ( point->flags & touch_flag ) != 0 )
-            break;
-
-          point++;
-        }
-
-        /* interpolate between last_touched and point */
-        af_iup_interp( last_touched + 1, point - 1,
-                       last_touched, point );
-      }
-
-    EndContour:
-      /* special case: only one point was touched */
-      if ( last_touched == first_touched )
-        af_iup_shift( first_point, end_point, first_touched );
-
-      else /* interpolate the last part */
-      {
-        if ( last_touched < end_point )
-          af_iup_interp( last_touched + 1, end_point,
-                         last_touched, first_touched );
-
-        if ( first_touched > points )
-          af_iup_interp( first_point, first_touched - 1,
-                         last_touched, first_touched );
-      }
-
-    NextContour:
-      ;
-    }
-
-    /* now save the interpolated values back to x/y */
-    if ( dim == AF_DIMENSION_HORZ )
-    {
-      for ( point = points; point < point_limit; point++ )
-        point->x = point->u;
-    }
-    else
-    {
-      for ( point = points; point < point_limit; point++ )
-        point->y = point->u;
-    }
-  }
-
-
-#ifdef AF_CONFIG_OPTION_USE_WARPER
-
-  /* Apply (small) warp scale and warp delta for given dimension. */
-
-  FT_LOCAL_DEF( void )
-  af_glyph_hints_scale_dim( AF_GlyphHints  hints,
-                            AF_Dimension   dim,
-                            FT_Fixed       scale,
-                            FT_Pos         delta )
-  {
-    AF_Point  points       = hints->points;
-    AF_Point  points_limit = points + hints->num_points;
-    AF_Point  point;
-
-
-    if ( dim == AF_DIMENSION_HORZ )
-    {
-      for ( point = points; point < points_limit; point++ )
-        point->x = FT_MulFix( point->fx, scale ) + delta;
-    }
-    else
-    {
-      for ( point = points; point < points_limit; point++ )
-        point->y = FT_MulFix( point->fy, scale ) + delta;
-    }
-  }
-
-#endif /* AF_CONFIG_OPTION_USE_WARPER */
-
-/* END */