shithub: freetype+ttf2subf

Download patch

ref: 0bdf608f3d79e7b45983b88a7733426c06eb5f49
parent: 26fb1bcd05afc1d61ad80cd7313aa5a88713e78b
author: Werner Lemberg <[email protected]>
date: Wed May 28 18:42:41 EDT 2003

* src/pshinter/pshalgo1.[ch], src/pshinter/pshalgo2.[ch]: Removed.
* src/pshinter/pshalgo.h: Removed.

* src/pshinter/pshalgo3.[ch]: Renamed to...
* src/pshinter/pshalgo.[ch]: New files.
s/PSH3/PSH/.
s/psh3/psh/.
s/ps3/ps/.

* src/pshinter/pshrec.c, src/pshinter/pshinter.c: Updated.
* src/pshinter/rules.mk, src/pshinter/Jamfile: Updated

* src/pshinter/pshglob.[ch] (psh_dimension_snap_width): Commented
out.

* tests/gview.c: Remove code for pshalgo1 and pshalgo2.
Updated.

git/fs: mount .git/fs: mount/attach disallowed
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,23 @@
+2003-05-29  Werner Lemberg  <[email protected]>
+
+	* src/pshinter/pshalgo1.[ch], src/pshinter/pshalgo2.[ch]: Removed.
+	* src/pshinter/pshalgo.h: Removed.
+
+	* src/pshinter/pshalgo3.[ch]: Renamed to...
+	* src/pshinter/pshalgo.[ch]: New files.
+	s/PSH3/PSH/.
+	s/psh3/psh/.
+	s/ps3/ps/.
+
+	* src/pshinter/pshrec.c, src/pshinter/pshinter.c: Updated.
+	* src/pshinter/rules.mk, src/pshinter/Jamfile: Updated
+
+	* src/pshinter/pshglob.[ch] (psh_dimension_snap_width): Commented
+	out.
+
+	* tests/gview.c: Remove code for pshalgo1 and pshalgo2.
+	Updated.
+
 2003-05-28  Martin Zinser  <[email protected]>
 
 	* vms_make.com: Reworked support for shareable images on VMS.  The
--- a/src/base/ftglyph.c
+++ b/src/base/ftglyph.c
@@ -254,13 +254,13 @@
 
     /* copy it */
     FT_MEM_COPY( target->points, source->points,
-              source->n_points * sizeof ( FT_Vector ) );
+                 source->n_points * sizeof ( FT_Vector ) );
 
     FT_MEM_COPY( target->tags, source->tags,
-              source->n_points * sizeof ( FT_Byte ) );
+                 source->n_points * sizeof ( FT_Byte ) );
 
     FT_MEM_COPY( target->contours, source->contours,
-              source->n_contours * sizeof ( FT_Short ) );
+                 source->n_contours * sizeof ( FT_Short ) );
 
     /* copy all flags, except the `FT_OUTLINE_OWNER' one */
     target->flags = source->flags | FT_OUTLINE_OWNER;
--- a/src/base/ftsynth.c
+++ b/src/base/ftsynth.c
@@ -82,14 +82,14 @@
 
     /* we need to compute the `previous' and `next' point */
     /* for these extrema.                                 */
-    cur   = outline->points + n;
-    prev  = cur - 1;
-    next  = cur + 1;
+    cur  = outline->points + n;
+    prev = cur - 1;
+    next = cur + 1;
 
     first = 0;
     for ( c = 0; c < outline->n_contours; c++ )
     {
-      last  = outline->contours[c];
+      last = outline->contours[c];
 
       if ( n == first )
         prev = outline->points + last;
--- a/src/pshinter/Jamfile
+++ b/src/pshinter/Jamfile
@@ -8,7 +8,7 @@
 
   if $(FT2_MULTI)
   {
-    _sources = pshrec pshglob pshalgo1 pshalgo2 pshalgo3 pshmod ;
+    _sources = pshrec pshglob pshalgo pshmod ;
   }
   else
   {
--- /dev/null
+++ b/src/pshinter/pshalgo.c
@@ -1,0 +1,1997 @@
+/***************************************************************************/
+/*                                                                         */
+/*  pshalgo.c                                                              */
+/*                                                                         */
+/*    PostScript hinting algorithm 3 (body).                               */
+/*                                                                         */
+/*  Copyright 2001, 2002, 2003 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 <ft2build.h>
+#include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_DEBUG_H
+#include "pshalgo.h"
+
+
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_pshalgo2
+
+
+#ifdef DEBUG_HINTER
+  PSH_Hint_Table  ps_debug_hint_table = 0;
+  PSH_HintFunc    ps_debug_hint_func  = 0;
+  PSH_Glyph       ps_debug_glyph      = 0;
+#endif
+
+
+#define  COMPUTE_INFLEXS  /* compute inflection points to optimize "S" and others */
+#define  STRONGER         /* slightly increase the contrast of smooth hinting */
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                  BASIC HINTS RECORDINGS                       *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  /* return true iff two stem hints overlap */
+  static FT_Int
+  psh_hint_overlap( PSH_Hint  hint1,
+                    PSH_Hint  hint2 )
+  {
+    return ( hint1->org_pos + hint1->org_len >= hint2->org_pos &&
+             hint2->org_pos + hint2->org_len >= hint1->org_pos );
+  }
+
+
+  /* destroy hints table */
+  static void
+  psh_hint_table_done( PSH_Hint_Table  table,
+                       FT_Memory       memory )
+  {
+    FT_FREE( table->zones );
+    table->num_zones = 0;
+    table->zone      = 0;
+
+    FT_FREE( table->sort );
+    FT_FREE( table->hints );
+    table->num_hints   = 0;
+    table->max_hints   = 0;
+    table->sort_global = 0;
+  }
+
+
+  /* deactivate all hints in a table */
+  static void
+  psh_hint_table_deactivate( PSH_Hint_Table  table )
+  {
+    FT_UInt   count = table->max_hints;
+    PSH_Hint  hint  = table->hints;
+
+
+    for ( ; count > 0; count--, hint++ )
+    {
+      psh_hint_deactivate( hint );
+      hint->order = -1;
+    }
+  }
+
+
+  /* internal function used to record a new hint */
+  static void
+  psh_hint_table_record( PSH_Hint_Table  table,
+                         FT_UInt         idx )
+  {
+    PSH_Hint  hint = table->hints + idx;
+
+
+    if ( idx >= table->max_hints )
+    {
+      FT_ERROR(( "psh_hint_table_record: invalid hint index %d\n", idx ));
+      return;
+    }
+
+    /* ignore active hints */
+    if ( psh_hint_is_active( hint ) )
+      return;
+
+    psh_hint_activate( hint );
+
+    /* now scan the current active hint set in order to determine */
+    /* if we are overlapping with another segment                 */
+    {
+      PSH_Hint*  sorted = table->sort_global;
+      FT_UInt    count  = table->num_hints;
+      PSH_Hint   hint2;
+
+
+      hint->parent = 0;
+      for ( ; count > 0; count--, sorted++ )
+      {
+        hint2 = sorted[0];
+
+        if ( psh_hint_overlap( hint, hint2 ) )
+        {
+          hint->parent = hint2;
+          break;
+        }
+      }
+    }
+
+    if ( table->num_hints < table->max_hints )
+      table->sort_global[table->num_hints++] = hint;
+    else
+      FT_ERROR(( "psh_hint_table_record: too many sorted hints!  BUG!\n" ));
+  }
+
+
+  static void
+  psh_hint_table_record_mask( PSH_Hint_Table  table,
+                              PS_Mask         hint_mask )
+  {
+    FT_Int    mask = 0, val = 0;
+    FT_Byte*  cursor = hint_mask->bytes;
+    FT_UInt   idx, limit;
+
+
+    limit = hint_mask->num_bits;
+
+    for ( idx = 0; idx < limit; idx++ )
+    {
+      if ( mask == 0 )
+      {
+        val  = *cursor++;
+        mask = 0x80;
+      }
+
+      if ( val & mask )
+        psh_hint_table_record( table, idx );
+
+      mask >>= 1;
+    }
+  }
+
+
+  /* create hints table */
+  static FT_Error
+  psh_hint_table_init( PSH_Hint_Table  table,
+                       PS_Hint_Table   hints,
+                       PS_Mask_Table   hint_masks,
+                       PS_Mask_Table   counter_masks,
+                       FT_Memory       memory )
+  {
+    FT_UInt   count = hints->num_hints;
+    FT_Error  error;
+
+    FT_UNUSED( counter_masks );
+
+
+    /* allocate our tables */
+    if ( FT_NEW_ARRAY( table->sort,  2 * count     ) ||
+         FT_NEW_ARRAY( table->hints,     count     ) ||
+         FT_NEW_ARRAY( table->zones, 2 * count + 1 ) )
+      goto Exit;
+
+    table->max_hints   = count;
+    table->sort_global = table->sort + count;
+    table->num_hints   = 0;
+    table->num_zones   = 0;
+    table->zone        = 0;
+
+    /* now, initialize the "hints" array */
+    {
+      PSH_Hint  write = table->hints;
+      PS_Hint   read  = hints->hints;
+
+
+      for ( ; count > 0; count--, write++, read++ )
+      {
+        write->org_pos = read->pos;
+        write->org_len = read->len;
+        write->flags   = read->flags;
+      }
+    }
+
+    /* we now need to determine the initial "parent" stems; first  */
+    /* activate the hints that are given by the initial hint masks */
+    if ( hint_masks )
+    {
+      FT_UInt  Count = hint_masks->num_masks;
+      PS_Mask  Mask  = hint_masks->masks;
+
+
+      table->hint_masks = hint_masks;
+
+      for ( ; Count > 0; Count--, Mask++ )
+        psh_hint_table_record_mask( table, Mask );
+    }
+
+    /* now, do a linear parse in case some hints were left alone */
+    if ( table->num_hints != table->max_hints )
+    {
+      FT_UInt  Index, Count;
+
+
+      FT_ERROR(( "psh_hint_table_init: missing/incorrect hint masks!\n" ));
+      Count = table->max_hints;
+      for ( Index = 0; Index < Count; Index++ )
+        psh_hint_table_record( table, Index );
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  static void
+  psh_hint_table_activate_mask( PSH_Hint_Table  table,
+                                PS_Mask         hint_mask )
+  {
+    FT_Int    mask = 0, val = 0;
+    FT_Byte*  cursor = hint_mask->bytes;
+    FT_UInt   idx, limit, count;
+
+
+    limit = hint_mask->num_bits;
+    count = 0;
+
+    psh_hint_table_deactivate( table );
+
+    for ( idx = 0; idx < limit; idx++ )
+    {
+      if ( mask == 0 )
+      {
+        val  = *cursor++;
+        mask = 0x80;
+      }
+
+      if ( val & mask )
+      {
+        PSH_Hint  hint = &table->hints[idx];
+
+
+        if ( !psh_hint_is_active( hint ) )
+        {
+          FT_UInt     count2;
+
+#if 0
+          PSH_Hint*  sort = table->sort;
+          PSH_Hint   hint2;
+
+
+          for ( count2 = count; count2 > 0; count2--, sort++ )
+          {
+            hint2 = sort[0];
+            if ( psh_hint_overlap( hint, hint2 ) )
+              FT_ERROR(( "psh_hint_table_activate_mask:"
+                         " found overlapping hints\n" ))
+          }
+#else
+          count2 = 0;
+#endif
+
+          if ( count2 == 0 )
+          {
+            psh_hint_activate( hint );
+            if ( count < table->max_hints )
+              table->sort[count++] = hint;
+            else
+              FT_ERROR(( "psh_hint_tableactivate_mask:"
+                         " too many active hints\n" ));
+          }
+        }
+      }
+
+      mask >>= 1;
+    }
+    table->num_hints = count;
+
+    /* now, sort the hints; they are guaranteed to not overlap */
+    /* so we can compare their "org_pos" field directly        */
+    {
+      FT_Int     i1, i2;
+      PSH_Hint   hint1, hint2;
+      PSH_Hint*  sort = table->sort;
+
+
+      /* a simple bubble sort will do, since in 99% of cases, the hints */
+      /* will be already sorted -- and the sort will be linear          */
+      for ( i1 = 1; i1 < (FT_Int)count; i1++ )
+      {
+        hint1 = sort[i1];
+        for ( i2 = i1 - 1; i2 >= 0; i2-- )
+        {
+          hint2 = sort[i2];
+
+          if ( hint2->org_pos < hint1->org_pos )
+            break;
+
+          sort[i2 + 1] = hint2;
+          sort[i2]     = hint1;
+        }
+      }
+    }
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****               HINTS GRID-FITTING AND OPTIMIZATION             *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+#if 1
+  static FT_Pos
+  psh_dimension_quantize_len( PSH_Dimension  dim,
+                              FT_Pos         len,
+                              FT_Bool        do_snapping )
+  {
+    if ( len <= 64 )
+      len = 64;
+    else
+    {
+      FT_Pos  delta = len - dim->stdw.widths[0].cur;
+
+
+      if ( delta < 0 )
+        delta = -delta;
+
+      if ( delta < 40 )
+      {
+        len = dim->stdw.widths[0].cur;
+        if ( len < 48 )
+          len = 48;
+      }
+
+      if ( len < 3 * 64 )
+      {
+        delta = ( len & 63 );
+        len  &= -64;
+
+        if ( delta < 10 )
+          len += delta;
+
+        else if ( delta < 32 )
+          len += 10;
+
+        else if ( delta < 54 )
+          len += 54;
+
+        else
+          len += delta;
+      }
+      else
+        len = ( len + 32 ) & -64;
+    }
+
+    if ( do_snapping )
+      len = ( len + 32 ) & -64;
+
+    return  len;
+  }
+#endif /* 0 */
+
+
+#ifdef DEBUG_HINTER
+
+  static void
+  ps_simple_scale( PSH_Hint_Table  table,
+                   FT_Fixed        scale,
+                   FT_Fixed        delta,
+                   FT_Int          dimension )
+  {
+    PSH_Hint  hint;
+    FT_UInt   count;
+
+
+    for ( count = 0; count < table->max_hints; count++ )
+    {
+      hint = table->hints + count;
+
+      hint->cur_pos = FT_MulFix( hint->org_pos, scale ) + delta;
+      hint->cur_len = FT_MulFix( hint->org_len, scale );
+
+      if ( ps_debug_hint_func )
+        ps_debug_hint_func( hint, dimension );
+    }
+  }
+
+#endif /* DEBUG_HINTER */
+
+
+  static FT_Fixed
+  psh_hint_snap_stem_side_delta( FT_Fixed  pos,
+                                 FT_Fixed  len )
+  {
+    FT_Fixed  delta1 = ( ( pos + 32 ) & -64 ) - pos;
+    FT_Fixed  delta2 = ( ( pos + len + 32 ) & -64  ) - pos - len;
+
+
+    if ( ABS( delta1 ) <= ABS( delta2 ) )
+      return delta1;
+    else
+      return delta2;
+  }
+
+
+  static void
+  psh_hint_align( PSH_Hint     hint,
+                  PSH_Globals  globals,
+                  FT_Int       dimension,
+                  PSH_Glyph    glyph )
+  {
+    PSH_Dimension  dim   = &globals->dimension[dimension];
+    FT_Fixed       scale = dim->scale_mult;
+    FT_Fixed       delta = dim->scale_delta;
+
+
+    if ( !psh_hint_is_fitted( hint ) )
+    {
+      FT_Pos  pos = FT_MulFix( hint->org_pos, scale ) + delta;
+      FT_Pos  len = FT_MulFix( hint->org_len, scale );
+
+      FT_Int            do_snapping;
+      FT_Pos            fit_len;
+      PSH_AlignmentRec  align;
+
+
+      /* ignore stem alignments when requested through the hint flags */
+      if ( ( dimension == 0 && !glyph->do_horz_hints ) ||
+           ( dimension == 1 && !glyph->do_vert_hints ) )
+      {
+        hint->cur_pos = pos;
+        hint->cur_len = len;
+
+        psh_hint_set_fitted( hint );
+        return;
+      }
+
+      /* perform stem snapping when requested - this is necessary
+       * for monochrome and LCD hinting modes only
+       */
+      do_snapping = ( dimension == 0 && glyph->do_horz_snapping ) ||
+                    ( dimension == 1 && glyph->do_vert_snapping );
+
+      hint->cur_len = fit_len = len;
+
+      /* check blue zones for horizontal stems */
+      align.align     = PSH_BLUE_ALIGN_NONE;
+      align.align_bot = align.align_top = 0;
+
+      if ( dimension == 1 )
+        psh_blues_snap_stem( &globals->blues,
+                             hint->org_pos + hint->org_len,
+                             hint->org_pos,
+                             &align );
+
+      switch ( align.align )
+      {
+      case PSH_BLUE_ALIGN_TOP:
+        /* the top of the stem is aligned against a blue zone */
+        hint->cur_pos = align.align_top - fit_len;
+        break;
+
+      case PSH_BLUE_ALIGN_BOT:
+        /* the bottom of the stem is aligned against a blue zone */
+        hint->cur_pos = align.align_bot;
+        break;
+
+      case PSH_BLUE_ALIGN_TOP | PSH_BLUE_ALIGN_BOT:
+        /* both edges of the stem are aligned against blue zones */
+        hint->cur_pos = align.align_bot;
+        hint->cur_len = align.align_top - align.align_bot;
+        break;
+
+      default:
+        {
+          PSH_Hint  parent = hint->parent;
+
+
+          if ( parent )
+          {
+            FT_Pos  par_org_center, par_cur_center;
+            FT_Pos  cur_org_center, cur_delta;
+
+
+            /* ensure that parent is already fitted */
+            if ( !psh_hint_is_fitted( parent ) )
+              psh_hint_align( parent, globals, dimension, glyph );
+
+            par_org_center = parent->org_pos + ( parent->org_len >> 1 );
+            par_cur_center = parent->cur_pos + ( parent->cur_len >> 1 );
+            cur_org_center = hint->org_pos   + ( hint->org_len   >> 1 );
+
+            cur_delta = FT_MulFix( cur_org_center - par_org_center, scale );
+            pos       = par_cur_center + cur_delta - ( len >> 1 );
+          }
+
+          hint->cur_pos = pos;
+          hint->cur_len = fit_len;
+
+          /* Stem adjustment tries to snap stem widths to standard
+           * ones.  This is important to prevent unpleasant rounding
+           * artefacts.
+           */
+          if ( glyph->do_stem_adjust )
+          {
+            if ( len <= 64 )
+            {
+              /* the stem is less than one pixel; we will center it
+               * around the nearest pixel center
+               */
+#if 1
+              pos = ( pos + ( len >> 1 ) ) & -64;
+#else
+             /* this seems to be a bug! */
+              pos = ( pos + ( ( len >> 1 ) & -64 ) );
+#endif
+              len = 64;
+            }
+            else
+            {
+              len = psh_dimension_quantize_len( dim, len, 0 );
+            }
+          }
+
+          /* now that we have a good hinted stem width, try to position */
+          /* the stem along a pixel grid integer coordinate             */
+          hint->cur_pos = pos + psh_hint_snap_stem_side_delta( pos, len );
+          hint->cur_len = len;
+        }
+      }
+
+      if ( do_snapping )
+      {
+        pos = hint->cur_pos;
+        len = hint->cur_len;
+
+        if ( len < 64 )
+          len = 64;
+        else
+          len = ( len + 32 ) & -64;
+
+        switch ( align.align )
+        {
+          case PSH_BLUE_ALIGN_TOP:
+            hint->cur_pos = align.align_top - len;
+            hint->cur_len = len;
+            break;
+
+          case PSH_BLUE_ALIGN_BOT:
+            hint->cur_len = len;
+            break;
+
+          case PSH_BLUE_ALIGN_BOT | PSH_BLUE_ALIGN_TOP:
+            /* don't touch */
+            break;
+
+
+          default:
+            hint->cur_len = len;
+            if ( len & 64 )
+              pos = ( ( pos + ( len >> 1 ) ) & -64 ) + 32;
+            else
+              pos = ( pos + ( len >> 1 ) + 32 ) & -64;
+
+            hint->cur_pos = pos - ( len >> 1 );
+            hint->cur_len = len;
+        }
+      }
+
+      psh_hint_set_fitted( hint );
+
+#ifdef DEBUG_HINTER
+      if ( ps_debug_hint_func )
+        ps_debug_hint_func( hint, dimension );
+#endif
+    }
+  }
+
+
+#if 0  /* not used for now, experimental */
+
+ /*
+  *  A variant to perform "light" hinting (i.e. FT_RENDER_MODE_LIGHT)
+  *  of stems
+  */
+  static void
+  psh_hint_align_light( PSH_Hint     hint,
+                        PSH_Globals  globals,
+                        FT_Int       dimension,
+                        PSH_Glyph    glyph )
+  {
+    PSH_Dimension  dim   = &globals->dimension[dimension];
+    FT_Fixed       scale = dim->scale_mult;
+    FT_Fixed       delta = dim->scale_delta;
+
+
+    if ( !psh_hint_is_fitted( hint ) )
+    {
+      FT_Pos  pos = FT_MulFix( hint->org_pos, scale ) + delta;
+      FT_Pos  len = FT_MulFix( hint->org_len, scale );
+
+      FT_Pos  fit_len;
+
+      PSH_AlignmentRec  align;
+
+
+      /* ignore stem alignments when requested through the hint flags */
+      if ( ( dimension == 0 && !glyph->do_horz_hints ) ||
+           ( dimension == 1 && !glyph->do_vert_hints ) )
+      {
+        hint->cur_pos = pos;
+        hint->cur_len = len;
+
+        psh_hint_set_fitted( hint );
+        return;
+      }
+
+      fit_len = len;
+
+      hint->cur_len = fit_len;
+
+      /* check blue zones for horizontal stems */
+      align.align = PSH_BLUE_ALIGN_NONE;
+      align.align_bot = align.align_top = 0;
+
+      if ( dimension == 1 )
+        psh_blues_snap_stem( &globals->blues,
+                             hint->org_pos + hint->org_len,
+                             hint->org_pos,
+                             &align );
+
+      switch ( align.align )
+      {
+      case PSH_BLUE_ALIGN_TOP:
+        /* the top of the stem is aligned against a blue zone */
+        hint->cur_pos = align.align_top - fit_len;
+        break;
+
+      case PSH_BLUE_ALIGN_BOT:
+        /* the bottom of the stem is aligned against a blue zone */
+        hint->cur_pos = align.align_bot;
+        break;
+
+      case PSH_BLUE_ALIGN_TOP | PSH_BLUE_ALIGN_BOT:
+        /* both edges of the stem are aligned against blue zones */
+        hint->cur_pos = align.align_bot;
+        hint->cur_len = align.align_top - align.align_bot;
+        break;
+
+      default:
+        {
+          PSH_Hint  parent = hint->parent;
+
+
+          if ( parent )
+          {
+            FT_Pos  par_org_center, par_cur_center;
+            FT_Pos  cur_org_center, cur_delta;
+
+
+            /* ensure that parent is already fitted */
+            if ( !psh_hint_is_fitted( parent ) )
+              psh_hint_align_light( parent, globals, dimension, glyph );
+
+            par_org_center = parent->org_pos + ( parent->org_len / 2 );
+            par_cur_center = parent->cur_pos + ( parent->cur_len / 2 );
+            cur_org_center = hint->org_pos   + ( hint->org_len   / 2 );
+
+            cur_delta = FT_MulFix( cur_org_center - par_org_center, scale );
+            pos       = par_cur_center + cur_delta - ( len >> 1 );
+          }
+
+          /* Stems less than one pixel wide are easy -- we want to
+           * make them as dark as possible, so they must fall within
+           * one pixel.  If the stem is split between two pixels
+           * then snap the edge that is nearer to the pixel boundary
+           * to the pixel boundary.
+           */
+          if ( len <= 64 )
+          {
+            if ( ( pos + len + 63 ) / 64  != pos / 64 + 1 )
+              pos += psh_hint_snap_stem_side_delta ( pos, len );
+          }
+
+          /* Position stems other to minimize the amount of mid-grays.
+           * There are, in general, two positions that do this,
+           * illustrated as A) and B) below.
+           *
+           *   +                   +                   +                   +
+           *
+           * A)             |--------------------------------|
+           * B)   |--------------------------------|
+           * C)       |--------------------------------|
+           *
+           * Position A) (split the excess stem equally) should be better
+           * for stems of width N + f where f < 0.5.
+           *
+           * Position B) (split the deficiency equally) should be better
+           * for stems of width N + f where f > 0.5.
+           *
+           * It turns out though that minimizing the total number of lit
+           * pixels is also important, so position C), with one edge
+           * aligned with a pixel boundary is actually preferable
+           * to A).  There are also more possibile positions for C) than
+           * for A) or B), so it involves less distortion of the overall
+           * character shape.
+           */
+          else /* len > 64 */
+          {
+            FT_Fixed  frac_len = len & 63;
+            FT_Fixed  center = pos + ( len >> 1 );
+            FT_Fixed  delta_a, delta_b;
+
+
+            if ( ( len / 64 ) & 1 )
+            {
+              delta_a = ( center & -64 ) + 32 - center;
+              delta_b = ( ( center + 32 ) & - 64 ) - center;
+            }
+            else
+            {
+              delta_a = ( ( center + 32 ) & - 64 ) - center;
+              delta_b = ( center & -64 ) + 32 - center;
+            }
+
+            /* We choose between B) and C) above based on the amount
+             * of fractinal stem width; for small amounts, choose
+             * C) always, for large amounts, B) always, and inbetween,
+             * pick whichever one involves less stem movement.
+             */
+            if ( frac_len < 32 )
+            {
+              pos += psh_hint_snap_stem_side_delta ( pos, len );
+            }
+            else if ( frac_len < 48 )
+            {
+              FT_Fixed  side_delta = psh_hint_snap_stem_side_delta ( pos,
+                                                                     len );
+
+
+              if ( ABS( side_delta ) < ABS( delta_b ) )
+                pos += side_delta;
+              else
+                pos += delta_b;
+            }
+            else
+            {
+              pos += delta_b;
+            }
+          }
+
+          hint->cur_pos = pos;
+        }
+      }  /* switch */
+
+      psh_hint_set_fitted( hint );
+
+#ifdef DEBUG_HINTER
+      if ( ps_debug_hint_func )
+        ps_debug_hint_func( hint, dimension );
+#endif
+    }
+  }
+
+#endif /* 0 */
+
+
+  static void
+  psh_hint_table_align_hints( PSH_Hint_Table  table,
+                              PSH_Globals     globals,
+                              FT_Int          dimension,
+                              PSH_Glyph       glyph )
+  {
+    PSH_Hint       hint;
+    FT_UInt        count;
+
+#ifdef DEBUG_HINTER
+
+    PSH_Dimension  dim   = &globals->dimension[dimension];
+    FT_Fixed       scale = dim->scale_mult;
+    FT_Fixed       delta = dim->scale_delta;
+
+
+    if ( ps_debug_no_vert_hints && dimension == 0 )
+    {
+      ps_simple_scale( table, scale, delta, dimension );
+      return;
+    }
+
+    if ( ps_debug_no_horz_hints && dimension == 1 )
+    {
+      ps_simple_scale( table, scale, delta, dimension );
+      return;
+    }
+
+#endif /* DEBUG_HINTER*/
+
+    hint  = table->hints;
+    count = table->max_hints;
+
+    for ( ; count > 0; count--, hint++ )
+      psh_hint_align( hint, globals, dimension, glyph );
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                POINTS INTERPOLATION ROUTINES                  *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+#define PSH_ZONE_MIN  -3200000L
+#define PSH_ZONE_MAX  +3200000L
+
+#define xxDEBUG_ZONES
+
+
+#ifdef DEBUG_ZONES
+
+#include <stdio.h>
+
+  static void
+  psh_print_zone( PSH_Zone  zone )
+  {
+    printf( "zone [scale,delta,min,max] = [%.3f,%.3f,%d,%d]\n",
+             zone->scale / 65536.0,
+             zone->delta / 64.0,
+             zone->min,
+             zone->max );
+  }
+
+#else
+
+#define psh_print_zone( x )  do { } while ( 0 )
+
+#endif /* DEBUG_ZONES */
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                    HINTER GLYPH MANAGEMENT                    *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+#ifdef COMPUTE_INFLEXS
+
+  /* compute all inflex points in a given glyph */
+  static void
+  psh_glyph_compute_inflections( PSH_Glyph  glyph )
+  {
+    FT_UInt  n;
+
+
+    for ( n = 0; n < glyph->num_contours; n++ )
+    {
+      PSH_Point  first, start, end, before, after;
+      FT_Angle   angle_in, angle_seg, angle_out;
+      FT_Angle   diff_in, diff_out;
+      FT_Int     finished = 0;
+
+
+      /* we need at least 4 points to create an inflection point */
+      if ( glyph->contours[n].count < 4 )
+        continue;
+
+      /* compute first segment in contour */
+      first = glyph->contours[n].start;
+
+      start = end = first;
+      do
+      {
+        end = end->next;
+        if ( end == first )
+          goto Skip;
+
+      } while ( PSH_POINT_EQUAL_ORG( end, first ) );
+
+      angle_seg = PSH_POINT_ANGLE( start, end );
+
+      /* extend the segment start whenever possible */
+      before = start;
+      do
+      {
+        do
+        {
+          start  = before;
+          before = before->prev;
+          if ( before == first )
+            goto Skip;
+
+        } while ( PSH_POINT_EQUAL_ORG( before, start ) );
+
+        angle_in = PSH_POINT_ANGLE( before, start );
+
+      } while ( angle_in == angle_seg );
+
+      first   = start;
+      diff_in = FT_Angle_Diff( angle_in, angle_seg );
+
+      /* now, process all segments in the contour */
+      do
+      {
+        /* first, extend current segment's end whenever possible */
+        after = end;
+        do
+        {
+          do
+          {
+            end   = after;
+            after = after->next;
+            if ( after == first )
+              finished = 1;
+
+          } while ( PSH_POINT_EQUAL_ORG( end, after ) );
+
+          angle_out = PSH_POINT_ANGLE( end, after );
+
+        } while ( angle_out == angle_seg );
+
+        diff_out = FT_Angle_Diff( angle_seg, angle_out );
+
+        if ( ( diff_in ^ diff_out ) < 0 )
+        {
+          /* diff_in and diff_out have different signs, we have */
+          /* inflection points here...                          */
+
+          do
+          {
+            psh_point_set_inflex( start );
+            start = start->next;
+          }
+          while ( start != end );
+
+          psh_point_set_inflex( start );
+        }
+
+        start     = end;
+        end       = after;
+        angle_seg = angle_out;
+        diff_in   = diff_out;
+
+      } while ( !finished );
+
+    Skip:
+      ;
+    }
+  }
+
+#endif /* COMPUTE_INFLEXS */
+
+
+  static void
+  psh_glyph_done( PSH_Glyph  glyph )
+  {
+    FT_Memory  memory = glyph->memory;
+
+
+    psh_hint_table_done( &glyph->hint_tables[1], memory );
+    psh_hint_table_done( &glyph->hint_tables[0], memory );
+
+    FT_FREE( glyph->points );
+    FT_FREE( glyph->contours );
+
+    glyph->num_points   = 0;
+    glyph->num_contours = 0;
+
+    glyph->memory = 0;
+  }
+
+
+  static int
+  psh_compute_dir( FT_Pos  dx,
+                   FT_Pos  dy )
+  {
+    FT_Pos  ax, ay;
+    int     result = PSH_DIR_NONE;
+
+
+    ax = ( dx >= 0 ) ? dx : -dx;
+    ay = ( dy >= 0 ) ? dy : -dy;
+
+    if ( ay * 12 < ax )
+    {
+      /* |dy| <<< |dx|  means a near-horizontal segment */
+      result = ( dx >= 0 ) ? PSH_DIR_RIGHT : PSH_DIR_LEFT;
+    }
+    else if ( ax * 12 < ay )
+    {
+      /* |dx| <<< |dy|  means a near-vertical segment */
+      result = ( dy >= 0 ) ? PSH_DIR_UP : PSH_DIR_DOWN;
+    }
+
+    return result;
+  }
+
+
+  /* load outline point coordinates into hinter glyph */
+  static void
+  psh_glyph_load_points( PSH_Glyph  glyph,
+                         FT_Int     dimension )
+  {
+    FT_Vector*  vec   = glyph->outline->points;
+    PSH_Point   point = glyph->points;
+    FT_UInt     count = glyph->num_points;
+
+
+    for ( ; count > 0; count--, point++, vec++ )
+    {
+      point->flags2 = 0;
+      point->hint   = NULL;
+      if ( dimension == 0 )
+      {
+        point->org_u = vec->x;
+        point->org_v = vec->y;
+      }
+      else
+      {
+        point->org_u = vec->y;
+        point->org_v = vec->x;
+      }
+
+#ifdef DEBUG_HINTER
+      point->org_x = vec->x;
+      point->org_y = vec->y;
+#endif
+
+    }
+  }
+
+
+  /* save hinted point coordinates back to outline */
+  static void
+  psh_glyph_save_points( PSH_Glyph  glyph,
+                         FT_Int     dimension )
+  {
+    FT_UInt     n;
+    PSH_Point   point = glyph->points;
+    FT_Vector*  vec   = glyph->outline->points;
+    char*       tags  = glyph->outline->tags;
+
+
+    for ( n = 0; n < glyph->num_points; n++ )
+    {
+      if ( dimension == 0 )
+        vec[n].x = point->cur_u;
+      else
+        vec[n].y = point->cur_u;
+
+      if ( psh_point_is_strong( point ) )
+        tags[n] |= (char)( ( dimension == 0 ) ? 32 : 64 );
+
+#ifdef DEBUG_HINTER
+
+      if ( dimension == 0 )
+      {
+        point->cur_x   = point->cur_u;
+        point->flags_x = point->flags2 | point->flags;
+      }
+      else
+      {
+        point->cur_y   = point->cur_u;
+        point->flags_y = point->flags2 | point->flags;
+      }
+
+#endif
+
+      point++;
+    }
+  }
+
+
+  static FT_Error
+  psh_glyph_init( PSH_Glyph    glyph,
+                  FT_Outline*  outline,
+                  PS_Hints     ps_hints,
+                  PSH_Globals  globals )
+  {
+    FT_Error   error;
+    FT_Memory  memory;
+
+
+    /* clear all fields */
+    FT_MEM_ZERO( glyph, sizeof ( *glyph ) );
+
+    memory = globals->memory;
+
+    /* allocate and setup points + contours arrays */
+    if ( FT_NEW_ARRAY( glyph->points,   outline->n_points   ) ||
+         FT_NEW_ARRAY( glyph->contours, outline->n_contours ) )
+      goto Exit;
+
+    glyph->num_points   = outline->n_points;
+    glyph->num_contours = outline->n_contours;
+
+    {
+      FT_UInt      first = 0, next, n;
+      PSH_Point    points  = glyph->points;
+      PSH_Contour  contour = glyph->contours;
+
+
+      for ( n = 0; n < glyph->num_contours; n++ )
+      {
+        FT_Int     count;
+        PSH_Point  point;
+
+
+        next  = outline->contours[n] + 1;
+        count = next - first;
+
+        contour->start = points + first;
+        contour->count = (FT_UInt)count;
+
+        if ( count > 0 )
+        {
+          point = points + first;
+
+          point->prev    = points + next - 1;
+          point->contour = contour;
+
+          for ( ; count > 1; count-- )
+          {
+            point[0].next = point + 1;
+            point[1].prev = point;
+            point++;
+            point->contour = contour;
+          }
+          point->next = points + first;
+        }
+
+        contour++;
+        first = next;
+      }
+    }
+
+    {
+      PSH_Point   points = glyph->points;
+      PSH_Point   point  = points;
+      FT_Vector*  vec    = outline->points;
+      FT_UInt     n;
+
+
+      for ( n = 0; n < glyph->num_points; n++, point++ )
+      {
+        FT_Int  n_prev = point->prev - points;
+        FT_Int  n_next = point->next - points;
+        FT_Pos  dxi, dyi, dxo, dyo;
+
+
+        if ( !( outline->tags[n] & FT_CURVE_TAG_ON ) )
+          point->flags = PSH_POINT_OFF;
+
+        dxi = vec[n].x - vec[n_prev].x;
+        dyi = vec[n].y - vec[n_prev].y;
+
+        point->dir_in = (FT_Char)psh_compute_dir( dxi, dyi );
+
+        dxo = vec[n_next].x - vec[n].x;
+        dyo = vec[n_next].y - vec[n].y;
+
+        point->dir_out = (FT_Char)psh_compute_dir( dxo, dyo );
+
+        /* detect smooth points */
+        if ( point->flags & PSH_POINT_OFF )
+          point->flags |= PSH_POINT_SMOOTH;
+        else if ( point->dir_in  != PSH_DIR_NONE ||
+                  point->dir_out != PSH_DIR_NONE )
+        {
+          if ( point->dir_in == point->dir_out )
+            point->flags |= PSH_POINT_SMOOTH;
+        }
+        else
+        {
+          FT_Angle  angle_in, angle_out, diff;
+
+
+          angle_in  = FT_Atan2( dxi, dyi );
+          angle_out = FT_Atan2( dxo, dyo );
+
+          diff = angle_in - angle_out;
+          if ( diff < 0 )
+            diff = -diff;
+
+          if ( diff > FT_ANGLE_PI )
+            diff = FT_ANGLE_2PI - diff;
+
+          if ( diff < FT_ANGLE_PI / 16 )
+            point->flags |= PSH_POINT_SMOOTH;
+        }
+      }
+    }
+
+    glyph->memory  = memory;
+    glyph->outline = outline;
+    glyph->globals = globals;
+
+#ifdef COMPUTE_INFLEXS
+    psh_glyph_load_points( glyph, 0 );
+    psh_glyph_compute_inflections( glyph );
+#endif /* COMPUTE_INFLEXS */
+
+    /* now deal with hints tables */
+    error = psh_hint_table_init( &glyph->hint_tables [0],
+                                 &ps_hints->dimension[0].hints,
+                                 &ps_hints->dimension[0].masks,
+                                 &ps_hints->dimension[0].counters,
+                                 memory );
+    if ( error )
+      goto Exit;
+
+    error = psh_hint_table_init( &glyph->hint_tables [1],
+                                 &ps_hints->dimension[1].hints,
+                                 &ps_hints->dimension[1].masks,
+                                 &ps_hints->dimension[1].counters,
+                                 memory );
+    if ( error )
+      goto Exit;
+
+  Exit:
+    return error;
+  }
+
+
+  /* compute all extrema in a glyph for a given dimension */
+  static void
+  psh_glyph_compute_extrema( PSH_Glyph  glyph )
+  {
+    FT_UInt  n;
+
+
+    /* first of all, compute all local extrema */
+    for ( n = 0; n < glyph->num_contours; n++ )
+    {
+      PSH_Point  first = glyph->contours[n].start;
+      PSH_Point  point, before, after;
+
+
+      if ( glyph->contours[n].count == 0 )
+        continue;
+
+      point  = first;
+      before = point;
+      after  = point;
+
+      do
+      {
+        before = before->prev;
+        if ( before == first )
+          goto Skip;
+
+      } while ( before->org_u == point->org_u );
+
+      first = point = before->next;
+
+      for (;;)
+      {
+        after = point;
+        do
+        {
+          after = after->next;
+          if ( after == first )
+            goto Next;
+
+        } while ( after->org_u == point->org_u );
+
+        if ( before->org_u < point->org_u )
+        {
+          if ( after->org_u < point->org_u )
+          {
+            /* local maximum */
+            goto Extremum;
+          }
+        }
+        else /* before->org_u > point->org_u */
+        {
+          if ( after->org_u > point->org_u )
+          {
+            /* local minimum */
+          Extremum:
+            do
+            {
+              psh_point_set_extremum( point );
+              point = point->next;
+
+            } while ( point != after );
+          }
+        }
+
+        before = after->prev;
+        point  = after;
+
+      } /* for  */
+
+    Next:
+      ;
+    }
+
+    /* for each extrema, determine its direction along the */
+    /* orthogonal axis                                     */
+    for ( n = 0; n < glyph->num_points; n++ )
+    {
+      PSH_Point  point, before, after;
+
+
+      point  = &glyph->points[n];
+      before = point;
+      after  = point;
+
+      if ( psh_point_is_extremum( point ) )
+      {
+        do
+        {
+          before = before->prev;
+          if ( before == point )
+            goto Skip;
+
+        } while ( before->org_v == point->org_v );
+
+        do
+        {
+          after = after->next;
+          if ( after == point )
+            goto Skip;
+
+        } while ( after->org_v == point->org_v );
+      }
+
+      if ( before->org_v < point->org_v &&
+           after->org_v  > point->org_v )
+      {
+        psh_point_set_positive( point );
+      }
+      else if ( before->org_v > point->org_v &&
+                after->org_v  < point->org_v )
+      {
+        psh_point_set_negative( point );
+      }
+
+    Skip:
+      ;
+    }
+  }
+
+
+#define PSH_STRONG_THRESHOLD  30
+
+
+  /* major_dir is the direction for points on the bottom/left of the stem; */
+  /* Points on the top/right of the stem will have a direction of          */
+  /* -major_dir.                                                           */
+
+  static void
+  psh_hint_table_find_strong_point( PSH_Hint_Table  table,
+                                    PSH_Point       point,
+                                    FT_Int          major_dir )
+  {
+    PSH_Hint*  sort      = table->sort;
+    FT_UInt    num_hints = table->num_hints;
+    FT_Int     point_dir = 0;
+
+
+    if ( PSH_DIR_COMPARE( point->dir_in, major_dir ) )
+      point_dir = point->dir_in;
+
+    else if ( PSH_DIR_COMPARE( point->dir_out, major_dir ) )
+      point_dir = point->dir_out;
+
+    if ( point_dir )
+    {
+      FT_UInt  flag;
+
+
+      for ( ; num_hints > 0; num_hints--, sort++ )
+      {
+        PSH_Hint  hint = sort[0];
+        FT_Pos    d;
+
+
+        if ( point_dir == major_dir )
+        {
+          flag = PSH_POINT_EDGE_MIN;
+          d    = point->org_u - hint->org_pos;
+
+          if ( ABS( d ) < PSH_STRONG_THRESHOLD )
+          {
+          Is_Strong:
+            psh_point_set_strong( point );
+            point->flags2 |= flag;
+            point->hint    = hint;
+            break;
+          }
+        }
+        else if ( point_dir == -major_dir )
+        {
+          flag = PSH_POINT_EDGE_MAX;
+          d    = point->org_u - hint->org_pos - hint->org_len;
+
+          if ( ABS( d ) < PSH_STRONG_THRESHOLD )
+            goto Is_Strong;
+        }
+      }
+    }
+
+#if 1
+    else if ( psh_point_is_extremum( point ) )
+    {
+      /* treat extrema as special cases for stem edge alignment */
+      FT_UInt  min_flag, max_flag;
+
+
+      if ( major_dir == PSH_DIR_HORIZONTAL )
+      {
+        min_flag = PSH_POINT_POSITIVE;
+        max_flag = PSH_POINT_NEGATIVE;
+      }
+      else
+      {
+        min_flag = PSH_POINT_NEGATIVE;
+        max_flag = PSH_POINT_POSITIVE;
+      }
+
+      for ( ; num_hints > 0; num_hints--, sort++ )
+      {
+        PSH_Hint  hint = sort[0];
+        FT_Pos    d, flag;
+
+
+        if ( point->flags2 & min_flag )
+        {
+          flag = PSH_POINT_EDGE_MIN;
+          d    = point->org_u - hint->org_pos;
+
+          if ( ABS( d ) < PSH_STRONG_THRESHOLD )
+          {
+          Is_Strong2:
+            point->flags2 |= flag;
+            point->hint    = hint;
+            psh_point_set_strong( point );
+            break;
+          }
+        }
+        else if ( point->flags2 & max_flag )
+        {
+          flag = PSH_POINT_EDGE_MAX;
+          d    = point->org_u - hint->org_pos - hint->org_len;
+
+          if ( ABS( d ) < PSH_STRONG_THRESHOLD )
+            goto Is_Strong2;
+        }
+
+        if ( point->org_u >= hint->org_pos                 &&
+             point->org_u <= hint->org_pos + hint->org_len )
+        {
+          point->hint = hint;
+        }
+      }
+    }
+
+#endif /* 1 */
+  }
+
+
+  /* find strong points in a glyph */
+  static void
+  psh_glyph_find_strong_points( PSH_Glyph  glyph,
+                                FT_Int     dimension )
+  {
+    /* a point is strong if it is located on a stem                   */
+    /* edge and has an "in" or "out" tangent to the hint's direction  */
+    {
+      PSH_Hint_Table  table     = &glyph->hint_tables[dimension];
+      PS_Mask         mask      = table->hint_masks->masks;
+      FT_UInt         num_masks = table->hint_masks->num_masks;
+      FT_UInt         first     = 0;
+      FT_Int          major_dir = dimension == 0 ? PSH_DIR_VERTICAL
+                                                 : PSH_DIR_HORIZONTAL;
+
+
+      /* process secondary hints to "selected" points */
+      if ( num_masks > 1 && glyph->num_points > 0 )
+      {
+        first = mask->end_point;
+        mask++;
+        for ( ; num_masks > 1; num_masks--, mask++ )
+        {
+          FT_UInt  next;
+          FT_Int   count;
+
+
+          next  = mask->end_point;
+          count = next - first;
+          if ( count > 0 )
+          {
+            PSH_Point  point = glyph->points + first;
+
+
+            psh_hint_table_activate_mask( table, mask );
+
+            for ( ; count > 0; count--, point++ )
+              psh_hint_table_find_strong_point( table, point, major_dir );
+          }
+          first = next;
+        }
+      }
+
+      /* process primary hints for all points */
+      if ( num_masks == 1 )
+      {
+        FT_UInt    count = glyph->num_points;
+        PSH_Point  point = glyph->points;
+
+
+        psh_hint_table_activate_mask( table, table->hint_masks->masks );
+        for ( ; count > 0; count--, point++ )
+        {
+          if ( !psh_point_is_strong( point ) )
+            psh_hint_table_find_strong_point( table, point, major_dir );
+        }
+      }
+
+      /* now, certain points may have been attached to hint and */
+      /* not marked as strong; update their flags then          */
+      {
+        FT_UInt    count = glyph->num_points;
+        PSH_Point  point = glyph->points;
+
+
+        for ( ; count > 0; count--, point++ )
+          if ( point->hint && !psh_point_is_strong( point ) )
+            psh_point_set_strong( point );
+      }
+    }
+  }
+
+
+  /* interpolate strong points with the help of hinted coordinates */
+  static void
+  psh_glyph_interpolate_strong_points( PSH_Glyph  glyph,
+                                       FT_Int     dimension )
+  {
+    PSH_Dimension  dim   = &glyph->globals->dimension[dimension];
+    FT_Fixed       scale = dim->scale_mult;
+
+
+    {
+      FT_UInt    count = glyph->num_points;
+      PSH_Point  point = glyph->points;
+
+
+      for ( ; count > 0; count--, point++ )
+      {
+        PSH_Hint  hint = point->hint;
+
+
+        if ( hint )
+        {
+          FT_Pos  delta;
+
+
+          if ( psh_point_is_edge_min( point ) )
+          {
+            point->cur_u = hint->cur_pos;
+          }
+          else if ( psh_point_is_edge_max( point ) )
+          {
+            point->cur_u = hint->cur_pos + hint->cur_len;
+          }
+          else
+          {
+            delta = point->org_u - hint->org_pos;
+
+            if ( delta <= 0 )
+              point->cur_u = hint->cur_pos + FT_MulFix( delta, scale );
+
+            else if ( delta >= hint->org_len )
+              point->cur_u = hint->cur_pos + hint->cur_len +
+                               FT_MulFix( delta - hint->org_len, scale );
+
+            else if ( hint->org_len > 0 )
+              point->cur_u = hint->cur_pos +
+                               FT_MulDiv( delta, hint->cur_len,
+                                          hint->org_len );
+            else
+              point->cur_u = hint->cur_pos;
+          }
+          psh_point_set_fitted( point );
+        }
+      }
+    }
+  }
+
+
+  static void
+  psh_glyph_interpolate_normal_points( PSH_Glyph  glyph,
+                                       FT_Int     dimension )
+  {
+
+#if 1
+
+    PSH_Dimension  dim   = &glyph->globals->dimension[dimension];
+    FT_Fixed       scale = dim->scale_mult;
+
+
+    /* first technique: a point is strong if it is a local extrema */
+    {
+      FT_UInt    count = glyph->num_points;
+      PSH_Point  point = glyph->points;
+
+
+      for ( ; count > 0; count--, point++ )
+      {
+        if ( psh_point_is_strong( point ) )
+          continue;
+
+        /* sometimes, some local extremas are smooth points */
+        if ( psh_point_is_smooth( point ) )
+        {
+          if ( point->dir_in == PSH_DIR_NONE   ||
+               point->dir_in != point->dir_out )
+            continue;
+
+          if ( !psh_point_is_extremum( point )   &&
+               !psh_point_is_inflex( point ) )
+            continue;
+
+          point->flags &= ~PSH_POINT_SMOOTH;
+        }
+
+        /* find best enclosing point coordinates */
+        {
+          PSH_Point  before = 0;
+          PSH_Point  after  = 0;
+
+          FT_Pos     diff_before = -32000;
+          FT_Pos     diff_after  =  32000;
+          FT_Pos     u = point->org_u;
+
+          FT_Int     count2 = glyph->num_points;
+          PSH_Point  cur    = glyph->points;
+
+
+          for ( ; count2 > 0; count2--, cur++ )
+          {
+            if ( psh_point_is_strong( cur ) )
+            {
+              FT_Pos  diff = cur->org_u - u;;
+
+
+              if ( diff <= 0 )
+              {
+                if ( diff > diff_before )
+                {
+                  diff_before = diff;
+                  before      = cur;
+                }
+              }
+              else if ( diff >= 0 )
+              {
+                if ( diff < diff_after )
+                {
+                  diff_after = diff;
+                  after      = cur;
+                }
+              }
+            }
+          }
+
+          if ( !before )
+          {
+            if ( !after )
+              continue;
+
+            /* we are before the first strong point coordinate; */
+            /* simply translate the point                       */
+            point->cur_u = after->cur_u +
+                           FT_MulFix( point->org_u - after->org_u, scale );
+          }
+          else if ( !after )
+          {
+            /* we are after the last strong point coordinate; */
+            /* simply translate the point                     */
+            point->cur_u = before->cur_u +
+                           FT_MulFix( point->org_u - before->org_u, scale );
+          }
+          else
+          {
+            if ( diff_before == 0 )
+              point->cur_u = before->cur_u;
+
+            else if ( diff_after == 0 )
+              point->cur_u = after->cur_u;
+
+            else
+              point->cur_u = before->cur_u +
+                             FT_MulDiv( u - before->org_u,
+                                        after->cur_u - before->cur_u,
+                                        after->org_u - before->org_u );
+          }
+
+          psh_point_set_fitted( point );
+        }
+      }
+    }
+
+#endif /* 1 */
+
+  }
+
+
+  /* interpolate other points */
+  static void
+  psh_glyph_interpolate_other_points( PSH_Glyph  glyph,
+                                      FT_Int     dimension )
+  {
+    PSH_Dimension  dim          = &glyph->globals->dimension[dimension];
+    FT_Fixed       scale        = dim->scale_mult;
+    FT_Fixed       delta        = dim->scale_delta;
+    PSH_Contour    contour      = glyph->contours;
+    FT_UInt        num_contours = glyph->num_contours;
+
+
+    for ( ; num_contours > 0; num_contours--, contour++ )
+    {
+      PSH_Point  start = contour->start;
+      PSH_Point  first, next, point;
+      FT_UInt    fit_count;
+
+
+      /* count the number of strong points in this contour */
+      next      = start + contour->count;
+      fit_count = 0;
+      first     = 0;
+
+      for ( point = start; point < next; point++ )
+        if ( psh_point_is_fitted( point ) )
+        {
+          if ( !first )
+            first = point;
+
+          fit_count++;
+        }
+
+      /* if there are less than 2 fitted points in the contour, we */
+      /* simply scale and eventually translate the contour points  */
+      if ( fit_count < 2 )
+      {
+        if ( fit_count == 1 )
+          delta = first->cur_u - FT_MulFix( first->org_u, scale );
+
+        for ( point = start; point < next; point++ )
+          if ( point != first )
+            point->cur_u = FT_MulFix( point->org_u, scale ) + delta;
+
+        goto Next_Contour;
+      }
+
+      /* there are more than 2 strong points in this contour; we */
+      /* need to interpolate weak points between them            */
+      start = first;
+      do
+      {
+        point = first;
+
+        /* skip consecutive fitted points */
+        for (;;)
+        {
+          next = first->next;
+          if ( next == start )
+            goto Next_Contour;
+
+          if ( !psh_point_is_fitted( next ) )
+            break;
+
+          first = next;
+        }
+
+        /* find next fitted point after unfitted one */
+        for (;;)
+        {
+          next = next->next;
+          if ( psh_point_is_fitted( next ) )
+            break;
+        }
+
+        /* now interpolate between them */
+        {
+          FT_Pos    org_a, org_ab, cur_a, cur_ab;
+          FT_Pos    org_c, org_ac, cur_c;
+          FT_Fixed  scale_ab;
+
+
+          if ( first->org_u <= next->org_u )
+          {
+            org_a  = first->org_u;
+            cur_a  = first->cur_u;
+            org_ab = next->org_u - org_a;
+            cur_ab = next->cur_u - cur_a;
+          }
+          else
+          {
+            org_a  = next->org_u;
+            cur_a  = next->cur_u;
+            org_ab = first->org_u - org_a;
+            cur_ab = first->cur_u - cur_a;
+          }
+
+          scale_ab = 0x10000L;
+          if ( org_ab > 0 )
+            scale_ab = FT_DivFix( cur_ab, org_ab );
+
+          point = first->next;
+          do
+          {
+            org_c  = point->org_u;
+            org_ac = org_c - org_a;
+
+            if ( org_ac <= 0 )
+            {
+              /* on the left of the interpolation zone */
+              cur_c = cur_a + FT_MulFix( org_ac, scale );
+            }
+            else if ( org_ac >= org_ab )
+            {
+              /* on the right on the interpolation zone */
+              cur_c = cur_a + cur_ab + FT_MulFix( org_ac - org_ab, scale );
+            }
+            else
+            {
+              /* within the interpolation zone */
+              cur_c = cur_a + FT_MulFix( org_ac, scale_ab );
+            }
+
+            point->cur_u = cur_c;
+
+            point = point->next;
+
+          } while ( point != next );
+        }
+
+        /* keep going until all points in the contours have been processed */
+        first = next;
+
+      } while ( first != start );
+
+    Next_Contour:
+      ;
+    }
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                     HIGH-LEVEL INTERFACE                      *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  FT_Error
+  ps_hints_apply( PS_Hints        ps_hints,
+                  FT_Outline*     outline,
+                  PSH_Globals     globals,
+                  FT_Render_Mode  hint_mode )
+  {
+    PSH_GlyphRec  glyphrec;
+    PSH_Glyph     glyph = &glyphrec;
+    FT_Error      error;
+#ifdef DEBUG_HINTER
+    FT_Memory     memory;
+#endif
+    FT_Int        dimension;
+
+
+    /* something to do? */
+    if ( outline->n_points == 0 || outline->n_contours == 0 )
+      return FT_Err_Ok;
+
+#ifdef DEBUG_HINTER
+
+    memory = globals->memory;
+
+    if ( ps_debug_glyph )
+    {
+      psh_glyph_done( ps_debug_glyph );
+      FT_FREE( ps_debug_glyph );
+    }
+
+    if ( FT_NEW( glyph ) )
+      return error;
+
+    ps_debug_glyph = glyph;
+
+#endif /* DEBUG_HINTER */
+
+    error = psh_glyph_init( glyph, outline, ps_hints, globals );
+    if ( error )
+      goto Exit;
+
+    /* try to optimize the y_scale so that the top of non-capital letters
+     * is aligned on a pixel boundary whenever possible
+     */
+    {
+      PSH_Dimension  dim_x = &glyph->globals->dimension[0];
+      PSH_Dimension  dim_y = &glyph->globals->dimension[1];
+
+      FT_Fixed x_scale = dim_x->scale_mult;
+      FT_Fixed y_scale = dim_y->scale_mult;
+
+      FT_Fixed scaled;
+      FT_Fixed fitted;
+
+
+      scaled = FT_MulFix( globals->blues.normal_top.zones->org_ref, y_scale );
+      fitted = ( scaled + 32 ) & -64;
+
+      if (scaled != fitted ) {
+        y_scale = FT_MulDiv( y_scale, fitted, scaled );
+
+        if ( fitted < scaled )
+          x_scale -= x_scale / 50;
+
+        psh_globals_set_scale( glyph->globals, x_scale, y_scale, 0, 0 );
+      }
+    }
+
+    glyph->do_horz_hints = 1;
+    glyph->do_vert_hints = 1;
+
+    glyph->do_horz_snapping = FT_BOOL( hint_mode == FT_RENDER_MODE_MONO ||
+                                       hint_mode == FT_RENDER_MODE_LCD  );
+
+    glyph->do_vert_snapping = FT_BOOL( hint_mode == FT_RENDER_MODE_MONO  ||
+                                       hint_mode == FT_RENDER_MODE_LCD_V );
+
+    glyph->do_stem_adjust   = FT_BOOL( hint_mode != FT_RENDER_MODE_LIGHT );
+
+    for ( dimension = 0; dimension < 2; dimension++ )
+    {
+      /* load outline coordinates into glyph */
+      psh_glyph_load_points( glyph, dimension );
+
+      /* compute local extrema */
+      psh_glyph_compute_extrema( glyph );
+
+      /* compute aligned stem/hints positions */
+      psh_hint_table_align_hints( &glyph->hint_tables[dimension],
+                                  glyph->globals,
+                                  dimension,
+                                  glyph );
+
+      /* find strong points, align them, then interpolate others */
+      psh_glyph_find_strong_points( glyph, dimension );
+      psh_glyph_interpolate_strong_points( glyph, dimension );
+      psh_glyph_interpolate_normal_points( glyph, dimension );
+      psh_glyph_interpolate_other_points( glyph, dimension );
+
+      /* save hinted coordinates back to outline */
+      psh_glyph_save_points( glyph, dimension );
+    }
+
+  Exit:
+
+#ifndef DEBUG_HINTER
+    psh_glyph_done( glyph );
+#endif
+
+    return error;
+  }
+
+
+/* END */
--- a/src/pshinter/pshalgo.h
+++ b/src/pshinter/pshalgo.h
@@ -2,13 +2,13 @@
 /*                                                                         */
 /*  pshalgo.h                                                              */
 /*                                                                         */
-/*    This header file defines the used hinting algorithm.                 */
+/*    PostScript hinting algorithm (specification).                        */
 /*                                                                         */
-/*  Copyright 2001 by                                                      */
+/*  Copyright 2001, 2002, 2003 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       */
+/*  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.                                        */
@@ -19,33 +19,235 @@
 #ifndef __PSHALGO_H__
 #define __PSHALGO_H__
 
+
+#include "pshrec.h"
+#include "pshglob.h"
+#include FT_TRIGONOMETRY_H
+
+
 FT_BEGIN_HEADER
 
-/* define to choose hinting algorithm */
-#define PSH_ALGORITHM_3
 
-#if defined(PSH_ALGORITHM_1)
+  /* handle to Hint structure */
+  typedef struct PSH_HintRec_*  PSH_Hint;
 
-#  include "pshalgo1.h"
-#  define PS_HINTS_APPLY_FUNC  ps1_hints_apply
+  /* hint bit-flags */
+  typedef enum
+  {
+    PSH_HINT_GHOST  = PS_HINT_FLAG_GHOST,
+    PSH_HINT_BOTTOM = PS_HINT_FLAG_BOTTOM,
+    PSH_HINT_ACTIVE = 4,
+    PSH_HINT_FITTED = 8
 
-#elif defined(PSH_ALGORITHM_2)
+  } PSH_Hint_Flags;
 
-#  include "pshalgo2.h"
-#  define PS_HINTS_APPLY_FUNC  ps2_hints_apply
 
-#elif defined(PSH_ALGORITHM_3)
+#define psh_hint_is_active( x )  ( ( (x)->flags & PSH_HINT_ACTIVE ) != 0 )
+#define psh_hint_is_ghost( x )   ( ( (x)->flags & PSH_HINT_GHOST  ) != 0 )
+#define psh_hint_is_fitted( x )  ( ( (x)->flags & PSH_HINT_FITTED ) != 0 )
 
-#  include "pshalgo3.h"
-#  define PS_HINTS_APPLY_FUNC  ps3_hints_apply
+#define psh_hint_activate( x )    (x)->flags |=  PSH_HINT_ACTIVE
+#define psh_hint_deactivate( x )  (x)->flags &= ~PSH_HINT_ACTIVE
+#define psh_hint_set_fitted( x )  (x)->flags |=  PSH_HINT_FITTED
 
-#else
+  /* hint structure */
+  typedef struct  PSH_HintRec_
+  {
+    FT_Int    org_pos;
+    FT_Int    org_len;
+    FT_Pos    cur_pos;
+    FT_Pos    cur_len;
+    FT_UInt   flags;
+    PSH_Hint  parent;
+    FT_Int    order;
 
-#  error "invalid Postscript Hinter algorithm selection"
+  } PSH_HintRec;
 
+
+  /* this is an interpolation zone used for strong points;  */
+  /* weak points are interpolated according to their strong */
+  /* neighbours                                             */
+  typedef struct  PSH_ZoneRec_
+  {
+    FT_Fixed  scale;
+    FT_Fixed  delta;
+    FT_Pos    min;
+    FT_Pos    max;
+
+  } PSH_ZoneRec, *PSH_Zone;
+
+
+  typedef struct  PSH_Hint_TableRec_
+  {
+    FT_UInt        max_hints;
+    FT_UInt        num_hints;
+    PSH_Hint       hints;
+    PSH_Hint*      sort;
+    PSH_Hint*      sort_global;
+    FT_UInt        num_zones;
+    PSH_ZoneRec*   zones;
+    PSH_Zone       zone;
+    PS_Mask_Table  hint_masks;
+    PS_Mask_Table  counter_masks;
+
+  } PSH_Hint_TableRec, *PSH_Hint_Table;
+
+
+  typedef struct PSH_PointRec_*    PSH_Point;
+  typedef struct PSH_ContourRec_*  PSH_Contour;
+
+  enum
+  {
+    PSH_DIR_NONE  =  4,
+    PSH_DIR_UP    = -1,
+    PSH_DIR_DOWN  =  1,
+    PSH_DIR_LEFT  = -2,
+    PSH_DIR_RIGHT =  2
+  };
+
+#define PSH_DIR_HORIZONTAL  2
+#define PSH_DIR_VERTICAL    1
+
+#define PSH_DIR_COMPARE( d1, d2 )   ( (d1) == (d2) || (d1) == -(d2) )
+#define PSH_DIR_IS_HORIZONTAL( d )  PSH_DIR_COMPARE( d, PSH_DIR_HORIZONTAL )
+#define PSH_DIR_IS_VERTICAL( d )    PSH_DIR_COMPARE( d, PSH_DIR_VERTICAL )
+
+
+ /* the following bit-flags are computed once by the glyph */
+ /* analyzer, for both dimensions                          */
+  enum
+  {
+    PSH_POINT_OFF    = 1,   /* point is off the curve */
+    PSH_POINT_SMOOTH = 2,   /* point is smooth        */
+    PSH_POINT_INFLEX = 4    /* point is inflection    */
+  };
+
+#define psh_point_is_smooth( p )  ( (p)->flags & PSH_POINT_SMOOTH )
+#define psh_point_is_off( p )     ( (p)->flags & PSH_POINT_OFF    )
+#define psh_point_is_inflex( p )  ( (p)->flags & PSH_POINT_INFLEX )
+
+#define psh_point_set_smooth( p )  (p)->flags |= PSH_POINT_SMOOTH
+#define psh_point_set_off( p )     (p)->flags |= PSH_POINT_OFF
+#define psh_point_set_inflex( p )  (p)->flags |= PSH_POINT_INFLEX
+
+  /* the following bit-flags are re-computed for each dimension */
+  enum
+  {
+    PSH_POINT_STRONG   = 16,   /* point is strong                           */
+    PSH_POINT_FITTED   = 32,   /* point is already fitted                   */
+    PSH_POINT_EXTREMUM = 64,   /* point is local extremum                   */
+    PSH_POINT_POSITIVE = 128,  /* extremum has positive contour flow        */
+    PSH_POINT_NEGATIVE = 256,  /* extremum has negative contour flow        */
+    PSH_POINT_EDGE_MIN = 512,  /* point is aligned to left/bottom stem edge */
+    PSH_POINT_EDGE_MAX = 1024  /* point is aligned to top/right stem edge   */
+  };
+
+#define psh_point_is_strong( p )    ( (p)->flags2 & PSH_POINT_STRONG )
+#define psh_point_is_fitted( p )    ( (p)->flags2 & PSH_POINT_FITTED )
+#define psh_point_is_extremum( p )  ( (p)->flags2 & PSH_POINT_EXTREMUM )
+#define psh_point_is_positive( p )  ( (p)->flags2 & PSH_POINT_POSITIVE )
+#define psh_point_is_negative( p )  ( (p)->flags2 & PSH_POINT_NEGATIVE )
+#define psh_point_is_edge_min( p )  ( (p)->flags2 & PSH_POINT_EDGE_MIN )
+#define psh_point_is_edge_max( p )  ( (p)->flags2 & PSH_POINT_EDGE_MAX )
+
+#define psh_point_set_strong( p )    (p)->flags2 |= PSH_POINT_STRONG
+#define psh_point_set_fitted( p )    (p)->flags2 |= PSH_POINT_FITTED
+#define psh_point_set_extremum( p )  (p)->flags2 |= PSH_POINT_EXTREMUM
+#define psh_point_set_positive( p )  (p)->flags2 |= PSH_POINT_POSITIVE
+#define psh_point_set_negative( p )  (p)->flags2 |= PSH_POINT_NEGATIVE
+#define psh_point_set_edge_min( p )  (p)->flags2 |= PSH_POINT_EDGE_MIN
+#define psh_point_set_edge_max( p )  (p)->flags2 |= PSH_POINT_EDGE_MAX
+
+
+  typedef struct  PSH_PointRec_
+  {
+    PSH_Point    prev;
+    PSH_Point    next;
+    PSH_Contour  contour;
+    FT_UInt      flags;
+    FT_UInt      flags2;
+    FT_Char      dir_in;
+    FT_Char      dir_out;
+    FT_Angle     angle_in;
+    FT_Angle     angle_out;
+    PSH_Hint     hint;
+    FT_Pos       org_u;
+    FT_Pos       org_v;
+    FT_Pos       cur_u;
+#ifdef DEBUG_HINTER
+    FT_Pos       org_x;
+    FT_Pos       cur_x;
+    FT_Pos       org_y;
+    FT_Pos       cur_y;
+    FT_UInt      flags_x;
+    FT_UInt      flags_y;
 #endif
 
+  } PSH_PointRec;
+
+
+#define PSH_POINT_EQUAL_ORG( a, b )  ( (a)->org_u == (b)->org_u && \
+                                       (a)->org_v == (b)->org_v )
+
+#define PSH_POINT_ANGLE( a, b )  FT_Atan2( (b)->org_u - (a)->org_u,  \
+                                           (b)->org_v - (a)->org_v )
+
+  typedef struct  PSH_ContourRec_
+  {
+    PSH_Point  start;
+    FT_UInt    count;
+
+  } PSH_ContourRec;
+
+
+  typedef struct  PSH_GlyphRec_
+  {
+    FT_UInt            num_points;
+    FT_UInt            num_contours;
+
+    PSH_Point          points;
+    PSH_Contour        contours;
+
+    FT_Memory          memory;
+    FT_Outline*        outline;
+    PSH_Globals        globals;
+    PSH_Hint_TableRec  hint_tables[2];
+
+    FT_Bool            vertical;
+    FT_Int             major_dir;
+    FT_Int             minor_dir;
+
+    FT_Bool            do_horz_hints;
+    FT_Bool            do_vert_hints;
+    FT_Bool            do_horz_snapping;
+    FT_Bool            do_vert_snapping;
+    FT_Bool            do_stem_adjust;
+
+  } PSH_GlyphRec, *PSH_Glyph;
+
+
+#ifdef DEBUG_HINTER
+  extern PSH_Hint_Table  ps_debug_hint_table;
+
+  typedef void
+  (*PSH_HintFunc)( PSH_Hint  hint,
+                   FT_Bool   vertical );
+
+  extern PSH_HintFunc    ps_debug_hint_func;
+
+  extern PSH_Glyph       ps_debug_glyph;
+#endif
+
+
+  extern FT_Error
+  ps_hints_apply( PS_Hints        ps_hints,
+                  FT_Outline*     outline,
+                  PSH_Globals     globals,
+                  FT_Render_Mode  hint_mode );
+
+
 FT_END_HEADER
+
 
 #endif /* __PSHALGO_H__ */
 
--- a/src/pshinter/pshalgo1.c
+++ /dev/null
@@ -1,785 +1,0 @@
-/***************************************************************************/
-/*                                                                         */
-/*  pshalgo1.c                                                             */
-/*                                                                         */
-/*    PostScript hinting algorithm 1 (body).                               */
-/*                                                                         */
-/*  Copyright 2001, 2002 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 <ft2build.h>
-#include FT_INTERNAL_OBJECTS_H
-#include FT_INTERNAL_DEBUG_H
-#include "pshalgo1.h"
-
-#undef  FT_COMPONENT
-#define FT_COMPONENT  trace_pshalgo1
-
-#ifdef DEBUG_HINTER
-  PSH1_Hint_Table  ps1_debug_hint_table = 0;
-  PSH1_HintFunc    ps1_debug_hint_func  = 0;
-#endif
-
-
- /************************************************************************/
- /************************************************************************/
- /*****                                                              *****/
- /*****                 BASIC HINTS RECORDINGS                       *****/
- /*****                                                              *****/
- /************************************************************************/
- /************************************************************************/
-
-  /* return true iff two stem hints overlap */
-  static FT_Int
-  psh1_hint_overlap( PSH1_Hint  hint1,
-                     PSH1_Hint  hint2 )
-  {
-    return ( hint1->org_pos + hint1->org_len >= hint2->org_pos &&
-             hint2->org_pos + hint2->org_len >= hint1->org_pos );
-  }
-
-
-  /* destroy hints table */
-  static void
-  psh1_hint_table_done( PSH1_Hint_Table  table,
-                        FT_Memory        memory )
-  {
-    FT_FREE( table->zones );
-    table->num_zones = 0;
-    table->zone      = 0;
-
-    FT_FREE( table->sort );
-    FT_FREE( table->hints );
-    table->num_hints   = 0;
-    table->max_hints   = 0;
-    table->sort_global = 0;
-  }
-
-
-  /* deactivate all hints in a table */
-  static void
-  psh1_hint_table_deactivate( PSH1_Hint_Table  table )
-  {
-    FT_UInt    count = table->max_hints;
-    PSH1_Hint  hint  = table->hints;
-
-
-    for ( ; count > 0; count--, hint++ )
-    {
-      psh1_hint_deactivate( hint );
-      hint->order = -1;
-    }
-  }
-
-
-  /* internal function used to record a new hint */
-  static void
-  psh1_hint_table_record( PSH1_Hint_Table  table,
-                          FT_UInt          idx )
-  {
-    PSH1_Hint  hint = table->hints + idx;
-
-
-    if ( idx >= table->max_hints )
-    {
-      FT_ERROR(( "%s.activate: invalid hint index %d\n", idx ));
-      return;
-    }
-
-    /* ignore active hints */
-    if ( psh1_hint_is_active( hint ) )
-      return;
-
-    psh1_hint_activate( hint );
-
-    /* now scan the current active hint set in order to determine */
-    /* if we are overlapping with another segment                 */
-    {
-      PSH1_Hint*  sorted = table->sort_global;
-      FT_UInt     count  = table->num_hints;
-      PSH1_Hint   hint2;
-
-
-      hint->parent = 0;
-      for ( ; count > 0; count--, sorted++ )
-      {
-        hint2 = sorted[0];
-
-        if ( psh1_hint_overlap( hint, hint2 ) )
-        {
-          hint->parent = hint2;
-          break;
-        }
-      }
-    }
-
-    if ( table->num_hints < table->max_hints )
-      table->sort_global[table->num_hints++] = hint;
-    else
-      FT_ERROR(( "%s.activate: too many sorted hints!  BUG!\n",
-                 "ps.fitter" ));
-  }
-
-
-  static void
-  psh1_hint_table_record_mask( PSH1_Hint_Table  table,
-                               PS_Mask          hint_mask )
-  {
-    FT_Int    mask = 0, val = 0;
-    FT_Byte*  cursor = hint_mask->bytes;
-    FT_UInt   idx, limit;
-
-
-    limit = hint_mask->num_bits;
-
-    if ( limit != table->max_hints )
-      FT_ERROR(( "%s.activate_mask: invalid bit count (%d instead of %d)\n",
-                 "ps.fitter", hint_mask->num_bits, table->max_hints ));
-
-    for ( idx = 0; idx < limit; idx++ )
-    {
-      if ( mask == 0 )
-      {
-        val  = *cursor++;
-        mask = 0x80;
-      }
-
-      if ( val & mask )
-        psh1_hint_table_record( table, idx );
-
-      mask >>= 1;
-    }
-  }
-
-
-  /* create hints table */
-  static FT_Error
-  psh1_hint_table_init( PSH1_Hint_Table  table,
-                        PS_Hint_Table    hints,
-                        PS_Mask_Table    hint_masks,
-                        PS_Mask_Table    counter_masks,
-                        FT_Memory        memory )
-  {
-    FT_UInt   count = hints->num_hints;
-    FT_Error  error;
-
-    FT_UNUSED( counter_masks );
-
-
-    /* allocate our tables */
-    if ( FT_NEW_ARRAY( table->sort,  2 * count     ) ||
-         FT_NEW_ARRAY( table->hints,     count     ) ||
-         FT_NEW_ARRAY( table->zones, 2 * count + 1 ) )
-      goto Exit;
-
-    table->max_hints   = count;
-    table->sort_global = table->sort + count;
-    table->num_hints   = 0;
-    table->num_zones   = 0;
-    table->zone        = 0;
-
-    /* now, initialize the "hints" array */
-    {
-      PSH1_Hint  write = table->hints;
-      PS_Hint    read  = hints->hints;
-
-
-      for ( ; count > 0; count--, write++, read++ )
-      {
-        write->org_pos = read->pos;
-        write->org_len = read->len;
-        write->flags   = read->flags;
-      }
-    }
-
-    /* we now need to determine the initial "parent" stems; first  */
-    /* activate the hints that are given by the initial hint masks */
-    if ( hint_masks )
-    {
-      FT_UInt  Count = hint_masks->num_masks;
-      PS_Mask  Mask  = hint_masks->masks;
-
-
-      table->hint_masks = hint_masks;
-
-      for ( ; Count > 0; Count--, Mask++ )
-        psh1_hint_table_record_mask( table, Mask );
-    }
-
-    /* now, do a linear parse in case some hints were left alone */
-    if ( table->num_hints != table->max_hints )
-    {
-      FT_UInt   Index, Count;
-
-
-      FT_ERROR(( "%s.init: missing/incorrect hint masks!\n" ));
-      Count = table->max_hints;
-      for ( Index = 0; Index < Count; Index++ )
-        psh1_hint_table_record( table, Index );
-    }
-
-  Exit:
-    return error;
-  }
-
-
-  static void
-  psh1_hint_table_activate_mask( PSH1_Hint_Table  table,
-                                 PS_Mask          hint_mask )
-  {
-    FT_Int    mask = 0, val = 0;
-    FT_Byte*  cursor = hint_mask->bytes;
-    FT_UInt   idx, limit, count;
-
-
-    limit = hint_mask->num_bits;
-    count = 0;
-
-    psh1_hint_table_deactivate( table );
-
-    for ( idx = 0; idx < limit; idx++ )
-    {
-      if ( mask == 0 )
-      {
-        val  = *cursor++;
-        mask = 0x80;
-      }
-
-      if ( val & mask )
-      {
-        PSH1_Hint  hint = &table->hints[idx];
-
-
-        if ( !psh1_hint_is_active( hint ) )
-        {
-          PSH1_Hint*  sort = table->sort;
-          FT_UInt     count2;
-          PSH1_Hint   hint2;
-
-
-          for ( count2 = count; count2 > 0; count2--, sort++ )
-          {
-            hint2 = sort[0];
-            if ( psh1_hint_overlap( hint, hint2 ) )
-            {
-              FT_ERROR(( "%s.activate_mask: found overlapping hints\n",
-                         "psf.hint" ));
-              break;
-            }
-          }
-
-          if ( count2 == 0 )
-          {
-            psh1_hint_activate( hint );
-            if ( count < table->max_hints )
-              table->sort[count++] = hint;
-            else
-              FT_ERROR(( "%s.activate_mask: too many active hints\n",
-                         "psf.hint" ));
-          }
-        }
-      }
-
-      mask >>= 1;
-    }
-    table->num_hints = count;
-
-    /* now, sort the hints; they are guaranteed to not overlap */
-    /* so we can compare their "org_pos" field directly        */
-    {
-      FT_Int      i1, i2;
-      PSH1_Hint   hint1, hint2;
-      PSH1_Hint*  sort = table->sort;
-
-
-      /* a simple bubble sort will do, since in 99% of cases, the hints */
-      /* will be already sorted; and the sort will be linear            */
-      for ( i1 = 1; i1 < (FT_Int)count; i1++ )
-      {
-        hint1 = sort[i1];
-
-        for ( i2 = i1 - 1; i2 >= 0; i2-- )
-        {
-          hint2 = sort[i2];
-          if ( hint2->org_pos < hint1->org_pos )
-            break;
-
-          sort[i2 + 1] = hint2;
-          sort[i2]     = hint1;
-        }
-      }
-    }
-  }
-
-
-  /*************************************************************************/
-  /*************************************************************************/
-  /*****                                                               *****/
-  /*****               HINTS GRID-FITTING AND OPTIMIZATION             *****/
-  /*****                                                               *****/
-  /*************************************************************************/
-  /*************************************************************************/
-
-#ifdef DEBUG_HINTER
-  void
-  ps_simple_scale( PSH1_Hint_Table  table,
-                   FT_Fixed         scale,
-                   FT_Fixed         delta,
-                   FT_Int           vertical )
-  {
-    PSH1_Hint  hint;
-    FT_UInt    count;
-
-
-    for ( count = 0; count < table->num_hints; count++ )
-    {
-      hint = table->sort[count];
-      if ( psh1_hint_is_active( hint ) )
-      {
-        hint->cur_pos = FT_MulFix( hint->org_pos, scale ) + delta;
-        hint->cur_len = FT_MulFix( hint->org_len, scale );
-
-        if ( ps1_debug_hint_func )
-          ps1_debug_hint_func( hint, vertical );
-      }
-    }
-  }
-#endif
-
-
-  FT_LOCAL_DEF( FT_Error )
-  psh1_hint_table_optimize( PSH1_Hint_Table  table,
-                            PSH_Globals      globals,
-                            FT_Outline*      outline,
-                            FT_Int           vertical )
-  {
-    PSH_Dimension  dim   = &globals->dimension[vertical];
-    FT_Fixed       scale = dim->scale_mult;
-    FT_Fixed       delta = dim->scale_delta;
-
-    FT_UNUSED( outline );
-
-
-#ifdef DEBUG_HINTER
-    if ( ps_debug_no_vert_hints && vertical )
-    {
-      ps_simple_scale( table, scale, delta, vertical );
-      return 0;
-    }
-
-    if ( ps_debug_no_horz_hints && !vertical )
-    {
-      ps_simple_scale( table, scale, delta, vertical );
-      return 0;
-    }
-#endif
-
-    /* XXXX: for now, we only scale the hints to test all other aspects */
-    /*       of the PostScript hinter                                   */
-    {
-      PSH1_Hint  hint;
-      FT_UInt   count;
-
-
-      for ( count = 0; count < table->num_hints; count++ )
-      {
-        hint = table->sort[count];
-        if ( psh1_hint_is_active( hint ) )
-        {
-#if 1
-          FT_Pos  pos = FT_MulFix( hint->org_pos, scale ) + delta;
-          FT_Pos  len = FT_MulFix( hint->org_len, scale );
-
-          FT_Pos  fit_center;
-          FT_Pos  fit_len;
-
-          PSH_AlignmentRec  align;
-
-
-          /* compute fitted width/height */
-          fit_len = psh_dimension_snap_width( dim, hint->org_len );
-          if ( fit_len < 64 )
-            fit_len = 64;
-          else
-            fit_len = ( fit_len + 32 ) & -64;
-
-          hint->cur_len = fit_len;
-
-          /* check blue zones for horizontal stems */
-          align.align     = PSH_BLUE_ALIGN_NONE;
-          align.align_bot = align.align_top = 0;
-          if ( !vertical )
-          {
-            psh_blues_snap_stem( &globals->blues,
-                                 hint->org_pos + hint->org_len,
-                                 hint->org_pos,
-                                 &align );
-          }
-
-          switch ( align.align )
-          {
-          case PSH_BLUE_ALIGN_TOP:
-            /* the top of the stem is aligned against a blue zone */
-            hint->cur_pos = align.align_top - fit_len;
-            break;
-
-          case PSH_BLUE_ALIGN_BOT:
-            /* the bottom of the stem is aligned against a blue zone */
-            hint->cur_pos = align.align_bot;
-            break;
-
-          case PSH_BLUE_ALIGN_TOP | PSH_BLUE_ALIGN_BOT:
-            /* both edges of the stem are aligned against blue zones */
-            hint->cur_pos = align.align_bot;
-            hint->cur_len = align.align_top - align.align_bot;
-            break;
-
-          default:
-            /* normal processing */
-            if ( ( fit_len / 64 ) & 1 )
-            {
-              /* odd number of pixels */
-              fit_center = ( ( pos + ( len >> 1 ) ) & -64 ) + 32;
-            }
-            else
-            {
-              /* even number of pixels */
-              fit_center = ( pos + ( len >> 1 ) + 32 ) & -64;
-            }
-
-            hint->cur_pos = fit_center - ( fit_len >> 1 );
-          }
-
-# else
-
-          hint->cur_pos = ( FT_MulFix( hint->org_pos, scale ) + delta + 32 )
-                          & -64;
-          hint->cur_len = FT_MulFix( hint->org_len, scale );
-
-# endif
-
-#ifdef DEBUG_HINTER
-        if ( ps1_debug_hint_func )
-          ps1_debug_hint_func( hint, vertical );
-#endif
-        }
-      }
-    }
-
-    return 0;
-  }
-
-
-  /*************************************************************************/
-  /*************************************************************************/
-  /*****                                                               *****/
-  /*****               POINTS INTERPOLATION ROUTINES                   *****/
-  /*****                                                               *****/
-  /*************************************************************************/
-  /*************************************************************************/
-
-#define PSH1_ZONE_MIN  -3200000
-#define PSH1_ZONE_MAX  +3200000
-
-#define xxDEBUG_ZONES
-
-
-#ifdef DEBUG_ZONES
-
-#include <stdio.h>
-
-  static void
-  psh1_print_zone( PSH1_Zone  zone )
-  {
-    printf( "zone [scale,delta,min,max] = [%.3f,%.3f,%d,%d]\n",
-             zone->scale / 65536.0,
-             zone->delta / 64.0,
-             zone->min,
-             zone->max );
-  }
-
-#else
-#define psh1_print_zone( x )  do { } while ( 0 )
-#endif
-
-  /* setup interpolation zones once the hints have been grid-fitted */
-  /* by the optimizer                                               */
-  static void
-  psh1_hint_table_setup_zones( PSH1_Hint_Table  table,
-                               FT_Fixed         scale,
-                               FT_Fixed         delta )
-  {
-    FT_UInt     count;
-    PSH1_Zone   zone;
-    PSH1_Hint  *sort, hint, hint2;
-
-
-    zone  = table->zones;
-
-    /* special case, no hints defined */
-    if ( table->num_hints == 0 )
-    {
-      zone->scale = scale;
-      zone->delta = delta;
-      zone->min   = PSH1_ZONE_MIN;
-      zone->max   = PSH1_ZONE_MAX;
-
-      table->num_zones = 1;
-      table->zone      = zone;
-      return;
-    }
-
-    /* the first zone is before the first hint    */
-    /* x' = (x-x0)*s + x0' = x*s + ( x0' - x0*s ) */
-
-    sort = table->sort;
-    hint = sort[0];
-
-    zone->scale = scale;
-    zone->delta = hint->cur_pos - FT_MulFix( hint->org_pos, scale );
-    zone->min   = PSH1_ZONE_MIN;
-    zone->max   = hint->org_pos;
-
-    psh1_print_zone( zone );
-
-    zone++;
-
-    for ( count = table->num_hints; count > 0; count-- )
-    {
-      FT_Fixed  scale2;
-
-
-      if ( hint->org_len > 0 )
-      {
-        /* setup a zone for inner-stem interpolation */
-        /* (x' - x0') = (x - x0)*(x1'-x0')/(x1-x0)   */
-        /* x' = x*s2 + x0' - x0*s2                   */
-
-        scale2      = FT_DivFix( hint->cur_len, hint->org_len );
-        zone->scale = scale2;
-        zone->min   = hint->org_pos;
-        zone->max   = hint->org_pos + hint->org_len;
-        zone->delta = hint->cur_pos - FT_MulFix( zone->min, scale2 );
-
-        psh1_print_zone( zone );
-
-        zone++;
-      }
-
-      if ( count == 1 )
-        break;
-
-      sort++;
-      hint2 = sort[0];
-
-      /* setup zone for inter-stem interpolation */
-      /* (x'-x1') = (x-x1)*(x2'-x1')/(x2-x1)     */
-      /* x' = x*s3 + x1' - x1*s3                 */
-
-      scale2 = FT_DivFix( hint2->cur_pos - (hint->cur_pos + hint->cur_len),
-                          hint2->org_pos - (hint->org_pos + hint->org_len) );
-      zone->scale = scale2;
-      zone->min   = hint->org_pos + hint->org_len;
-      zone->max   = hint2->org_pos;
-      zone->delta = hint->cur_pos + hint->cur_len -
-                    FT_MulFix( zone->min, scale2 );
-
-      psh1_print_zone( zone );
-
-      zone++;
-
-      hint = hint2;
-    }
-
-    /* the last zone */
-    zone->scale = scale;
-    zone->min   = hint->org_pos + hint->org_len;
-    zone->max   = PSH1_ZONE_MAX;
-    zone->delta = hint->cur_pos + hint->cur_len -
-                  FT_MulFix( zone->min, scale );
-
-    psh1_print_zone( zone );
-
-    zone++;
-
-    table->num_zones = zone - table->zones;
-    table->zone      = table->zones;
-  }
-
-
-  /* tune a single coordinate with the current interpolation zones */
-  static FT_Pos
-  psh1_hint_table_tune_coord( PSH1_Hint_Table  table,
-                              FT_Int           coord )
-  {
-    PSH1_Zone   zone;
-
-
-    zone = table->zone;
-
-    if ( coord < zone->min )
-    {
-      do
-      {
-        if ( zone == table->zones )
-          break;
-
-        zone--;
-
-      } while ( coord < zone->min );
-      table->zone = zone;
-    }
-    else if ( coord > zone->max )
-    {
-      do
-      {
-        if ( zone == table->zones + table->num_zones - 1 )
-          break;
-
-        zone++;
-
-      } while ( coord > zone->max );
-      table->zone = zone;
-    }
-
-    return FT_MulFix( coord, zone->scale ) + zone->delta;
-  }
-
-
-  /* tune a given outline with current interpolation zones. */
-  /* The function only works in a single dimension.         */
-  static void
-  psh1_hint_table_tune_outline( PSH1_Hint_Table  table,
-                                FT_Outline*      outline,
-                                PSH_Globals      globals,
-                                FT_Int           vertical )
-
-  {
-    FT_UInt         count, first, last;
-    PS_Mask_Table   hint_masks = table->hint_masks;
-    PS_Mask         mask;
-    PSH_Dimension   dim        = &globals->dimension[vertical];
-    FT_Fixed        scale      = dim->scale_mult;
-    FT_Fixed        delta      = dim->scale_delta;
-
-
-    if ( hint_masks && hint_masks->num_masks > 0 )
-    {
-      first = 0;
-      mask  = hint_masks->masks;
-      count = hint_masks->num_masks;
-
-      for ( ; count > 0; count--, mask++ )
-      {
-        last = mask->end_point;
-
-        if ( last > first )
-        {
-          FT_Vector*   vec;
-          FT_Int       count2;
-
-
-          psh1_hint_table_activate_mask( table, mask );
-          psh1_hint_table_optimize( table, globals, outline, vertical );
-          psh1_hint_table_setup_zones( table, scale, delta );
-          last = mask->end_point;
-
-          vec    = outline->points + first;
-          count2 = last - first;
-
-          for ( ; count2 > 0; count2--, vec++ )
-          {
-            FT_Pos  x, *px;
-
-
-            px  = vertical ? &vec->x : &vec->y;
-            x   = *px;
-
-            *px = psh1_hint_table_tune_coord( table, (FT_Int)x );
-          }
-        }
-
-        first = last;
-      }
-    }
-    else    /* no hints in this glyph, simply scale the outline */
-    {
-      FT_Vector*  vec;
-
-
-      vec   = outline->points;
-      count = outline->n_points;
-
-      if ( vertical )
-      {
-        for ( ; count > 0; count--, vec++ )
-          vec->x = FT_MulFix( vec->x, scale ) + delta;
-      }
-      else
-      {
-        for ( ; count > 0; count--, vec++ )
-          vec->y = FT_MulFix( vec->y, scale ) + delta;
-      }
-    }
-  }
-
-
-  /*************************************************************************/
-  /*************************************************************************/
-  /*****                                                               *****/
-  /*****                     HIGH-LEVEL INTERFACE                      *****/
-  /*****                                                               *****/
-  /*************************************************************************/
-  /*************************************************************************/
-
-  FT_Error
-  ps1_hints_apply( PS_Hints        ps_hints,
-                   FT_Outline*     outline,
-                   PSH_Globals     globals,
-                   FT_Render_Mode  hint_mode )
-  {
-    PSH1_Hint_TableRec  hints;
-    FT_Error            error = 0;
-    FT_Int              dimension;
-
-
-    FT_UNUSED( hint_mode );
-
-    for ( dimension = 1; dimension >= 0; dimension-- )
-    {
-      PS_Dimension  dim = &ps_hints->dimension[dimension];
-
-
-      /* initialize hints table */
-      FT_MEM_ZERO( &hints, sizeof ( hints ) );
-      error = psh1_hint_table_init( &hints,
-                                    &dim->hints,
-                                    &dim->masks,
-                                    &dim->counters,
-                                    ps_hints->memory );
-      if ( error )
-        goto Exit;
-
-      psh1_hint_table_tune_outline( &hints,
-                                    outline,
-                                    globals,
-                                    dimension );
-
-      psh1_hint_table_done( &hints, ps_hints->memory );
-    }
-
-  Exit:
-    return error;
-  }
-
-
-/* END */
--- a/src/pshinter/pshalgo1.h
+++ /dev/null
@@ -1,110 +1,0 @@
-/***************************************************************************/
-/*                                                                         */
-/*  pshalgo1.h                                                             */
-/*                                                                         */
-/*    PostScript hinting algorithm 1 (specification).                      */
-/*                                                                         */
-/*  Copyright 2001 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.                                        */
-/*                                                                         */
-/***************************************************************************/
-
-
-#ifndef __PSHALGO1_H__
-#define __PSHALGO1_H__
-
-#include "pshrec.h"
-
-FT_BEGIN_HEADER
-
-  typedef struct PSH1_HintRec_*  PSH1_Hint;
-
-  typedef enum
-  {
-    PSH1_HINT_FLAG_GHOST  = PS_HINT_FLAG_GHOST,
-    PSH1_HINT_FLAG_BOTTOM = PS_HINT_FLAG_BOTTOM,
-    PSH1_HINT_FLAG_ACTIVE = 4
-
-  } PSH1_Hint_Flags;
-
-#define psh1_hint_is_active( x )                          \
-          ( ( (x)->flags & PSH1_HINT_FLAG_ACTIVE ) != 0 )
-#define psh1_hint_is_ghost( x )                          \
-          ( ( (x)->flags & PSH1_HINT_FLAG_GHOST ) != 0 )
-
-#define psh1_hint_activate( x )    (x)->flags |= PSH1_HINT_FLAG_ACTIVE
-#define psh1_hint_deactivate( x )  (x)->flags &= ~PSH1_HINT_FLAG_ACTIVE
-
-  typedef struct  PSH1_HintRec_
-  {
-    FT_Int     org_pos;
-    FT_Int     org_len;
-    FT_Pos     cur_pos;
-    FT_Pos     cur_len;
-
-    FT_UInt    flags;
-
-    PSH1_Hint  parent;
-    FT_Int     order;
-
-  } PSH1_HintRec;
-
-
-  /* this is an interpolation zone used for strong points;  */
-  /* weak points are interpolated according to their strong */
-  /* neighbours                                             */
-  typedef struct  PSH1_ZoneRec_
-  {
-    FT_Fixed  scale;
-    FT_Fixed  delta;
-    FT_Pos    min;
-    FT_Pos    max;
-
-  } PSH1_ZoneRec, *PSH1_Zone;
-
-
-  typedef struct  PSH1_Hint_TableRec_
-  {
-    FT_UInt        max_hints;
-    FT_UInt        num_hints;
-    PSH1_Hint      hints;
-    PSH1_Hint*     sort;
-    PSH1_Hint*     sort_global;
-    FT_UInt        num_zones;
-    PSH1_Zone      zones;
-    PSH1_Zone      zone;
-    PS_Mask_Table  hint_masks;
-    PS_Mask_Table  counter_masks;
-
-  } PSH1_Hint_TableRec, *PSH1_Hint_Table;
-
-
-  extern FT_Error
-  ps1_hints_apply( PS_Hints        ps_hints,
-                   FT_Outline*     outline,
-                   PSH_Globals     globals,
-                   FT_Render_Mode  hint_mode );
-
-
-#ifdef DEBUG_HINTER
-  extern  PSH1_Hint_Table  ps1_debug_hint_table;
-
-  typedef void
-  (*PSH1_HintFunc)( PSH1_Hint  hint,
-                    FT_Bool    vertical );
-
-  extern PSH1_HintFunc  ps1_debug_hint_func;
-#endif
-
-FT_END_HEADER
-
-#endif /* __PSHALGO1_H__ */
-
-
-/* END */
--- a/src/pshinter/pshalgo2.c
+++ /dev/null
@@ -1,1557 +1,0 @@
-/***************************************************************************/
-/*                                                                         */
-/*  pshalgo2.c                                                             */
-/*                                                                         */
-/*    PostScript hinting algorithm 2 (body).                               */
-/*                                                                         */
-/*  Copyright 2001, 2002 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 <ft2build.h>
-#include FT_INTERNAL_OBJECTS_H
-#include FT_INTERNAL_DEBUG_H
-#include "pshalgo2.h"
-
-#undef  FT_COMPONENT
-#define FT_COMPONENT  trace_pshalgo2
-
-#ifdef DEBUG_HINTER
-  PSH2_Hint_Table  ps2_debug_hint_table = 0;
-  PSH2_HintFunc    ps2_debug_hint_func  = 0;
-  PSH2_Glyph       ps2_debug_glyph      = 0;
-#endif
-
-
-  /*************************************************************************/
-  /*************************************************************************/
-  /*****                                                               *****/
-  /*****                  BASIC HINTS RECORDINGS                       *****/
-  /*****                                                               *****/
-  /*************************************************************************/
-  /*************************************************************************/
-
-  /* return true iff two stem hints overlap */
-  static FT_Int
-  psh2_hint_overlap( PSH2_Hint  hint1,
-                     PSH2_Hint  hint2 )
-  {
-    return ( hint1->org_pos + hint1->org_len >= hint2->org_pos &&
-             hint2->org_pos + hint2->org_len >= hint1->org_pos );
-  }
-
-
-  /* destroy hints table */
-  static void
-  psh2_hint_table_done( PSH2_Hint_Table  table,
-                        FT_Memory        memory )
-  {
-    FT_FREE( table->zones );
-    table->num_zones = 0;
-    table->zone      = 0;
-
-    FT_FREE( table->sort );
-    FT_FREE( table->hints );
-    table->num_hints   = 0;
-    table->max_hints   = 0;
-    table->sort_global = 0;
-  }
-
-
-  /* deactivate all hints in a table */
-  static void
-  psh2_hint_table_deactivate( PSH2_Hint_Table  table )
-  {
-    FT_UInt   count = table->max_hints;
-    PSH2_Hint  hint  = table->hints;
-
-
-    for ( ; count > 0; count--, hint++ )
-    {
-      psh2_hint_deactivate( hint );
-      hint->order = -1;
-    }
-  }
-
-
-  /* internal function used to record a new hint */
-  static void
-  psh2_hint_table_record( PSH2_Hint_Table  table,
-                          FT_UInt          idx )
-  {
-    PSH2_Hint  hint = table->hints + idx;
-
-
-    if ( idx >= table->max_hints )
-    {
-      FT_ERROR(( "%s.activate: invalid hint index %d\n", idx ));
-      return;
-    }
-
-    /* ignore active hints */
-    if ( psh2_hint_is_active( hint ) )
-      return;
-
-    psh2_hint_activate( hint );
-
-    /* now scan the current active hint set in order to determine */
-    /* if we are overlapping with another segment                 */
-    {
-      PSH2_Hint*  sorted = table->sort_global;
-      FT_UInt     count  = table->num_hints;
-      PSH2_Hint   hint2;
-
-
-      hint->parent = 0;
-      for ( ; count > 0; count--, sorted++ )
-      {
-        hint2 = sorted[0];
-
-        if ( psh2_hint_overlap( hint, hint2 ) )
-        {
-          hint->parent = hint2;
-          break;
-        }
-      }
-    }
-
-    if ( table->num_hints < table->max_hints )
-      table->sort_global[table->num_hints++] = hint;
-    else
-      FT_ERROR(( "%s.activate: too many sorted hints!  BUG!\n",
-                 "ps.fitter" ));
-  }
-
-
-  static void
-  psh2_hint_table_record_mask( PSH2_Hint_Table  table,
-                               PS_Mask          hint_mask )
-  {
-    FT_Int    mask = 0, val = 0;
-    FT_Byte*  cursor = hint_mask->bytes;
-    FT_UInt   idx, limit;
-
-
-    limit = hint_mask->num_bits;
-
-    for ( idx = 0; idx < limit; idx++ )
-    {
-      if ( mask == 0 )
-      {
-        val  = *cursor++;
-        mask = 0x80;
-      }
-
-      if ( val & mask )
-        psh2_hint_table_record( table, idx );
-
-      mask >>= 1;
-    }
-  }
-
-
-  /* create hints table */
-  static FT_Error
-  psh2_hint_table_init( PSH2_Hint_Table  table,
-                        PS_Hint_Table    hints,
-                        PS_Mask_Table    hint_masks,
-                        PS_Mask_Table    counter_masks,
-                        FT_Memory        memory )
-  {
-    FT_UInt   count = hints->num_hints;
-    FT_Error  error;
-
-    FT_UNUSED( counter_masks );
-
-
-    /* allocate our tables */
-    if ( FT_NEW_ARRAY( table->sort,  2 * count     ) ||
-         FT_NEW_ARRAY( table->hints,     count     ) ||
-         FT_NEW_ARRAY( table->zones, 2 * count + 1 ) )
-      goto Exit;
-
-    table->max_hints   = count;
-    table->sort_global = table->sort + count;
-    table->num_hints   = 0;
-    table->num_zones   = 0;
-    table->zone        = 0;
-
-    /* now, initialize the "hints" array */
-    {
-      PSH2_Hint  write = table->hints;
-      PS_Hint    read  = hints->hints;
-
-
-      for ( ; count > 0; count--, write++, read++ )
-      {
-        write->org_pos = read->pos;
-        write->org_len = read->len;
-        write->flags   = read->flags;
-      }
-    }
-
-    /* we now need to determine the initial "parent" stems; first  */
-    /* activate the hints that are given by the initial hint masks */
-    if ( hint_masks )
-    {
-      FT_UInt  Count = hint_masks->num_masks;
-      PS_Mask  Mask  = hint_masks->masks;
-
-
-      table->hint_masks = hint_masks;
-
-      for ( ; Count > 0; Count--, Mask++ )
-        psh2_hint_table_record_mask( table, Mask );
-    }
-
-    /* now, do a linear parse in case some hints were left alone */
-    if ( table->num_hints != table->max_hints )
-    {
-      FT_UInt   Index, Count;
-
-
-      FT_ERROR(( "%s.init: missing/incorrect hint masks!\n" ));
-      Count = table->max_hints;
-      for ( Index = 0; Index < Count; Index++ )
-        psh2_hint_table_record( table, Index );
-    }
-
-  Exit:
-    return error;
-  }
-
-
-  static void
-  psh2_hint_table_activate_mask( PSH2_Hint_Table  table,
-                                 PS_Mask          hint_mask )
-  {
-    FT_Int    mask = 0, val = 0;
-    FT_Byte*  cursor = hint_mask->bytes;
-    FT_UInt   idx, limit, count;
-
-
-    limit = hint_mask->num_bits;
-    count = 0;
-
-    psh2_hint_table_deactivate( table );
-
-    for ( idx = 0; idx < limit; idx++ )
-    {
-      if ( mask == 0 )
-      {
-        val  = *cursor++;
-        mask = 0x80;
-      }
-
-      if ( val & mask )
-      {
-        PSH2_Hint  hint = &table->hints[idx];
-
-
-        if ( !psh2_hint_is_active( hint ) )
-        {
-          FT_UInt     count2;
-
-#if 0
-          PSH2_Hint*  sort = table->sort;
-          PSH2_Hint   hint2;
-
-          for ( count2 = count; count2 > 0; count2--, sort++ )
-          {
-            hint2 = sort[0];
-            if ( psh2_hint_overlap( hint, hint2 ) )
-              FT_ERROR(( "%s.activate_mask: found overlapping hints\n",
-                         "psf.hint" ));
-          }
-#else
-          count2 = 0;
-#endif
-
-          if ( count2 == 0 )
-          {
-            psh2_hint_activate( hint );
-            if ( count < table->max_hints )
-              table->sort[count++] = hint;
-            else
-              FT_ERROR(( "%s.activate_mask: too many active hints\n",
-                         "psf.hint" ));
-          }
-        }
-      }
-
-      mask >>= 1;
-    }
-    table->num_hints = count;
-
-    /* now, sort the hints; they are guaranteed to not overlap */
-    /* so we can compare their "org_pos" field directly        */
-    {
-      FT_Int      i1, i2;
-      PSH2_Hint   hint1, hint2;
-      PSH2_Hint*  sort = table->sort;
-
-
-      /* a simple bubble sort will do, since in 99% of cases, the hints */
-      /* will be already sorted -- and the sort will be linear          */
-      for ( i1 = 1; i1 < (FT_Int)count; i1++ )
-      {
-        hint1 = sort[i1];
-        for ( i2 = i1 - 1; i2 >= 0; i2-- )
-        {
-          hint2 = sort[i2];
-
-          if ( hint2->org_pos < hint1->org_pos )
-            break;
-
-          sort[i2 + 1] = hint2;
-          sort[i2]     = hint1;
-        }
-      }
-    }
-  }
-
-
-  /*************************************************************************/
-  /*************************************************************************/
-  /*****                                                               *****/
-  /*****               HINTS GRID-FITTING AND OPTIMIZATION             *****/
-  /*****                                                               *****/
-  /*************************************************************************/
-  /*************************************************************************/
-
-#ifdef DEBUG_HINTER
-  static void
-  ps2_simple_scale( PSH2_Hint_Table  table,
-                    FT_Fixed         scale,
-                    FT_Fixed         delta,
-                    FT_Int           dimension )
-  {
-    PSH2_Hint  hint;
-    FT_UInt    count;
-
-
-    for ( count = 0; count < table->max_hints; count++ )
-    {
-      hint = table->hints + count;
-
-      hint->cur_pos = FT_MulFix( hint->org_pos, scale ) + delta;
-      hint->cur_len = FT_MulFix( hint->org_len, scale );
-
-      if ( ps2_debug_hint_func )
-        ps2_debug_hint_func( hint, dimension );
-    }
-  }
-#endif
-
-
-  static void
-  psh2_hint_align( PSH2_Hint    hint,
-                   PSH_Globals  globals,
-                   FT_Int       dimension )
-  {
-    PSH_Dimension  dim   = &globals->dimension[dimension];
-    FT_Fixed       scale = dim->scale_mult;
-    FT_Fixed       delta = dim->scale_delta;
-
-
-    if ( !psh2_hint_is_fitted(hint) )
-    {
-      FT_Pos  pos = FT_MulFix( hint->org_pos, scale ) + delta;
-      FT_Pos  len = FT_MulFix( hint->org_len, scale );
-
-      FT_Pos  fit_center;
-      FT_Pos  fit_len;
-
-      PSH_AlignmentRec  align;
-
-
-      /* compute fitted width/height */
-      fit_len = 0;
-      if ( hint->org_len )
-      {
-        fit_len = psh_dimension_snap_width( dim, hint->org_len );
-        if ( fit_len < 64 )
-          fit_len = 64;
-        else
-          fit_len = ( fit_len + 32 ) & -64;
-      }
-
-      hint->cur_len = fit_len;
-
-      /* check blue zones for horizontal stems */
-      align.align = PSH_BLUE_ALIGN_NONE;
-      align.align_bot = align.align_top = 0;
-
-      if ( dimension == 1 )
-        psh_blues_snap_stem( &globals->blues,
-                             hint->org_pos + hint->org_len,
-                             hint->org_pos,
-                             &align );
-
-      switch ( align.align )
-      {
-      case PSH_BLUE_ALIGN_TOP:
-        /* the top of the stem is aligned against a blue zone */
-        hint->cur_pos = align.align_top - fit_len;
-        break;
-
-      case PSH_BLUE_ALIGN_BOT:
-        /* the bottom of the stem is aligned against a blue zone */
-        hint->cur_pos = align.align_bot;
-        break;
-
-      case PSH_BLUE_ALIGN_TOP | PSH_BLUE_ALIGN_BOT:
-        /* both edges of the stem are aligned against blue zones */
-        hint->cur_pos = align.align_bot;
-        hint->cur_len = align.align_top - align.align_bot;
-        break;
-
-      default:
-        {
-          PSH2_Hint  parent = hint->parent;
-
-
-          if ( parent )
-          {
-            FT_Pos  par_org_center, par_cur_center;
-            FT_Pos  cur_org_center, cur_delta;
-
-
-            /* ensure that parent is already fitted */
-            if ( !psh2_hint_is_fitted( parent ) )
-              psh2_hint_align( parent, globals, dimension );
-
-            par_org_center = parent->org_pos + ( parent->org_len / 2);
-            par_cur_center = parent->cur_pos + ( parent->cur_len / 2);
-            cur_org_center = hint->org_pos   + ( hint->org_len   / 2);
-
-            cur_delta = FT_MulFix( cur_org_center - par_org_center, scale );
-#if 0
-            if ( cur_delta >= 0 )
-              cur_delta = ( cur_delta + 16 ) & -64;
-            else
-              cur_delta = -( (-cur_delta + 16 ) & -64 );
-#endif
-            pos = par_cur_center + cur_delta - ( len >> 1 );
-          }
-
-          /* normal processing */
-          if ( ( fit_len / 64 ) & 1 )
-          {
-            /* odd number of pixels */
-            fit_center = ( ( pos + ( len >> 1 ) ) & -64 ) + 32;
-          }
-          else
-          {
-            /* even number of pixels */
-            fit_center = ( pos + ( len >> 1 ) + 32 ) & -64;
-          }
-
-          hint->cur_pos = fit_center - ( fit_len >> 1 );
-        }
-      }
-
-      psh2_hint_set_fitted( hint );
-
-#ifdef DEBUG_HINTER
-      if ( ps2_debug_hint_func )
-        ps2_debug_hint_func( hint, dimension );
-#endif
-    }
-  }
-
-
-  static void
-  psh2_hint_table_align_hints( PSH2_Hint_Table  table,
-                               PSH_Globals      globals,
-                               FT_Int           dimension )
-  {
-    PSH2_Hint      hint;
-    FT_UInt        count;
-
-#ifdef DEBUG_HINTER
-    PSH_Dimension  dim   = &globals->dimension[dimension];
-    FT_Fixed       scale = dim->scale_mult;
-    FT_Fixed       delta = dim->scale_delta;
-
-
-    if ( ps_debug_no_vert_hints && dimension == 0 )
-    {
-      ps2_simple_scale( table, scale, delta, dimension );
-      return;
-    }
-
-    if ( ps_debug_no_horz_hints && dimension == 1 )
-    {
-      ps2_simple_scale( table, scale, delta, dimension );
-      return;
-    }
-#endif
-
-    hint  = table->hints;
-    count = table->max_hints;
-
-    for ( ; count > 0; count--, hint++ )
-      psh2_hint_align( hint, globals, dimension );
-  }
-
-
-  /*************************************************************************/
-  /*************************************************************************/
-  /*****                                                               *****/
-  /*****                POINTS INTERPOLATION ROUTINES                  *****/
-  /*****                                                               *****/
-  /*************************************************************************/
-  /*************************************************************************/
-
-#define PSH2_ZONE_MIN  -3200000
-#define PSH2_ZONE_MAX  +3200000
-
-#define xxDEBUG_ZONES
-
-
-#ifdef DEBUG_ZONES
-
-#include <stdio.h>
-
-  static void
-  psh2_print_zone( PSH2_Zone  zone )
-  {
-    printf( "zone [scale,delta,min,max] = [%.3f,%.3f,%d,%d]\n",
-             zone->scale/65536.0,
-             zone->delta/64.0,
-             zone->min,
-             zone->max );
-  }
-
-#else
-
-#define psh2_print_zone( x )   do { } while ( 0 )
-
-#endif
-
-#if 0
-  /* setup interpolation zones once the hints have been grid-fitted */
-  /* by the optimizer                                               */
-  static void
-  psh2_hint_table_setup_zones( PSH2_Hint_Table  table,
-                               FT_Fixed         scale,
-                               FT_Fixed         delta )
-  {
-    FT_UInt     count;
-    PSH2_Zone   zone;
-    PSH2_Hint  *sort, hint, hint2;
-
-
-    zone = table->zones;
-
-    /* special case, no hints defined */
-    if ( table->num_hints == 0 )
-    {
-      zone->scale = scale;
-      zone->delta = delta;
-      zone->min   = PSH2_ZONE_MIN;
-      zone->max   = PSH2_ZONE_MAX;
-
-      table->num_zones = 1;
-      table->zone      = zone;
-      return;
-    }
-
-    /* the first zone is before the first hint */
-    /* x' = (x-x0)*s + x0' = x*s + ( x0' - x0*s ) */
-    sort = table->sort;
-    hint = sort[0];
-
-    zone->scale = scale;
-    zone->delta = hint->cur_pos - FT_MulFix( hint->org_pos, scale );
-    zone->min   = PSH2_ZONE_MIN;
-    zone->max   = hint->org_pos;
-
-    psh2_print_zone( zone );
-
-    zone++;
-
-    for ( count = table->num_hints; count > 0; count-- )
-    {
-      FT_Fixed  scale2;
-
-
-      if ( hint->org_len > 0 )
-      {
-        /* setup a zone for inner-stem interpolation */
-        /* (x' - x0') = (x - x0)*(x1'-x0')/(x1-x0)   */
-        /* x' = x*s2 + x0' - x0*s2                   */
-
-        scale2      = FT_DivFix( hint->cur_len, hint->org_len );
-        zone->scale = scale2;
-        zone->min   = hint->org_pos;
-        zone->max   = hint->org_pos + hint->org_len;
-        zone->delta = hint->cur_pos - FT_MulFix( zone->min, scale2 );
-
-        psh2_print_zone( zone );
-
-        zone++;
-      }
-
-      if ( count == 1 )
-        break;
-
-      sort++;
-      hint2 = sort[0];
-
-      /* setup zone for inter-stem interpolation */
-      /* (x'-x1') = (x-x1)*(x2'-x1')/(x2-x1)     */
-      /* x' = x*s3 + x1' - x1*s3                 */
-
-      scale2 = FT_DivFix( hint2->cur_pos - (hint->cur_pos + hint->cur_len),
-                          hint2->org_pos - (hint->org_pos + hint->org_len) );
-      zone->scale = scale2;
-      zone->min   = hint->org_pos + hint->org_len;
-      zone->max   = hint2->org_pos;
-      zone->delta = hint->cur_pos + hint->cur_len -
-                    FT_MulFix( zone->min, scale2 );
-
-      psh2_print_zone( zone );
-
-      zone++;
-
-      hint = hint2;
-    }
-
-    /* the last zone */
-    zone->scale = scale;
-    zone->min   = hint->org_pos + hint->org_len;
-    zone->max   = PSH2_ZONE_MAX;
-    zone->delta = hint->cur_pos + hint->cur_len -
-                  FT_MulFix( zone->min, scale );
-
-    psh2_print_zone( zone );
-
-    zone++;
-
-    table->num_zones = zone - table->zones;
-    table->zone      = table->zones;
-  }
-#endif
-
-#if 0
-  /* tune a single coordinate with the current interpolation zones */
-  static FT_Pos
-  psh2_hint_table_tune_coord( PSH2_Hint_Table  table,
-                              FT_Int           coord )
-  {
-    PSH2_Zone   zone;
-
-
-    zone = table->zone;
-
-    if ( coord < zone->min )
-    {
-      do
-      {
-        if ( zone == table->zones )
-          break;
-
-        zone--;
-
-      } while ( coord < zone->min );
-      table->zone = zone;
-    }
-    else if ( coord > zone->max )
-    {
-      do
-      {
-        if ( zone == table->zones + table->num_zones - 1 )
-          break;
-
-        zone++;
-
-      } while ( coord > zone->max );
-      table->zone = zone;
-    }
-
-    return FT_MulFix( coord, zone->scale ) + zone->delta;
-  }
-#endif
-
-#if 0
- /* tune a given outline with current interpolation zones */
- /* the function only works in a single dimension..       */
-  static void
-  psh2_hint_table_tune_outline( PSH2_Hint_Table  table,
-                                FT_Outline*      outline,
-                                PSH_Globals      globals,
-                                FT_Int           dimension )
-
-  {
-    FT_UInt        count, first, last;
-    PS_Mask_Table  hint_masks = table->hint_masks;
-    PS_Mask        mask;
-    PSH_Dimension  dim        = &globals->dimension[dimension];
-    FT_Fixed       scale      = dim->scale_mult;
-    FT_Fixed       delta      = dim->scale_delta;
-
-
-    if ( hint_masks && hint_masks->num_masks > 0 )
-    {
-      first = 0;
-      mask  = hint_masks->masks;
-      count = hint_masks->num_masks;
-
-      for ( ; count > 0; count--, mask++ )
-      {
-        last = mask->end_point;
-
-        if ( last > first )
-        {
-          FT_Vector*   vec;
-          FT_Int       count2;
-
-
-          psh2_hint_table_activate_mask( table, mask );
-          psh2_hint_table_optimize( table, globals, outline, dimension );
-          psh2_hint_table_setup_zones( table, scale, delta );
-          last = mask->end_point;
-
-          vec    = outline->points + first;
-          count2 = last - first;
-
-          for ( ; count2 > 0; count2--, vec++ )
-          {
-            FT_Pos  x, *px;
-
-
-            px  = dimension ? &vec->y : &vec->x;
-            x   = *px;
-
-            *px = psh2_hint_table_tune_coord( table, (FT_Int)x );
-          }
-        }
-
-        first = last;
-      }
-    }
-    else    /* no hints in this glyph, simply scale the outline */
-    {
-      FT_Vector*  vec;
-
-
-      vec   = outline->points;
-      count = outline->n_points;
-
-      if ( dimension == 0 )
-      {
-        for ( ; count > 0; count--, vec++ )
-          vec->x = FT_MulFix( vec->x, scale ) + delta;
-      }
-      else
-      {
-        for ( ; count > 0; count--, vec++ )
-          vec->y = FT_MulFix( vec->y, scale ) + delta;
-      }
-    }
-  }
-#endif
-
-
-  /*************************************************************************/
-  /*************************************************************************/
-  /*****                                                               *****/
-  /*****                    HINTER GLYPH MANAGEMENT                    *****/
-  /*****                                                               *****/
-  /*************************************************************************/
-  /*************************************************************************/
-
-  static int
-  psh2_point_is_extremum( PSH2_Point  point )
-  {
-    PSH2_Point  before = point;
-    PSH2_Point  after  = point;
-    FT_Pos      d_before;
-    FT_Pos      d_after;
-
-
-    do
-    {
-      before = before->prev;
-      if ( before == point )
-        return 0;
-
-      d_before = before->org_u - point->org_u;
-
-    } while ( d_before == 0 );
-
-    do
-    {
-      after = after->next;
-      if ( after == point )
-        return 0;
-
-      d_after = after->org_u - point->org_u;
-
-    } while ( d_after == 0 );
-
-    return ( ( d_before > 0 && d_after > 0 ) ||
-             ( d_before < 0 && d_after < 0 ) );
-  }
-
-
-  static void
-  psh2_glyph_done( PSH2_Glyph  glyph )
-  {
-    FT_Memory  memory = glyph->memory;
-
-
-    psh2_hint_table_done( &glyph->hint_tables[1], memory );
-    psh2_hint_table_done( &glyph->hint_tables[0], memory );
-
-    FT_FREE( glyph->points );
-    FT_FREE( glyph->contours );
-
-    glyph->num_points   = 0;
-    glyph->num_contours = 0;
-
-    glyph->memory = 0;
-  }
-
-
-  static int
-  psh2_compute_dir( FT_Pos  dx,
-                    FT_Pos  dy )
-  {
-    FT_Pos  ax, ay;
-    int     result = PSH2_DIR_NONE;
-
-
-    ax = ( dx >= 0 ) ? dx : -dx;
-    ay = ( dy >= 0 ) ? dy : -dy;
-
-    if ( ay * 12 < ax )
-    {
-      /* |dy| <<< |dx|  means a near-horizontal segment */
-      result = ( dx >= 0 ) ? PSH2_DIR_RIGHT : PSH2_DIR_LEFT;
-    }
-    else if ( ax * 12 < ay )
-    {
-      /* |dx| <<< |dy|  means a near-vertical segment */
-      result = ( dy >= 0 ) ? PSH2_DIR_UP : PSH2_DIR_DOWN;
-    }
-
-    return result;
-  }
-
-
-  static FT_Error
-  psh2_glyph_init( PSH2_Glyph   glyph,
-                   FT_Outline*  outline,
-                   PS_Hints     ps_hints,
-                   PSH_Globals  globals )
-  {
-    FT_Error   error;
-    FT_Memory  memory;
-
-
-    /* clear all fields */
-    FT_MEM_ZERO( glyph, sizeof ( *glyph ) );
-
-    memory = globals->memory;
-
-    /* allocate and setup points + contours arrays */
-    if ( FT_NEW_ARRAY( glyph->points,   outline->n_points   ) ||
-         FT_NEW_ARRAY( glyph->contours, outline->n_contours ) )
-      goto Exit;
-
-    glyph->num_points   = outline->n_points;
-    glyph->num_contours = outline->n_contours;
-
-    {
-      FT_UInt       first = 0, next, n;
-      PSH2_Point    points  = glyph->points;
-      PSH2_Contour  contour = glyph->contours;
-
-
-      for ( n = 0; n < glyph->num_contours; n++ )
-      {
-        FT_Int      count;
-        PSH2_Point  point;
-
-
-        next  = outline->contours[n] + 1;
-        count = next - first;
-
-        contour->start = points + first;
-        contour->count = (FT_UInt)count;
-
-        if ( count > 0 )
-        {
-          point = points + first;
-
-          point->prev    = points + next - 1;
-          point->contour = contour;
-
-          for ( ; count > 1; count-- )
-          {
-            point[0].next = point + 1;
-            point[1].prev = point;
-            point++;
-            point->contour = contour;
-          }
-          point->next = points + first;
-        }
-
-        contour++;
-        first = next;
-      }
-    }
-
-    {
-      PSH2_Point  points = glyph->points;
-      PSH2_Point  point  = points;
-      FT_Vector*  vec    = outline->points;
-      FT_UInt     n;
-
-
-      for ( n = 0; n < glyph->num_points; n++, point++ )
-      {
-        FT_Int  n_prev = point->prev - points;
-        FT_Int  n_next = point->next - points;
-        FT_Pos  dxi, dyi, dxo, dyo;
-
-
-        if ( !( outline->tags[n] & FT_CURVE_TAG_ON ) )
-          point->flags = PSH2_POINT_OFF;
-
-        dxi = vec[n].x - vec[n_prev].x;
-        dyi = vec[n].y - vec[n_prev].y;
-
-        point->dir_in = (FT_Char)psh2_compute_dir( dxi, dyi );
-
-        dxo = vec[n_next].x - vec[n].x;
-        dyo = vec[n_next].y - vec[n].y;
-
-        point->dir_out = (FT_Char)psh2_compute_dir( dxo, dyo );
-
-        /* detect smooth points */
-        if ( point->flags & PSH2_POINT_OFF )
-          point->flags |= PSH2_POINT_SMOOTH;
-        else if ( point->dir_in  != PSH2_DIR_NONE ||
-                  point->dir_out != PSH2_DIR_NONE )
-        {
-          if ( point->dir_in == point->dir_out )
-            point->flags |= PSH2_POINT_SMOOTH;
-        }
-        else
-        {
-          FT_Angle  angle_in, angle_out, diff;
-
-
-          angle_in  = FT_Atan2( dxi, dyi );
-          angle_out = FT_Atan2( dxo, dyo );
-
-          diff = angle_in - angle_out;
-          if ( diff < 0 )
-            diff = -diff;
-
-          if ( diff > FT_ANGLE_PI )
-            diff = FT_ANGLE_2PI - diff;
-
-          if ( diff < FT_ANGLE_PI / 16 )
-            point->flags |= PSH2_POINT_SMOOTH;
-        }
-      }
-    }
-
-    glyph->memory  = memory;
-    glyph->outline = outline;
-    glyph->globals = globals;
-
-    /* now deal with hints tables */
-    error = psh2_hint_table_init( &glyph->hint_tables [0],
-                                  &ps_hints->dimension[0].hints,
-                                  &ps_hints->dimension[0].masks,
-                                  &ps_hints->dimension[0].counters,
-                                  memory );
-    if ( error )
-      goto Exit;
-
-    error = psh2_hint_table_init( &glyph->hint_tables [1],
-                                  &ps_hints->dimension[1].hints,
-                                  &ps_hints->dimension[1].masks,
-                                  &ps_hints->dimension[1].counters,
-                                  memory );
-    if ( error )
-      goto Exit;
-
-  Exit:
-    return error;
-  }
-
-
-  /* load outline point coordinates into hinter glyph */
-  static void
-  psh2_glyph_load_points( PSH2_Glyph  glyph,
-                          FT_Int      dimension )
-  {
-    FT_Vector*  vec   = glyph->outline->points;
-    PSH2_Point  point = glyph->points;
-    FT_UInt     count = glyph->num_points;
-
-
-    for ( ; count > 0; count--, point++, vec++ )
-    {
-      point->flags &= PSH2_POINT_OFF | PSH2_POINT_SMOOTH;
-      point->hint   = 0;
-      if ( dimension == 0 )
-        point->org_u = vec->x;
-      else
-        point->org_u = vec->y;
-
-#ifdef DEBUG_HINTER
-      point->org_x = vec->x;
-      point->org_y = vec->y;
-#endif
-    }
-  }
-
-
-  /* save hinted point coordinates back to outline */
-  static void
-  psh2_glyph_save_points( PSH2_Glyph  glyph,
-                          FT_Int      dimension )
-  {
-    FT_UInt     n;
-    PSH2_Point  point = glyph->points;
-    FT_Vector*  vec   = glyph->outline->points;
-    char*       tags  = glyph->outline->tags;
-
-
-    for ( n = 0; n < glyph->num_points; n++ )
-    {
-      if ( dimension == 0 )
-        vec[n].x = point->cur_u;
-      else
-        vec[n].y = point->cur_u;
-
-      if ( psh2_point_is_strong( point ) )
-        tags[n] |= (char)( ( dimension == 0 ) ? 32 : 64 );
-
-#ifdef DEBUG_HINTER
-      if ( dimension == 0 )
-      {
-        point->cur_x   = point->cur_u;
-        point->flags_x = point->flags;
-      }
-      else
-      {
-        point->cur_y   = point->cur_u;
-        point->flags_y = point->flags;
-      }
-#endif
-      point++;
-    }
-  }
-
-
-#define PSH2_STRONG_THRESHOLD  10
-
-
-  static void
-  psh2_hint_table_find_strong_point( PSH2_Hint_Table  table,
-                                     PSH2_Point       point,
-                                     FT_Int           major_dir )
-  {
-    PSH2_Hint*   sort      = table->sort;
-    FT_UInt      num_hints = table->num_hints;
-
-
-    for ( ; num_hints > 0; num_hints--, sort++ )
-    {
-      PSH2_Hint  hint = sort[0];
-
-
-      if ( ABS( point->dir_in )  == major_dir ||
-           ABS( point->dir_out ) == major_dir )
-      {
-        FT_Pos  d;
-
-
-        d = point->org_u - hint->org_pos;
-        if ( ABS( d ) < PSH2_STRONG_THRESHOLD )
-        {
-        Is_Strong:
-          psh2_point_set_strong( point );
-          point->hint = hint;
-          break;
-        }
-
-        d -= hint->org_len;
-        if ( ABS( d ) < PSH2_STRONG_THRESHOLD )
-          goto Is_Strong;
-      }
-
-#if 1
-      if ( point->org_u >= hint->org_pos &&
-           point->org_u <= hint->org_pos + hint->org_len &&
-           psh2_point_is_extremum( point ) )
-      {
-        /* attach to hint, but don't mark as strong */
-        point->hint = hint;
-        break;
-      }
-#endif
-    }
-  }
-
-
-  /* find strong points in a glyph */
-  static void
-  psh2_glyph_find_strong_points( PSH2_Glyph  glyph,
-                                 FT_Int      dimension )
-  {
-    /* a point is strong if it is located on a stem                   */
-    /* edge and has an "in" or "out" tangent to the hint's direction  */
-    {
-      PSH2_Hint_Table  table     = &glyph->hint_tables[dimension];
-      PS_Mask          mask      = table->hint_masks->masks;
-      FT_UInt          num_masks = table->hint_masks->num_masks;
-      FT_UInt          first     = 0;
-      FT_Int           major_dir = dimension == 0 ? PSH2_DIR_UP : PSH2_DIR_RIGHT;
-
-
-      /* process secondary hints to "selected" points */
-      if ( num_masks > 1 && glyph->num_points > 0 )
-      {
-        first = mask->end_point;
-        mask++;
-        for ( ; num_masks > 1; num_masks--, mask++ )
-        {
-          FT_UInt  next;
-          FT_Int   count;
-
-
-          next  = mask->end_point;
-          count = next - first;
-          if ( count > 0 )
-          {
-            PSH2_Point  point = glyph->points + first;
-
-
-            psh2_hint_table_activate_mask( table, mask );
-
-            for ( ; count > 0; count--, point++ )
-              psh2_hint_table_find_strong_point( table, point, major_dir );
-          }
-          first = next;
-        }
-      }
-
-      /* process primary hints for all points */
-      if ( num_masks == 1 )
-      {
-        FT_UInt     count = glyph->num_points;
-        PSH2_Point  point = glyph->points;
-
-
-        psh2_hint_table_activate_mask( table, table->hint_masks->masks );
-        for ( ; count > 0; count--, point++ )
-        {
-          if ( !psh2_point_is_strong( point ) )
-            psh2_hint_table_find_strong_point( table, point, major_dir );
-        }
-      }
-
-      /* now, certain points may have been attached to hint and */
-      /* not marked as strong; update their flags then          */
-      {
-        FT_UInt     count = glyph->num_points;
-        PSH2_Point  point = glyph->points;
-
-
-        for ( ; count > 0; count--, point++ )
-          if ( point->hint && !psh2_point_is_strong( point ) )
-            psh2_point_set_strong( point );
-      }
-    }
-  }
-
-
-  /* interpolate strong points with the help of hinted coordinates */
-  static void
-  psh2_glyph_interpolate_strong_points( PSH2_Glyph  glyph,
-                                        FT_Int      dimension )
-  {
-    PSH_Dimension    dim   = &glyph->globals->dimension[dimension];
-    FT_Fixed         scale = dim->scale_mult;
-
-
-    {
-      FT_UInt     count = glyph->num_points;
-      PSH2_Point  point = glyph->points;
-
-
-      for ( ; count > 0; count--, point++ )
-      {
-        PSH2_Hint  hint = point->hint;
-
-
-        if ( hint )
-        {
-          FT_Pos  delta;
-
-
-          delta = point->org_u - hint->org_pos;
-
-          if ( delta <= 0 )
-            point->cur_u = hint->cur_pos + FT_MulFix( delta, scale );
-
-          else if ( delta >= hint->org_len )
-            point->cur_u = hint->cur_pos + hint->cur_len +
-                           FT_MulFix( delta - hint->org_len, scale );
-
-          else if ( hint->org_len > 0 )
-            point->cur_u = hint->cur_pos +
-                           FT_MulDiv( delta, hint->cur_len, hint->org_len );
-          else
-            point->cur_u = hint->cur_pos;
-
-          psh2_point_set_fitted( point );
-        }
-      }
-    }
-  }
-
-
-  static void
-  psh2_glyph_interpolate_normal_points( PSH2_Glyph  glyph,
-                                        FT_Int      dimension )
-  {
-#if 1
-    PSH_Dimension    dim   = &glyph->globals->dimension[dimension];
-    FT_Fixed         scale = dim->scale_mult;
-
-
-    /* first technique: a point is strong if it is a local extrema */
-    {
-      FT_UInt     count = glyph->num_points;
-      PSH2_Point  point = glyph->points;
-
-
-      for ( ; count > 0; count--, point++ )
-      {
-        if ( psh2_point_is_strong( point ) )
-          continue;
-
-        /* sometimes, some local extremas are smooth points */
-        if ( psh2_point_is_smooth( point ) )
-        {
-          if ( point->dir_in == PSH2_DIR_NONE  ||
-               point->dir_in != point->dir_out )
-            continue;
-
-          if ( !psh2_point_is_extremum( point ) )
-            continue;
-
-          point->flags &= ~PSH2_POINT_SMOOTH;
-        }
-
-        /* find best enclosing point coordinates */
-        {
-          PSH2_Point  before = 0;
-          PSH2_Point  after  = 0;
-
-          FT_Pos      diff_before = -32000;
-          FT_Pos      diff_after  =  32000;
-          FT_Pos      u = point->org_u;
-
-          FT_Int      count2 = glyph->num_points;
-          PSH2_Point  cur    = glyph->points;
-
-
-          for ( ; count2 > 0; count2--, cur++ )
-          {
-            if ( psh2_point_is_strong( cur ) )
-            {
-              FT_Pos   diff = cur->org_u - u;;
-
-
-              if ( diff <= 0 )
-              {
-                if ( diff > diff_before )
-                {
-                  diff_before = diff;
-                  before      = cur;
-                }
-              }
-              else if ( diff >= 0 )
-              {
-                if ( diff < diff_after )
-                {
-                  diff_after = diff;
-                  after      = cur;
-                }
-              }
-            }
-          }
-
-          if ( !before )
-          {
-            if ( !after )
-              continue;
-
-            /* we are before the first strong point coordinate; */
-            /* simply translate the point                       */
-            point->cur_u = after->cur_u +
-                           FT_MulFix( point->org_u - after->org_u, scale );
-          }
-          else if ( !after )
-          {
-            /* we are after the last strong point coordinate; */
-            /* simply translate the point                     */
-            point->cur_u = before->cur_u +
-                           FT_MulFix( point->org_u - before->org_u, scale );
-          }
-          else
-          {
-            if ( diff_before == 0 )
-              point->cur_u = before->cur_u;
-
-            else if ( diff_after == 0 )
-              point->cur_u = after->cur_u;
-
-            else
-              point->cur_u = before->cur_u +
-                             FT_MulDiv( u - before->org_u,
-                                        after->cur_u - before->cur_u,
-                                        after->org_u - before->org_u );
-          }
-
-          psh2_point_set_fitted( point );
-        }
-      }
-    }
-#endif
-  }
-
-
-  /* interpolate other points */
-  static void
-  psh2_glyph_interpolate_other_points( PSH2_Glyph  glyph,
-                                       FT_Int      dimension )
-  {
-    PSH_Dimension dim          = &glyph->globals->dimension[dimension];
-    FT_Fixed      scale        = dim->scale_mult;
-    FT_Fixed      delta        = dim->scale_delta;
-    PSH2_Contour  contour      = glyph->contours;
-    FT_UInt       num_contours = glyph->num_contours;
-
-
-    for ( ; num_contours > 0; num_contours--, contour++ )
-    {
-      PSH2_Point   start = contour->start;
-      PSH2_Point   first, next, point;
-      FT_UInt      fit_count;
-
-
-      /* count the number of strong points in this contour */
-      next      = start + contour->count;
-      fit_count = 0;
-      first     = 0;
-
-      for ( point = start; point < next; point++ )
-        if ( psh2_point_is_fitted( point ) )
-        {
-          if ( !first )
-            first = point;
-
-          fit_count++;
-        }
-
-      /* if there are less than 2 fitted points in the contour, we */
-      /* simply scale and eventually translate the contour points  */
-      if ( fit_count < 2 )
-      {
-        if ( fit_count == 1 )
-          delta = first->cur_u - FT_MulFix( first->org_u, scale );
-
-        for ( point = start; point < next; point++ )
-          if ( point != first )
-            point->cur_u = FT_MulFix( point->org_u, scale ) + delta;
-
-        goto Next_Contour;
-      }
-
-      /* there are more than 2 strong points in this contour; we */
-      /* need to interpolate weak points between them            */
-      start = first;
-      do
-      {
-        point = first;
-
-        /* skip consecutive fitted points */
-        for (;;)
-        {
-          next = first->next;
-          if ( next == start )
-            goto Next_Contour;
-
-          if ( !psh2_point_is_fitted( next ) )
-            break;
-
-          first = next;
-        }
-
-        /* find next fitted point after unfitted one */
-        for (;;)
-        {
-          next = next->next;
-          if ( psh2_point_is_fitted( next ) )
-            break;
-        }
-
-        /* now interpolate between them */
-        {
-          FT_Pos    org_a, org_ab, cur_a, cur_ab;
-          FT_Pos    org_c, org_ac, cur_c;
-          FT_Fixed  scale_ab;
-
-
-          if ( first->org_u <= next->org_u )
-          {
-            org_a  = first->org_u;
-            cur_a  = first->cur_u;
-            org_ab = next->org_u - org_a;
-            cur_ab = next->cur_u - cur_a;
-          }
-          else
-          {
-            org_a  = next->org_u;
-            cur_a  = next->cur_u;
-            org_ab = first->org_u - org_a;
-            cur_ab = first->cur_u - cur_a;
-          }
-
-          scale_ab = 0x10000L;
-          if ( org_ab > 0 )
-            scale_ab = FT_DivFix( cur_ab, org_ab );
-
-          point = first->next;
-          do
-          {
-            org_c  = point->org_u;
-            org_ac = org_c - org_a;
-
-            if ( org_ac <= 0 )
-            {
-              /* on the left of the interpolation zone */
-              cur_c = cur_a + FT_MulFix( org_ac, scale );
-            }
-            else if ( org_ac >= org_ab )
-            {
-              /* on the right on the interpolation zone */
-              cur_c = cur_a + cur_ab + FT_MulFix( org_ac - org_ab, scale );
-            }
-            else
-            {
-              /* within the interpolation zone */
-              cur_c = cur_a + FT_MulFix( org_ac, scale_ab );
-            }
-
-            point->cur_u = cur_c;
-
-            point = point->next;
-
-          } while ( point != next );
-        }
-
-        /* keep going until all points in the contours have been processed */
-        first = next;
-
-      } while ( first != start );
-
-    Next_Contour:
-      ;
-    }
-  }
-
-
-  /*************************************************************************/
-  /*************************************************************************/
-  /*****                                                               *****/
-  /*****                     HIGH-LEVEL INTERFACE                      *****/
-  /*****                                                               *****/
-  /*************************************************************************/
-  /*************************************************************************/
-
-  FT_Error
-  ps2_hints_apply( PS_Hints        ps_hints,
-                   FT_Outline*     outline,
-                   PSH_Globals     globals,
-                   FT_Render_Mode  hint_mode )
-  {
-    PSH2_GlyphRec  glyphrec;
-    PSH2_Glyph     glyph = &glyphrec;
-    FT_Error       error;
-#ifdef DEBUG_HINTER
-    FT_Memory      memory;
-#endif
-    FT_Int         dimension;
-
-    FT_UNUSED( hint_mode );
-
-#ifdef DEBUG_HINTER
-    memory = globals->memory;
-
-    if ( ps2_debug_glyph )
-    {
-      psh2_glyph_done( ps2_debug_glyph );
-      FT_FREE( ps2_debug_glyph );
-    }
-
-    if ( FT_NEW( glyph ) )
-      return error;
-
-    ps2_debug_glyph = glyph;
-#endif
-
-    error = psh2_glyph_init( glyph, outline, ps_hints, globals );
-    if ( error )
-      goto Exit;
-
-    for ( dimension = 0; dimension < 2; dimension++ )
-    {
-      /* load outline coordinates into glyph */
-      psh2_glyph_load_points( glyph, dimension );
-
-      /* compute aligned stem/hints positions */
-      psh2_hint_table_align_hints( &glyph->hint_tables[dimension],
-                                   glyph->globals,
-                                   dimension );
-
-      /* find strong points, align them, then interpolate others */
-      psh2_glyph_find_strong_points( glyph, dimension );
-      psh2_glyph_interpolate_strong_points( glyph, dimension );
-      psh2_glyph_interpolate_normal_points( glyph, dimension );
-      psh2_glyph_interpolate_other_points( glyph, dimension );
-
-      /* save hinted coordinates back to outline */
-      psh2_glyph_save_points( glyph, dimension );
-    }
-
-  Exit:
-#ifndef DEBUG_HINTER
-    psh2_glyph_done( glyph );
-#endif
-    return error;
-  }
-
-
-/* END */
--- a/src/pshinter/pshalgo2.h
+++ /dev/null
@@ -1,203 +1,0 @@
-/***************************************************************************/
-/*                                                                         */
-/*  pshalgo2.h                                                             */
-/*                                                                         */
-/*    PostScript hinting algorithm 2 (specification).                      */
-/*                                                                         */
-/*  Copyright 2001 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.                                        */
-/*                                                                         */
-/***************************************************************************/
-
-
-#ifndef __PSHALGO2_H__
-#define __PSHALGO2_H__
-
-
-#include "pshrec.h"
-#include "pshglob.h"
-#include FT_TRIGONOMETRY_H
-
-
-FT_BEGIN_HEADER
-
-
-  typedef struct PSH2_HintRec_*  PSH2_Hint;
-
-  typedef enum
-  {
-    PSH2_HINT_GHOST  = PS_HINT_FLAG_GHOST,
-    PSH2_HINT_BOTTOM = PS_HINT_FLAG_BOTTOM,
-    PSH2_HINT_ACTIVE = 4,
-    PSH2_HINT_FITTED = 8
-
-  } PSH2_Hint_Flags;
-
-
-#define psh2_hint_is_active( x )  ( ( (x)->flags & PSH2_HINT_ACTIVE ) != 0 )
-#define psh2_hint_is_ghost( x )   ( ( (x)->flags & PSH2_HINT_GHOST  ) != 0 )
-#define psh2_hint_is_fitted( x )  ( ( (x)->flags & PSH2_HINT_FITTED ) != 0 )
-
-#define psh2_hint_activate( x )    (x)->flags |=  PSH2_HINT_ACTIVE
-#define psh2_hint_deactivate( x )  (x)->flags &= ~PSH2_HINT_ACTIVE
-#define psh2_hint_set_fitted( x )  (x)->flags |=  PSH2_HINT_FITTED
-
-
-  typedef struct  PSH2_HintRec_
-  {
-    FT_Int     org_pos;
-    FT_Int     org_len;
-    FT_Pos     cur_pos;
-    FT_Pos     cur_len;
-    FT_UInt    flags;
-    PSH2_Hint  parent;
-    FT_Int     order;
-
-  } PSH2_HintRec;
-
-
-  /* this is an interpolation zone used for strong points;  */
-  /* weak points are interpolated according to their strong */
-  /* neighbours                                             */
-  typedef struct  PSH2_ZoneRec_
-  {
-    FT_Fixed  scale;
-    FT_Fixed  delta;
-    FT_Pos    min;
-    FT_Pos    max;
-
-  } PSH2_ZoneRec, *PSH2_Zone;
-
-
-  typedef struct  PSH2_Hint_TableRec_
-  {
-    FT_UInt        max_hints;
-    FT_UInt        num_hints;
-    PSH2_Hint      hints;
-    PSH2_Hint*     sort;
-    PSH2_Hint*     sort_global;
-    FT_UInt        num_zones;
-    PSH2_Zone      zones;
-    PSH2_Zone      zone;
-    PS_Mask_Table  hint_masks;
-    PS_Mask_Table  counter_masks;
-
-  } PSH2_Hint_TableRec, *PSH2_Hint_Table;
-
-
-  typedef struct PSH2_PointRec_*    PSH2_Point;
-  typedef struct PSH2_ContourRec_*  PSH2_Contour;
-
-  enum
-  {
-    PSH2_DIR_NONE  =  4,
-    PSH2_DIR_UP    =  1,
-    PSH2_DIR_DOWN  = -1,
-    PSH2_DIR_LEFT  = -2,
-    PSH2_DIR_RIGHT =  2
-  };
-
-  enum
-  {
-    PSH2_POINT_OFF    = 1,   /* point is off the curve  */
-    PSH2_POINT_STRONG = 2,   /* point is strong         */
-    PSH2_POINT_SMOOTH = 4,   /* point is smooth         */
-    PSH2_POINT_FITTED = 8    /* point is already fitted */
-  };
-
-
-  typedef struct  PSH2_PointRec_
-  {
-    PSH2_Point    prev;
-    PSH2_Point    next;
-    PSH2_Contour  contour;
-    FT_UInt       flags;
-    FT_Char       dir_in;
-    FT_Char       dir_out;
-    FT_Angle      angle_in;
-    FT_Angle      angle_out;
-    PSH2_Hint     hint;
-    FT_Pos        org_u;
-    FT_Pos        cur_u;
-#ifdef DEBUG_HINTER
-    FT_Pos        org_x;
-    FT_Pos        cur_x;
-    FT_Pos        org_y;
-    FT_Pos        cur_y;
-    FT_UInt       flags_x;
-    FT_UInt       flags_y;
-#endif
-
-  } PSH2_PointRec;
-
-
-#define psh2_point_is_strong( p )   ( (p)->flags & PSH2_POINT_STRONG )
-#define psh2_point_is_fitted( p )   ( (p)->flags & PSH2_POINT_FITTED )
-#define psh2_point_is_smooth( p )   ( (p)->flags & PSH2_POINT_SMOOTH )
-
-#define psh2_point_set_strong( p )  (p)->flags |= PSH2_POINT_STRONG
-#define psh2_point_set_fitted( p )  (p)->flags |= PSH2_POINT_FITTED
-#define psh2_point_set_smooth( p )  (p)->flags |= PSH2_POINT_SMOOTH
-
-
-  typedef struct  PSH2_ContourRec_
-  {
-    PSH2_Point  start;
-    FT_UInt     count;
-
-  } PSH2_ContourRec;
-
-
-  typedef struct  PSH2_GlyphRec_
-  {
-    FT_UInt             num_points;
-    FT_UInt             num_contours;
-
-    PSH2_Point          points;
-    PSH2_Contour        contours;
-
-    FT_Memory           memory;
-    FT_Outline*         outline;
-    PSH_Globals         globals;
-    PSH2_Hint_TableRec  hint_tables[2];
-
-    FT_Bool             vertical;
-    FT_Int              major_dir;
-    FT_Int              minor_dir;
-
-  } PSH2_GlyphRec, *PSH2_Glyph;
-
-
-#ifdef DEBUG_HINTER
-  extern PSH2_Hint_Table  ps2_debug_hint_table;
-
-  typedef void
-  (*PSH2_HintFunc)( PSH2_Hint  hint,
-                    FT_Bool    vertical );
-
-  extern PSH2_HintFunc    ps2_debug_hint_func;
-
-  extern PSH2_Glyph       ps2_debug_glyph;
-#endif
-
-
-  extern FT_Error
-  ps2_hints_apply( PS_Hints        ps_hints,
-                   FT_Outline*     outline,
-                   PSH_Globals     globals,
-                   FT_Render_Mode  hint_mode );
-
-
-FT_END_HEADER
-
-
-#endif /* __PSHALGO2_H__ */
-
-
-/* END */
--- a/src/pshinter/pshalgo3.c
+++ /dev/null
@@ -1,1997 +1,0 @@
-/***************************************************************************/
-/*                                                                         */
-/*  pshalgo3.c                                                             */
-/*                                                                         */
-/*    PostScript hinting algorithm 3 (body).                               */
-/*                                                                         */
-/*  Copyright 2001, 2002, 2003 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 <ft2build.h>
-#include FT_INTERNAL_OBJECTS_H
-#include FT_INTERNAL_DEBUG_H
-#include "pshalgo3.h"
-
-
-#undef  FT_COMPONENT
-#define FT_COMPONENT  trace_pshalgo2
-
-
-#ifdef DEBUG_HINTER
-  PSH3_Hint_Table  ps3_debug_hint_table = 0;
-  PSH3_HintFunc    ps3_debug_hint_func  = 0;
-  PSH3_Glyph       ps3_debug_glyph      = 0;
-#endif
-
-
-#define  COMPUTE_INFLEXS  /* compute inflection points to optimize "S" and others */
-#define  STRONGER         /* slightly increase the contrast of smooth hinting */
-
-  /*************************************************************************/
-  /*************************************************************************/
-  /*****                                                               *****/
-  /*****                  BASIC HINTS RECORDINGS                       *****/
-  /*****                                                               *****/
-  /*************************************************************************/
-  /*************************************************************************/
-
-  /* return true iff two stem hints overlap */
-  static FT_Int
-  psh3_hint_overlap( PSH3_Hint  hint1,
-                     PSH3_Hint  hint2 )
-  {
-    return ( hint1->org_pos + hint1->org_len >= hint2->org_pos &&
-             hint2->org_pos + hint2->org_len >= hint1->org_pos );
-  }
-
-
-  /* destroy hints table */
-  static void
-  psh3_hint_table_done( PSH3_Hint_Table  table,
-                        FT_Memory        memory )
-  {
-    FT_FREE( table->zones );
-    table->num_zones = 0;
-    table->zone      = 0;
-
-    FT_FREE( table->sort );
-    FT_FREE( table->hints );
-    table->num_hints   = 0;
-    table->max_hints   = 0;
-    table->sort_global = 0;
-  }
-
-
-  /* deactivate all hints in a table */
-  static void
-  psh3_hint_table_deactivate( PSH3_Hint_Table  table )
-  {
-    FT_UInt    count = table->max_hints;
-    PSH3_Hint  hint  = table->hints;
-
-
-    for ( ; count > 0; count--, hint++ )
-    {
-      psh3_hint_deactivate( hint );
-      hint->order = -1;
-    }
-  }
-
-
-  /* internal function used to record a new hint */
-  static void
-  psh3_hint_table_record( PSH3_Hint_Table  table,
-                          FT_UInt          idx )
-  {
-    PSH3_Hint  hint = table->hints + idx;
-
-
-    if ( idx >= table->max_hints )
-    {
-      FT_ERROR(( "psh3_hint_table_record: invalid hint index %d\n", idx ));
-      return;
-    }
-
-    /* ignore active hints */
-    if ( psh3_hint_is_active( hint ) )
-      return;
-
-    psh3_hint_activate( hint );
-
-    /* now scan the current active hint set in order to determine */
-    /* if we are overlapping with another segment                 */
-    {
-      PSH3_Hint*  sorted = table->sort_global;
-      FT_UInt     count  = table->num_hints;
-      PSH3_Hint   hint2;
-
-
-      hint->parent = 0;
-      for ( ; count > 0; count--, sorted++ )
-      {
-        hint2 = sorted[0];
-
-        if ( psh3_hint_overlap( hint, hint2 ) )
-        {
-          hint->parent = hint2;
-          break;
-        }
-      }
-    }
-
-    if ( table->num_hints < table->max_hints )
-      table->sort_global[table->num_hints++] = hint;
-    else
-      FT_ERROR(( "psh3_hint_table_record: too many sorted hints!  BUG!\n" ));
-  }
-
-
-  static void
-  psh3_hint_table_record_mask( PSH3_Hint_Table  table,
-                               PS_Mask          hint_mask )
-  {
-    FT_Int    mask = 0, val = 0;
-    FT_Byte*  cursor = hint_mask->bytes;
-    FT_UInt   idx, limit;
-
-
-    limit = hint_mask->num_bits;
-
-    for ( idx = 0; idx < limit; idx++ )
-    {
-      if ( mask == 0 )
-      {
-        val  = *cursor++;
-        mask = 0x80;
-      }
-
-      if ( val & mask )
-        psh3_hint_table_record( table, idx );
-
-      mask >>= 1;
-    }
-  }
-
-
-  /* create hints table */
-  static FT_Error
-  psh3_hint_table_init( PSH3_Hint_Table  table,
-                        PS_Hint_Table    hints,
-                        PS_Mask_Table    hint_masks,
-                        PS_Mask_Table    counter_masks,
-                        FT_Memory        memory )
-  {
-    FT_UInt   count = hints->num_hints;
-    FT_Error  error;
-
-    FT_UNUSED( counter_masks );
-
-
-    /* allocate our tables */
-    if ( FT_NEW_ARRAY( table->sort,  2 * count     ) ||
-         FT_NEW_ARRAY( table->hints,     count     ) ||
-         FT_NEW_ARRAY( table->zones, 2 * count + 1 ) )
-      goto Exit;
-
-    table->max_hints   = count;
-    table->sort_global = table->sort + count;
-    table->num_hints   = 0;
-    table->num_zones   = 0;
-    table->zone        = 0;
-
-    /* now, initialize the "hints" array */
-    {
-      PSH3_Hint  write = table->hints;
-      PS_Hint    read  = hints->hints;
-
-
-      for ( ; count > 0; count--, write++, read++ )
-      {
-        write->org_pos = read->pos;
-        write->org_len = read->len;
-        write->flags   = read->flags;
-      }
-    }
-
-    /* we now need to determine the initial "parent" stems; first  */
-    /* activate the hints that are given by the initial hint masks */
-    if ( hint_masks )
-    {
-      FT_UInt  Count = hint_masks->num_masks;
-      PS_Mask  Mask  = hint_masks->masks;
-
-
-      table->hint_masks = hint_masks;
-
-      for ( ; Count > 0; Count--, Mask++ )
-        psh3_hint_table_record_mask( table, Mask );
-    }
-
-    /* now, do a linear parse in case some hints were left alone */
-    if ( table->num_hints != table->max_hints )
-    {
-      FT_UInt  Index, Count;
-
-
-      FT_ERROR(( "psh3_hint_table_init: missing/incorrect hint masks!\n" ));
-      Count = table->max_hints;
-      for ( Index = 0; Index < Count; Index++ )
-        psh3_hint_table_record( table, Index );
-    }
-
-  Exit:
-    return error;
-  }
-
-
-  static void
-  psh3_hint_table_activate_mask( PSH3_Hint_Table  table,
-                                 PS_Mask          hint_mask )
-  {
-    FT_Int    mask = 0, val = 0;
-    FT_Byte*  cursor = hint_mask->bytes;
-    FT_UInt   idx, limit, count;
-
-
-    limit = hint_mask->num_bits;
-    count = 0;
-
-    psh3_hint_table_deactivate( table );
-
-    for ( idx = 0; idx < limit; idx++ )
-    {
-      if ( mask == 0 )
-      {
-        val  = *cursor++;
-        mask = 0x80;
-      }
-
-      if ( val & mask )
-      {
-        PSH3_Hint  hint = &table->hints[idx];
-
-
-        if ( !psh3_hint_is_active( hint ) )
-        {
-          FT_UInt     count2;
-
-#if 0
-          PSH3_Hint*  sort = table->sort;
-          PSH3_Hint   hint2;
-
-
-          for ( count2 = count; count2 > 0; count2--, sort++ )
-          {
-            hint2 = sort[0];
-            if ( psh3_hint_overlap( hint, hint2 ) )
-              FT_ERROR(( "psh3_hint_table_activate_mask:"
-                         " found overlapping hints\n" ))
-          }
-#else
-          count2 = 0;
-#endif
-
-          if ( count2 == 0 )
-          {
-            psh3_hint_activate( hint );
-            if ( count < table->max_hints )
-              table->sort[count++] = hint;
-            else
-              FT_ERROR(( "psh3_hint_tableactivate_mask:"
-                         " too many active hints\n" ));
-          }
-        }
-      }
-
-      mask >>= 1;
-    }
-    table->num_hints = count;
-
-    /* now, sort the hints; they are guaranteed to not overlap */
-    /* so we can compare their "org_pos" field directly        */
-    {
-      FT_Int      i1, i2;
-      PSH3_Hint   hint1, hint2;
-      PSH3_Hint*  sort = table->sort;
-
-
-      /* a simple bubble sort will do, since in 99% of cases, the hints */
-      /* will be already sorted -- and the sort will be linear          */
-      for ( i1 = 1; i1 < (FT_Int)count; i1++ )
-      {
-        hint1 = sort[i1];
-        for ( i2 = i1 - 1; i2 >= 0; i2-- )
-        {
-          hint2 = sort[i2];
-
-          if ( hint2->org_pos < hint1->org_pos )
-            break;
-
-          sort[i2 + 1] = hint2;
-          sort[i2]     = hint1;
-        }
-      }
-    }
-  }
-
-
-  /*************************************************************************/
-  /*************************************************************************/
-  /*****                                                               *****/
-  /*****               HINTS GRID-FITTING AND OPTIMIZATION             *****/
-  /*****                                                               *****/
-  /*************************************************************************/
-  /*************************************************************************/
-
-#if 1
-  static FT_Pos
-  psh3_dimension_quantize_len( PSH_Dimension  dim,
-                               FT_Pos         len,
-                               FT_Bool        do_snapping )
-  {
-    if ( len <= 64 )
-      len = 64;
-    else
-    {
-      FT_Pos  delta = len - dim->stdw.widths[0].cur;
-
-
-      if ( delta < 0 )
-        delta = -delta;
-
-      if ( delta < 40 )
-      {
-        len = dim->stdw.widths[0].cur;
-        if ( len < 48 )
-          len = 48;
-      }
-
-      if ( len < 3 * 64 )
-      {
-        delta = ( len & 63 );
-        len  &= -64;
-
-        if ( delta < 10 )
-          len += delta;
-
-        else if ( delta < 32 )
-          len += 10;
-
-        else if ( delta < 54 )
-          len += 54;
-
-        else
-          len += delta;
-      }
-      else
-        len = ( len + 32 ) & -64;
-    }
-
-    if ( do_snapping )
-      len = ( len + 32 ) & -64;
-
-    return  len;
-  }
-#endif /* 0 */
-
-
-#ifdef DEBUG_HINTER
-
-  static void
-  ps3_simple_scale( PSH3_Hint_Table  table,
-                    FT_Fixed         scale,
-                    FT_Fixed         delta,
-                    FT_Int           dimension )
-  {
-    PSH3_Hint  hint;
-    FT_UInt    count;
-
-
-    for ( count = 0; count < table->max_hints; count++ )
-    {
-      hint = table->hints + count;
-
-      hint->cur_pos = FT_MulFix( hint->org_pos, scale ) + delta;
-      hint->cur_len = FT_MulFix( hint->org_len, scale );
-
-      if ( ps3_debug_hint_func )
-        ps3_debug_hint_func( hint, dimension );
-    }
-  }
-
-#endif /* DEBUG_HINTER */
-
-
-  static FT_Fixed
-  psh3_hint_snap_stem_side_delta( FT_Fixed  pos,
-                                  FT_Fixed  len )
-  {
-    FT_Fixed  delta1 = ( ( pos + 32 ) & -64 ) - pos;
-    FT_Fixed  delta2 = ( ( pos + len + 32 ) & -64  ) - pos - len;
-
-
-    if ( ABS( delta1 ) <= ABS( delta2 ) )
-      return delta1;
-    else
-      return delta2;
-  }
-
-
-  static void
-  psh3_hint_align( PSH3_Hint    hint,
-                   PSH_Globals  globals,
-                   FT_Int       dimension,
-                   PSH3_Glyph   glyph )
-  {
-    PSH_Dimension  dim   = &globals->dimension[dimension];
-    FT_Fixed       scale = dim->scale_mult;
-    FT_Fixed       delta = dim->scale_delta;
-
-
-    if ( !psh3_hint_is_fitted( hint ) )
-    {
-      FT_Pos  pos = FT_MulFix( hint->org_pos, scale ) + delta;
-      FT_Pos  len = FT_MulFix( hint->org_len, scale );
-
-      FT_Int            do_snapping;
-      FT_Pos            fit_len;
-      PSH_AlignmentRec  align;
-
-
-      /* ignore stem alignments when requested through the hint flags */
-      if ( ( dimension == 0 && !glyph->do_horz_hints ) ||
-           ( dimension == 1 && !glyph->do_vert_hints ) )
-      {
-        hint->cur_pos = pos;
-        hint->cur_len = len;
-
-        psh3_hint_set_fitted( hint );
-        return;
-      }
-
-      /* perform stem snapping when requested - this is necessary
-       * for monochrome and LCD hinting modes only
-       */
-      do_snapping = ( dimension == 0 && glyph->do_horz_snapping ) ||
-                    ( dimension == 1 && glyph->do_vert_snapping );
-
-      hint->cur_len = fit_len = len;
-
-      /* check blue zones for horizontal stems */
-      align.align     = PSH_BLUE_ALIGN_NONE;
-      align.align_bot = align.align_top = 0;
-
-      if ( dimension == 1 )
-        psh_blues_snap_stem( &globals->blues,
-                             hint->org_pos + hint->org_len,
-                             hint->org_pos,
-                             &align );
-
-      switch ( align.align )
-      {
-      case PSH_BLUE_ALIGN_TOP:
-        /* the top of the stem is aligned against a blue zone */
-        hint->cur_pos = align.align_top - fit_len;
-        break;
-
-      case PSH_BLUE_ALIGN_BOT:
-        /* the bottom of the stem is aligned against a blue zone */
-        hint->cur_pos = align.align_bot;
-        break;
-
-      case PSH_BLUE_ALIGN_TOP | PSH_BLUE_ALIGN_BOT:
-        /* both edges of the stem are aligned against blue zones */
-        hint->cur_pos = align.align_bot;
-        hint->cur_len = align.align_top - align.align_bot;
-        break;
-
-      default:
-        {
-          PSH3_Hint  parent = hint->parent;
-
-
-          if ( parent )
-          {
-            FT_Pos  par_org_center, par_cur_center;
-            FT_Pos  cur_org_center, cur_delta;
-
-
-            /* ensure that parent is already fitted */
-            if ( !psh3_hint_is_fitted( parent ) )
-              psh3_hint_align( parent, globals, dimension, glyph );
-
-            par_org_center = parent->org_pos + ( parent->org_len >> 1 );
-            par_cur_center = parent->cur_pos + ( parent->cur_len >> 1 );
-            cur_org_center = hint->org_pos   + ( hint->org_len   >> 1 );
-
-            cur_delta = FT_MulFix( cur_org_center - par_org_center, scale );
-            pos       = par_cur_center + cur_delta - ( len >> 1 );
-          }
-
-          hint->cur_pos = pos;
-          hint->cur_len = fit_len;
-
-          /* Stem adjustment tries to snap stem widths to standard
-           * ones.  This is important to prevent unpleasant rounding
-           * artefacts.
-           */
-          if ( glyph->do_stem_adjust )
-          {
-            if ( len <= 64 )
-            {
-              /* the stem is less than one pixel; we will center it
-               * around the nearest pixel center
-               */
-#if 1
-              pos = ( pos + ( len >> 1 ) ) & -64;
-#else
-             /* this seems to be a bug! */
-              pos = ( pos + ( ( len >> 1 ) & -64 ) );
-#endif
-              len = 64;
-            }
-            else
-            {
-              len = psh3_dimension_quantize_len( dim, len, 0 );
-            }
-          }
-
-          /* now that we have a good hinted stem width, try to position */
-          /* the stem along a pixel grid integer coordinate             */
-          hint->cur_pos = pos + psh3_hint_snap_stem_side_delta( pos, len );
-          hint->cur_len = len;
-        }
-      }
-
-      if ( do_snapping )
-      {
-        pos = hint->cur_pos;
-        len = hint->cur_len;
-
-        if ( len < 64 )
-          len = 64;
-        else
-          len = ( len + 32 ) & -64;
-
-        switch ( align.align )
-        {
-          case PSH_BLUE_ALIGN_TOP:
-            hint->cur_pos = align.align_top - len;
-            hint->cur_len = len;
-            break;
-
-          case PSH_BLUE_ALIGN_BOT:
-            hint->cur_len = len;
-            break;
-
-          case PSH_BLUE_ALIGN_BOT | PSH_BLUE_ALIGN_TOP:
-            /* don't touch */
-            break;
-
-
-          default:
-            hint->cur_len = len;
-            if ( len & 64 )
-              pos = ( ( pos + ( len >> 1 ) ) & -64 ) + 32;
-            else
-              pos = ( pos + ( len >> 1 ) + 32 ) & -64;
-
-            hint->cur_pos = pos - ( len >> 1 );
-            hint->cur_len = len;
-        }
-      }
-
-      psh3_hint_set_fitted( hint );
-
-#ifdef DEBUG_HINTER
-      if ( ps3_debug_hint_func )
-        ps3_debug_hint_func( hint, dimension );
-#endif
-    }
-  }
-
-
-#if 0  /* not used for now, experimental */
-
- /*
-  *  A variant to perform "light" hinting (i.e. FT_RENDER_MODE_LIGHT)
-  *  of stems
-  */
-  static void
-  psh3_hint_align_light( PSH3_Hint    hint,
-                         PSH_Globals  globals,
-                         FT_Int       dimension,
-                         PSH3_Glyph   glyph )
-  {
-    PSH_Dimension  dim   = &globals->dimension[dimension];
-    FT_Fixed       scale = dim->scale_mult;
-    FT_Fixed       delta = dim->scale_delta;
-
-
-    if ( !psh3_hint_is_fitted(hint) )
-    {
-      FT_Pos  pos = FT_MulFix( hint->org_pos, scale ) + delta;
-      FT_Pos  len = FT_MulFix( hint->org_len, scale );
-
-      FT_Pos  fit_len;
-
-      PSH_AlignmentRec  align;
-
-
-      /* ignore stem alignments when requested through the hint flags */
-      if ( ( dimension == 0 && !glyph->do_horz_hints ) ||
-           ( dimension == 1 && !glyph->do_vert_hints ) )
-      {
-        hint->cur_pos = pos;
-        hint->cur_len = len;
-
-        psh3_hint_set_fitted( hint );
-        return;
-      }
-
-      fit_len = len;
-
-      hint->cur_len = fit_len;
-
-      /* check blue zones for horizontal stems */
-      align.align = PSH_BLUE_ALIGN_NONE;
-      align.align_bot = align.align_top = 0;
-
-      if ( dimension == 1 )
-        psh_blues_snap_stem( &globals->blues,
-                             hint->org_pos + hint->org_len,
-                             hint->org_pos,
-                             &align );
-
-      switch ( align.align )
-      {
-      case PSH_BLUE_ALIGN_TOP:
-        /* the top of the stem is aligned against a blue zone */
-        hint->cur_pos = align.align_top - fit_len;
-        break;
-
-      case PSH_BLUE_ALIGN_BOT:
-        /* the bottom of the stem is aligned against a blue zone */
-        hint->cur_pos = align.align_bot;
-        break;
-
-      case PSH_BLUE_ALIGN_TOP | PSH_BLUE_ALIGN_BOT:
-        /* both edges of the stem are aligned against blue zones */
-        hint->cur_pos = align.align_bot;
-        hint->cur_len = align.align_top - align.align_bot;
-        break;
-
-      default:
-        {
-          PSH3_Hint  parent = hint->parent;
-
-
-          if ( parent )
-          {
-            FT_Pos  par_org_center, par_cur_center;
-            FT_Pos  cur_org_center, cur_delta;
-
-
-            /* ensure that parent is already fitted */
-            if ( !psh3_hint_is_fitted( parent ) )
-              psh3_hint_align_light( parent, globals, dimension, glyph );
-
-            par_org_center = parent->org_pos + ( parent->org_len / 2 );
-            par_cur_center = parent->cur_pos + ( parent->cur_len / 2 );
-            cur_org_center = hint->org_pos   + ( hint->org_len   / 2 );
-
-            cur_delta = FT_MulFix( cur_org_center - par_org_center, scale );
-            pos       = par_cur_center + cur_delta - ( len >> 1 );
-          }
-
-          /* Stems less than one pixel wide are easy -- we want to
-           * make them as dark as possible, so they must fall within
-           * one pixel.  If the stem is split between two pixels
-           * then snap the edge that is nearer to the pixel boundary
-           * to the pixel boundary.
-           */
-          if ( len <= 64 )
-          {
-            if ( ( pos + len + 63 ) / 64  != pos / 64 + 1 )
-              pos += psh3_hint_snap_stem_side_delta ( pos, len );
-          }
-
-          /* Position stems other to minimize the amount of mid-grays.
-           * There are, in general, two positions that do this,
-           * illustrated as A) and B) below.
-           *
-           *   +                   +                   +                   +
-           *
-           * A)             |--------------------------------|
-           * B)   |--------------------------------|
-           * C)       |--------------------------------|
-           *
-           * Position A) (split the excess stem equally) should be better
-           * for stems of width N + f where f < 0.5.
-           *
-           * Position B) (split the deficiency equally) should be better
-           * for stems of width N + f where f > 0.5.
-           *
-           * It turns out though that minimizing the total number of lit
-           * pixels is also important, so position C), with one edge
-           * aligned with a pixel boundary is actually preferable
-           * to A).  There are also more possibile positions for C) than
-           * for A) or B), so it involves less distortion of the overall
-           * character shape.
-           */
-          else /* len > 64 */
-          {
-            FT_Fixed  frac_len = len & 63;
-            FT_Fixed  center = pos + ( len >> 1 );
-            FT_Fixed  delta_a, delta_b;
-
-
-            if ( ( len / 64 ) & 1 )
-            {
-              delta_a = ( center & -64 ) + 32 - center;
-              delta_b = ( ( center + 32 ) & - 64 ) - center;
-            }
-            else
-            {
-              delta_a = ( ( center + 32 ) & - 64 ) - center;
-              delta_b = ( center & -64 ) + 32 - center;
-            }
-
-            /* We choose between B) and C) above based on the amount
-             * of fractinal stem width; for small amounts, choose
-             * C) always, for large amounts, B) always, and inbetween,
-             * pick whichever one involves less stem movement.
-             */
-            if ( frac_len < 32 )
-            {
-              pos += psh3_hint_snap_stem_side_delta ( pos, len );
-            }
-            else if ( frac_len < 48 )
-            {
-              FT_Fixed  side_delta = psh3_hint_snap_stem_side_delta ( pos,
-                                                                      len );
-
-
-              if ( ABS( side_delta ) < ABS( delta_b ) )
-                pos += side_delta;
-              else
-                pos += delta_b;
-            }
-            else
-            {
-              pos += delta_b;
-            }
-          }
-
-          hint->cur_pos = pos;
-        }
-      }  /* switch */
-
-      psh3_hint_set_fitted( hint );
-
-#ifdef DEBUG_HINTER
-      if ( ps3_debug_hint_func )
-        ps3_debug_hint_func( hint, dimension );
-#endif
-    }
-  }
-
-#endif /* 0 */
-
-
-  static void
-  psh3_hint_table_align_hints( PSH3_Hint_Table  table,
-                               PSH_Globals      globals,
-                               FT_Int           dimension,
-                               PSH3_Glyph       glyph )
-  {
-    PSH3_Hint      hint;
-    FT_UInt        count;
-
-#ifdef DEBUG_HINTER
-
-    PSH_Dimension  dim   = &globals->dimension[dimension];
-    FT_Fixed       scale = dim->scale_mult;
-    FT_Fixed       delta = dim->scale_delta;
-
-
-    if ( ps_debug_no_vert_hints && dimension == 0 )
-    {
-      ps3_simple_scale( table, scale, delta, dimension );
-      return;
-    }
-
-    if ( ps_debug_no_horz_hints && dimension == 1 )
-    {
-      ps3_simple_scale( table, scale, delta, dimension );
-      return;
-    }
-
-#endif /* DEBUG_HINTER*/
-
-    hint  = table->hints;
-    count = table->max_hints;
-
-    for ( ; count > 0; count--, hint++ )
-      psh3_hint_align( hint, globals, dimension, glyph );
-  }
-
-
-  /*************************************************************************/
-  /*************************************************************************/
-  /*****                                                               *****/
-  /*****                POINTS INTERPOLATION ROUTINES                  *****/
-  /*****                                                               *****/
-  /*************************************************************************/
-  /*************************************************************************/
-
-#define PSH3_ZONE_MIN  -3200000L
-#define PSH3_ZONE_MAX  +3200000L
-
-#define xxDEBUG_ZONES
-
-
-#ifdef DEBUG_ZONES
-
-#include <stdio.h>
-
-  static void
-  psh3_print_zone( PSH3_Zone  zone )
-  {
-    printf( "zone [scale,delta,min,max] = [%.3f,%.3f,%d,%d]\n",
-             zone->scale / 65536.0,
-             zone->delta / 64.0,
-             zone->min,
-             zone->max );
-  }
-
-#else
-
-#define psh3_print_zone( x )  do { } while ( 0 )
-
-#endif /* DEBUG_ZONES */
-
-
-  /*************************************************************************/
-  /*************************************************************************/
-  /*****                                                               *****/
-  /*****                    HINTER GLYPH MANAGEMENT                    *****/
-  /*****                                                               *****/
-  /*************************************************************************/
-  /*************************************************************************/
-
-#ifdef COMPUTE_INFLEXS
-
-  /* compute all inflex points in a given glyph */
-  static void
-  psh3_glyph_compute_inflections( PSH3_Glyph  glyph )
-  {
-    FT_UInt  n;
-
-
-    for ( n = 0; n < glyph->num_contours; n++ )
-    {
-      PSH3_Point  first, start, end, before, after;
-      FT_Angle    angle_in, angle_seg, angle_out;
-      FT_Angle    diff_in, diff_out;
-      FT_Int      finished = 0;
-
-
-      /* we need at least 4 points to create an inflection point */
-      if ( glyph->contours[n].count < 4 )
-        continue;
-
-      /* compute first segment in contour */
-      first = glyph->contours[n].start;
-
-      start = end = first;
-      do
-      {
-        end = end->next;
-        if ( end == first )
-          goto Skip;
-
-      } while ( PSH3_POINT_EQUAL_ORG( end, first ) );
-
-      angle_seg = PSH3_POINT_ANGLE( start, end );
-
-      /* extend the segment start whenever possible */
-      before = start;
-      do
-      {
-        do
-        {
-          start  = before;
-          before = before->prev;
-          if ( before == first )
-            goto Skip;
-
-        } while ( PSH3_POINT_EQUAL_ORG( before, start ) );
-
-        angle_in = PSH3_POINT_ANGLE( before, start );
-
-      } while ( angle_in == angle_seg );
-
-      first   = start;
-      diff_in = FT_Angle_Diff( angle_in, angle_seg );
-
-      /* now, process all segments in the contour */
-      do
-      {
-        /* first, extend current segment's end whenever possible */
-        after = end;
-        do
-        {
-          do
-          {
-            end   = after;
-            after = after->next;
-            if ( after == first )
-              finished = 1;
-
-          } while ( PSH3_POINT_EQUAL_ORG( end, after ) );
-
-          angle_out = PSH3_POINT_ANGLE( end, after );
-
-        } while ( angle_out == angle_seg );
-
-        diff_out = FT_Angle_Diff( angle_seg, angle_out );
-
-        if ( ( diff_in ^ diff_out ) < 0 )
-        {
-          /* diff_in and diff_out have different signs, we have */
-          /* inflection points here...                          */
-
-          do
-          {
-            psh3_point_set_inflex( start );
-            start = start->next;
-          }
-          while ( start != end );
-
-          psh3_point_set_inflex( start );
-        }
-
-        start     = end;
-        end       = after;
-        angle_seg = angle_out;
-        diff_in   = diff_out;
-
-      } while ( !finished );
-
-    Skip:
-      ;
-    }
-  }
-
-#endif /* COMPUTE_INFLEXS */
-
-
-  static void
-  psh3_glyph_done( PSH3_Glyph  glyph )
-  {
-    FT_Memory  memory = glyph->memory;
-
-
-    psh3_hint_table_done( &glyph->hint_tables[1], memory );
-    psh3_hint_table_done( &glyph->hint_tables[0], memory );
-
-    FT_FREE( glyph->points );
-    FT_FREE( glyph->contours );
-
-    glyph->num_points   = 0;
-    glyph->num_contours = 0;
-
-    glyph->memory = 0;
-  }
-
-
-  static int
-  psh3_compute_dir( FT_Pos  dx,
-                    FT_Pos  dy )
-  {
-    FT_Pos  ax, ay;
-    int     result = PSH3_DIR_NONE;
-
-
-    ax = ( dx >= 0 ) ? dx : -dx;
-    ay = ( dy >= 0 ) ? dy : -dy;
-
-    if ( ay * 12 < ax )
-    {
-      /* |dy| <<< |dx|  means a near-horizontal segment */
-      result = ( dx >= 0 ) ? PSH3_DIR_RIGHT : PSH3_DIR_LEFT;
-    }
-    else if ( ax * 12 < ay )
-    {
-      /* |dx| <<< |dy|  means a near-vertical segment */
-      result = ( dy >= 0 ) ? PSH3_DIR_UP : PSH3_DIR_DOWN;
-    }
-
-    return result;
-  }
-
-
-  /* load outline point coordinates into hinter glyph */
-  static void
-  psh3_glyph_load_points( PSH3_Glyph  glyph,
-                          FT_Int      dimension )
-  {
-    FT_Vector*  vec   = glyph->outline->points;
-    PSH3_Point  point = glyph->points;
-    FT_UInt     count = glyph->num_points;
-
-
-    for ( ; count > 0; count--, point++, vec++ )
-    {
-      point->flags2 = 0;
-      point->hint   = NULL;
-      if ( dimension == 0 )
-      {
-        point->org_u = vec->x;
-        point->org_v = vec->y;
-      }
-      else
-      {
-        point->org_u = vec->y;
-        point->org_v = vec->x;
-      }
-
-#ifdef DEBUG_HINTER
-      point->org_x = vec->x;
-      point->org_y = vec->y;
-#endif
-
-    }
-  }
-
-
-  /* save hinted point coordinates back to outline */
-  static void
-  psh3_glyph_save_points( PSH3_Glyph  glyph,
-                          FT_Int      dimension )
-  {
-    FT_UInt     n;
-    PSH3_Point  point = glyph->points;
-    FT_Vector*  vec   = glyph->outline->points;
-    char*       tags  = glyph->outline->tags;
-
-
-    for ( n = 0; n < glyph->num_points; n++ )
-    {
-      if ( dimension == 0 )
-        vec[n].x = point->cur_u;
-      else
-        vec[n].y = point->cur_u;
-
-      if ( psh3_point_is_strong( point ) )
-        tags[n] |= (char)( ( dimension == 0 ) ? 32 : 64 );
-
-#ifdef DEBUG_HINTER
-
-      if ( dimension == 0 )
-      {
-        point->cur_x   = point->cur_u;
-        point->flags_x = point->flags2 | point->flags;
-      }
-      else
-      {
-        point->cur_y   = point->cur_u;
-        point->flags_y = point->flags2 | point->flags;
-      }
-
-#endif
-
-      point++;
-    }
-  }
-
-
-  static FT_Error
-  psh3_glyph_init( PSH3_Glyph   glyph,
-                   FT_Outline*  outline,
-                   PS_Hints     ps_hints,
-                   PSH_Globals  globals )
-  {
-    FT_Error   error;
-    FT_Memory  memory;
-
-
-    /* clear all fields */
-    FT_MEM_ZERO( glyph, sizeof ( *glyph ) );
-
-    memory = globals->memory;
-
-    /* allocate and setup points + contours arrays */
-    if ( FT_NEW_ARRAY( glyph->points,   outline->n_points   ) ||
-         FT_NEW_ARRAY( glyph->contours, outline->n_contours ) )
-      goto Exit;
-
-    glyph->num_points   = outline->n_points;
-    glyph->num_contours = outline->n_contours;
-
-    {
-      FT_UInt       first = 0, next, n;
-      PSH3_Point    points  = glyph->points;
-      PSH3_Contour  contour = glyph->contours;
-
-
-      for ( n = 0; n < glyph->num_contours; n++ )
-      {
-        FT_Int      count;
-        PSH3_Point  point;
-
-
-        next  = outline->contours[n] + 1;
-        count = next - first;
-
-        contour->start = points + first;
-        contour->count = (FT_UInt)count;
-
-        if ( count > 0 )
-        {
-          point = points + first;
-
-          point->prev    = points + next - 1;
-          point->contour = contour;
-
-          for ( ; count > 1; count-- )
-          {
-            point[0].next = point + 1;
-            point[1].prev = point;
-            point++;
-            point->contour = contour;
-          }
-          point->next = points + first;
-        }
-
-        contour++;
-        first = next;
-      }
-    }
-
-    {
-      PSH3_Point  points = glyph->points;
-      PSH3_Point  point  = points;
-      FT_Vector*  vec    = outline->points;
-      FT_UInt     n;
-
-
-      for ( n = 0; n < glyph->num_points; n++, point++ )
-      {
-        FT_Int  n_prev = point->prev - points;
-        FT_Int  n_next = point->next - points;
-        FT_Pos  dxi, dyi, dxo, dyo;
-
-
-        if ( !( outline->tags[n] & FT_CURVE_TAG_ON ) )
-          point->flags = PSH3_POINT_OFF;
-
-        dxi = vec[n].x - vec[n_prev].x;
-        dyi = vec[n].y - vec[n_prev].y;
-
-        point->dir_in = (FT_Char)psh3_compute_dir( dxi, dyi );
-
-        dxo = vec[n_next].x - vec[n].x;
-        dyo = vec[n_next].y - vec[n].y;
-
-        point->dir_out = (FT_Char)psh3_compute_dir( dxo, dyo );
-
-        /* detect smooth points */
-        if ( point->flags & PSH3_POINT_OFF )
-          point->flags |= PSH3_POINT_SMOOTH;
-        else if ( point->dir_in  != PSH3_DIR_NONE ||
-                  point->dir_out != PSH3_DIR_NONE )
-        {
-          if ( point->dir_in == point->dir_out )
-            point->flags |= PSH3_POINT_SMOOTH;
-        }
-        else
-        {
-          FT_Angle  angle_in, angle_out, diff;
-
-
-          angle_in  = FT_Atan2( dxi, dyi );
-          angle_out = FT_Atan2( dxo, dyo );
-
-          diff = angle_in - angle_out;
-          if ( diff < 0 )
-            diff = -diff;
-
-          if ( diff > FT_ANGLE_PI )
-            diff = FT_ANGLE_2PI - diff;
-
-          if ( diff < FT_ANGLE_PI / 16 )
-            point->flags |= PSH3_POINT_SMOOTH;
-        }
-      }
-    }
-
-    glyph->memory  = memory;
-    glyph->outline = outline;
-    glyph->globals = globals;
-
-#ifdef COMPUTE_INFLEXS
-    psh3_glyph_load_points( glyph, 0 );
-    psh3_glyph_compute_inflections( glyph );
-#endif /* COMPUTE_INFLEXS */
-
-    /* now deal with hints tables */
-    error = psh3_hint_table_init( &glyph->hint_tables [0],
-                                  &ps_hints->dimension[0].hints,
-                                  &ps_hints->dimension[0].masks,
-                                  &ps_hints->dimension[0].counters,
-                                  memory );
-    if ( error )
-      goto Exit;
-
-    error = psh3_hint_table_init( &glyph->hint_tables [1],
-                                  &ps_hints->dimension[1].hints,
-                                  &ps_hints->dimension[1].masks,
-                                  &ps_hints->dimension[1].counters,
-                                  memory );
-    if ( error )
-      goto Exit;
-
-  Exit:
-    return error;
-  }
-
-
-  /* compute all extrema in a glyph for a given dimension */
-  static void
-  psh3_glyph_compute_extrema( PSH3_Glyph  glyph )
-  {
-    FT_UInt  n;
-
-
-    /* first of all, compute all local extrema */
-    for ( n = 0; n < glyph->num_contours; n++ )
-    {
-      PSH3_Point  first = glyph->contours[n].start;
-      PSH3_Point  point, before, after;
-
-
-      if ( glyph->contours[n].count == 0 )
-        continue;
-
-      point  = first;
-      before = point;
-      after  = point;
-
-      do
-      {
-        before = before->prev;
-        if ( before == first )
-          goto Skip;
-
-      } while ( before->org_u == point->org_u );
-
-      first = point = before->next;
-
-      for (;;)
-      {
-        after = point;
-        do
-        {
-          after = after->next;
-          if ( after == first )
-            goto Next;
-
-        } while ( after->org_u == point->org_u );
-
-        if ( before->org_u < point->org_u )
-        {
-          if ( after->org_u < point->org_u )
-          {
-            /* local maximum */
-            goto Extremum;
-          }
-        }
-        else /* before->org_u > point->org_u */
-        {
-          if ( after->org_u > point->org_u )
-          {
-            /* local minimum */
-          Extremum:
-            do
-            {
-              psh3_point_set_extremum( point );
-              point = point->next;
-
-            } while ( point != after );
-          }
-        }
-
-        before = after->prev;
-        point  = after;
-
-      } /* for  */
-
-    Next:
-      ;
-    }
-
-    /* for each extrema, determine its direction along the */
-    /* orthogonal axis                                     */
-    for ( n = 0; n < glyph->num_points; n++ )
-    {
-      PSH3_Point  point, before, after;
-
-
-      point  = &glyph->points[n];
-      before = point;
-      after  = point;
-
-      if ( psh3_point_is_extremum( point ) )
-      {
-        do
-        {
-          before = before->prev;
-          if ( before == point )
-            goto Skip;
-
-        } while ( before->org_v == point->org_v );
-
-        do
-        {
-          after = after->next;
-          if ( after == point )
-            goto Skip;
-
-        } while ( after->org_v == point->org_v );
-      }
-
-      if ( before->org_v < point->org_v &&
-           after->org_v  > point->org_v )
-      {
-        psh3_point_set_positive( point );
-      }
-      else if ( before->org_v > point->org_v &&
-                after->org_v  < point->org_v )
-      {
-        psh3_point_set_negative( point );
-      }
-
-    Skip:
-      ;
-    }
-  }
-
-
-#define PSH3_STRONG_THRESHOLD  30
-
-
-  /* major_dir is the direction for points on the bottom/left of the stem; */
-  /* Points on the top/right of the stem will have a direction of          */
-  /* -major_dir.                                                           */
-
-  static void
-  psh3_hint_table_find_strong_point( PSH3_Hint_Table  table,
-                                     PSH3_Point       point,
-                                     FT_Int           major_dir )
-  {
-    PSH3_Hint*  sort      = table->sort;
-    FT_UInt     num_hints = table->num_hints;
-    FT_Int      point_dir = 0;
-
-
-    if ( PSH3_DIR_COMPARE( point->dir_in, major_dir ) )
-      point_dir = point->dir_in;
-
-    else if ( PSH3_DIR_COMPARE( point->dir_out, major_dir ) )
-      point_dir = point->dir_out;
-
-    if ( point_dir )
-    {
-      FT_UInt  flag;
-
-
-      for ( ; num_hints > 0; num_hints--, sort++ )
-      {
-        PSH3_Hint  hint = sort[0];
-        FT_Pos     d;
-
-
-        if ( point_dir == major_dir )
-        {
-          flag = PSH3_POINT_EDGE_MIN;
-          d    = point->org_u - hint->org_pos;
-
-          if ( ABS( d ) < PSH3_STRONG_THRESHOLD )
-          {
-          Is_Strong:
-            psh3_point_set_strong( point );
-            point->flags2 |= flag;
-            point->hint    = hint;
-            break;
-          }
-        }
-        else if ( point_dir == -major_dir )
-        {
-          flag  = PSH3_POINT_EDGE_MAX;
-          d     = point->org_u - hint->org_pos - hint->org_len;
-
-          if ( ABS( d ) < PSH3_STRONG_THRESHOLD )
-            goto Is_Strong;
-        }
-      }
-    }
-
-#if 1
-    else if ( psh3_point_is_extremum( point ) )
-    {
-      /* treat extrema as special cases for stem edge alignment */
-      FT_UInt  min_flag, max_flag;
-
-
-      if ( major_dir == PSH3_DIR_HORIZONTAL )
-      {
-        min_flag = PSH3_POINT_POSITIVE;
-        max_flag = PSH3_POINT_NEGATIVE;
-      }
-      else
-      {
-        min_flag = PSH3_POINT_NEGATIVE;
-        max_flag = PSH3_POINT_POSITIVE;
-      }
-
-      for ( ; num_hints > 0; num_hints--, sort++ )
-      {
-        PSH3_Hint  hint = sort[0];
-        FT_Pos     d, flag;
-
-
-        if ( point->flags2 & min_flag )
-        {
-          flag = PSH3_POINT_EDGE_MIN;
-          d    = point->org_u - hint->org_pos;
-
-          if ( ABS( d ) < PSH3_STRONG_THRESHOLD )
-          {
-          Is_Strong2:
-            point->flags2 |= flag;
-            point->hint    = hint;
-            psh3_point_set_strong( point );
-            break;
-          }
-        }
-        else if ( point->flags2 & max_flag )
-        {
-          flag = PSH3_POINT_EDGE_MAX;
-          d    = point->org_u - hint->org_pos - hint->org_len;
-
-          if ( ABS( d ) < PSH3_STRONG_THRESHOLD )
-            goto Is_Strong2;
-        }
-
-        if ( point->org_u >= hint->org_pos                 &&
-             point->org_u <= hint->org_pos + hint->org_len )
-        {
-          point->hint = hint;
-        }
-      }
-    }
-
-#endif /* 1 */
-  }
-
-
-  /* find strong points in a glyph */
-  static void
-  psh3_glyph_find_strong_points( PSH3_Glyph  glyph,
-                                 FT_Int      dimension )
-  {
-    /* a point is strong if it is located on a stem                   */
-    /* edge and has an "in" or "out" tangent to the hint's direction  */
-    {
-      PSH3_Hint_Table  table     = &glyph->hint_tables[dimension];
-      PS_Mask          mask      = table->hint_masks->masks;
-      FT_UInt          num_masks = table->hint_masks->num_masks;
-      FT_UInt          first     = 0;
-      FT_Int           major_dir = dimension == 0 ? PSH3_DIR_VERTICAL
-                                                  : PSH3_DIR_HORIZONTAL;
-
-
-      /* process secondary hints to "selected" points */
-      if ( num_masks > 1 && glyph->num_points > 0 )
-      {
-        first = mask->end_point;
-        mask++;
-        for ( ; num_masks > 1; num_masks--, mask++ )
-        {
-          FT_UInt  next;
-          FT_Int   count;
-
-
-          next  = mask->end_point;
-          count = next - first;
-          if ( count > 0 )
-          {
-            PSH3_Point  point = glyph->points + first;
-
-
-            psh3_hint_table_activate_mask( table, mask );
-
-            for ( ; count > 0; count--, point++ )
-              psh3_hint_table_find_strong_point( table, point, major_dir );
-          }
-          first = next;
-        }
-      }
-
-      /* process primary hints for all points */
-      if ( num_masks == 1 )
-      {
-        FT_UInt     count = glyph->num_points;
-        PSH3_Point  point = glyph->points;
-
-
-        psh3_hint_table_activate_mask( table, table->hint_masks->masks );
-        for ( ; count > 0; count--, point++ )
-        {
-          if ( !psh3_point_is_strong( point ) )
-            psh3_hint_table_find_strong_point( table, point, major_dir );
-        }
-      }
-
-      /* now, certain points may have been attached to hint and */
-      /* not marked as strong; update their flags then          */
-      {
-        FT_UInt     count = glyph->num_points;
-        PSH3_Point  point = glyph->points;
-
-
-        for ( ; count > 0; count--, point++ )
-          if ( point->hint && !psh3_point_is_strong( point ) )
-            psh3_point_set_strong( point );
-      }
-    }
-  }
-
-
-  /* interpolate strong points with the help of hinted coordinates */
-  static void
-  psh3_glyph_interpolate_strong_points( PSH3_Glyph  glyph,
-                                        FT_Int      dimension )
-  {
-    PSH_Dimension  dim   = &glyph->globals->dimension[dimension];
-    FT_Fixed       scale = dim->scale_mult;
-
-
-    {
-      FT_UInt     count = glyph->num_points;
-      PSH3_Point  point = glyph->points;
-
-
-      for ( ; count > 0; count--, point++ )
-      {
-        PSH3_Hint  hint = point->hint;
-
-
-        if ( hint )
-        {
-          FT_Pos  delta;
-
-
-          if ( psh3_point_is_edge_min( point ) )
-          {
-            point->cur_u = hint->cur_pos;
-          }
-          else if ( psh3_point_is_edge_max( point ) )
-          {
-            point->cur_u = hint->cur_pos + hint->cur_len;
-          }
-          else
-          {
-            delta = point->org_u - hint->org_pos;
-
-            if ( delta <= 0 )
-              point->cur_u = hint->cur_pos + FT_MulFix( delta, scale );
-
-            else if ( delta >= hint->org_len )
-              point->cur_u = hint->cur_pos + hint->cur_len +
-                               FT_MulFix( delta - hint->org_len, scale );
-
-            else if ( hint->org_len > 0 )
-              point->cur_u = hint->cur_pos +
-                               FT_MulDiv( delta, hint->cur_len,
-                                          hint->org_len );
-            else
-              point->cur_u = hint->cur_pos;
-          }
-          psh3_point_set_fitted( point );
-        }
-      }
-    }
-  }
-
-
-  static void
-  psh3_glyph_interpolate_normal_points( PSH3_Glyph  glyph,
-                                        FT_Int      dimension )
-  {
-
-#if 1
-
-    PSH_Dimension  dim   = &glyph->globals->dimension[dimension];
-    FT_Fixed       scale = dim->scale_mult;
-
-
-    /* first technique: a point is strong if it is a local extrema */
-    {
-      FT_UInt     count = glyph->num_points;
-      PSH3_Point  point = glyph->points;
-
-
-      for ( ; count > 0; count--, point++ )
-      {
-        if ( psh3_point_is_strong( point ) )
-          continue;
-
-        /* sometimes, some local extremas are smooth points */
-        if ( psh3_point_is_smooth( point ) )
-        {
-          if ( point->dir_in == PSH3_DIR_NONE  ||
-               point->dir_in != point->dir_out )
-            continue;
-
-          if ( !psh3_point_is_extremum( point )   &&
-               !psh3_point_is_inflex( point ) )
-            continue;
-
-          point->flags &= ~PSH3_POINT_SMOOTH;
-        }
-
-        /* find best enclosing point coordinates */
-        {
-          PSH3_Point  before = 0;
-          PSH3_Point  after  = 0;
-
-          FT_Pos      diff_before = -32000;
-          FT_Pos      diff_after  =  32000;
-          FT_Pos      u = point->org_u;
-
-          FT_Int      count2 = glyph->num_points;
-          PSH3_Point  cur    = glyph->points;
-
-
-          for ( ; count2 > 0; count2--, cur++ )
-          {
-            if ( psh3_point_is_strong( cur ) )
-            {
-              FT_Pos  diff = cur->org_u - u;;
-
-
-              if ( diff <= 0 )
-              {
-                if ( diff > diff_before )
-                {
-                  diff_before = diff;
-                  before      = cur;
-                }
-              }
-              else if ( diff >= 0 )
-              {
-                if ( diff < diff_after )
-                {
-                  diff_after = diff;
-                  after      = cur;
-                }
-              }
-            }
-          }
-
-          if ( !before )
-          {
-            if ( !after )
-              continue;
-
-            /* we are before the first strong point coordinate; */
-            /* simply translate the point                       */
-            point->cur_u = after->cur_u +
-                           FT_MulFix( point->org_u - after->org_u, scale );
-          }
-          else if ( !after )
-          {
-            /* we are after the last strong point coordinate; */
-            /* simply translate the point                     */
-            point->cur_u = before->cur_u +
-                           FT_MulFix( point->org_u - before->org_u, scale );
-          }
-          else
-          {
-            if ( diff_before == 0 )
-              point->cur_u = before->cur_u;
-
-            else if ( diff_after == 0 )
-              point->cur_u = after->cur_u;
-
-            else
-              point->cur_u = before->cur_u +
-                             FT_MulDiv( u - before->org_u,
-                                        after->cur_u - before->cur_u,
-                                        after->org_u - before->org_u );
-          }
-
-          psh3_point_set_fitted( point );
-        }
-      }
-    }
-
-#endif /* 1 */
-
-  }
-
-
-  /* interpolate other points */
-  static void
-  psh3_glyph_interpolate_other_points( PSH3_Glyph  glyph,
-                                       FT_Int      dimension )
-  {
-    PSH_Dimension  dim          = &glyph->globals->dimension[dimension];
-    FT_Fixed       scale        = dim->scale_mult;
-    FT_Fixed       delta        = dim->scale_delta;
-    PSH3_Contour   contour      = glyph->contours;
-    FT_UInt        num_contours = glyph->num_contours;
-
-
-    for ( ; num_contours > 0; num_contours--, contour++ )
-    {
-      PSH3_Point  start = contour->start;
-      PSH3_Point  first, next, point;
-      FT_UInt     fit_count;
-
-
-      /* count the number of strong points in this contour */
-      next      = start + contour->count;
-      fit_count = 0;
-      first     = 0;
-
-      for ( point = start; point < next; point++ )
-        if ( psh3_point_is_fitted( point ) )
-        {
-          if ( !first )
-            first = point;
-
-          fit_count++;
-        }
-
-      /* if there are less than 2 fitted points in the contour, we */
-      /* simply scale and eventually translate the contour points  */
-      if ( fit_count < 2 )
-      {
-        if ( fit_count == 1 )
-          delta = first->cur_u - FT_MulFix( first->org_u, scale );
-
-        for ( point = start; point < next; point++ )
-          if ( point != first )
-            point->cur_u = FT_MulFix( point->org_u, scale ) + delta;
-
-        goto Next_Contour;
-      }
-
-      /* there are more than 2 strong points in this contour; we */
-      /* need to interpolate weak points between them            */
-      start = first;
-      do
-      {
-        point = first;
-
-        /* skip consecutive fitted points */
-        for (;;)
-        {
-          next = first->next;
-          if ( next == start )
-            goto Next_Contour;
-
-          if ( !psh3_point_is_fitted( next ) )
-            break;
-
-          first = next;
-        }
-
-        /* find next fitted point after unfitted one */
-        for (;;)
-        {
-          next = next->next;
-          if ( psh3_point_is_fitted( next ) )
-            break;
-        }
-
-        /* now interpolate between them */
-        {
-          FT_Pos    org_a, org_ab, cur_a, cur_ab;
-          FT_Pos    org_c, org_ac, cur_c;
-          FT_Fixed  scale_ab;
-
-
-          if ( first->org_u <= next->org_u )
-          {
-            org_a  = first->org_u;
-            cur_a  = first->cur_u;
-            org_ab = next->org_u - org_a;
-            cur_ab = next->cur_u - cur_a;
-          }
-          else
-          {
-            org_a  = next->org_u;
-            cur_a  = next->cur_u;
-            org_ab = first->org_u - org_a;
-            cur_ab = first->cur_u - cur_a;
-          }
-
-          scale_ab = 0x10000L;
-          if ( org_ab > 0 )
-            scale_ab = FT_DivFix( cur_ab, org_ab );
-
-          point = first->next;
-          do
-          {
-            org_c  = point->org_u;
-            org_ac = org_c - org_a;
-
-            if ( org_ac <= 0 )
-            {
-              /* on the left of the interpolation zone */
-              cur_c = cur_a + FT_MulFix( org_ac, scale );
-            }
-            else if ( org_ac >= org_ab )
-            {
-              /* on the right on the interpolation zone */
-              cur_c = cur_a + cur_ab + FT_MulFix( org_ac - org_ab, scale );
-            }
-            else
-            {
-              /* within the interpolation zone */
-              cur_c = cur_a + FT_MulFix( org_ac, scale_ab );
-            }
-
-            point->cur_u = cur_c;
-
-            point = point->next;
-
-          } while ( point != next );
-        }
-
-        /* keep going until all points in the contours have been processed */
-        first = next;
-
-      } while ( first != start );
-
-    Next_Contour:
-      ;
-    }
-  }
-
-
-  /*************************************************************************/
-  /*************************************************************************/
-  /*****                                                               *****/
-  /*****                     HIGH-LEVEL INTERFACE                      *****/
-  /*****                                                               *****/
-  /*************************************************************************/
-  /*************************************************************************/
-
-  FT_Error
-  ps3_hints_apply( PS_Hints        ps_hints,
-                   FT_Outline*     outline,
-                   PSH_Globals     globals,
-                   FT_Render_Mode  hint_mode )
-  {
-    PSH3_GlyphRec  glyphrec;
-    PSH3_Glyph     glyph = &glyphrec;
-    FT_Error       error;
-#ifdef DEBUG_HINTER
-    FT_Memory      memory;
-#endif
-    FT_Int         dimension;
-
-
-    /* something to do? */
-    if ( outline->n_points == 0 || outline->n_contours == 0 )
-      return FT_Err_Ok;
-
-#ifdef DEBUG_HINTER
-
-    memory = globals->memory;
-
-    if ( ps3_debug_glyph )
-    {
-      psh3_glyph_done( ps3_debug_glyph );
-      FT_FREE( ps3_debug_glyph );
-    }
-
-    if ( FT_NEW( glyph ) )
-      return error;
-
-    ps3_debug_glyph = glyph;
-
-#endif /* DEBUG_HINTER */
-
-    error = psh3_glyph_init( glyph, outline, ps_hints, globals );
-    if ( error )
-      goto Exit;
-
-    /* try to optimize the y_scale so that the top of non-capital letters
-     * is aligned on a pixel boundary whenever possible
-     */
-    {
-      PSH_Dimension  dim_x = &glyph->globals->dimension[0];
-      PSH_Dimension  dim_y = &glyph->globals->dimension[1];
-
-      FT_Fixed x_scale = dim_x->scale_mult;
-      FT_Fixed y_scale = dim_y->scale_mult;
-
-      FT_Fixed scaled;
-      FT_Fixed fitted;
-
-
-      scaled = FT_MulFix( globals->blues.normal_top.zones->org_ref, y_scale );
-      fitted = ( scaled + 32 ) & -64;
-
-      if (scaled != fitted ) {
-        y_scale = FT_MulDiv( y_scale, fitted, scaled );
-
-        if ( fitted < scaled )
-          x_scale -= x_scale / 50;
-
-        psh_globals_set_scale( glyph->globals, x_scale, y_scale, 0, 0 );
-      }
-    }
-
-    glyph->do_horz_hints = 1;
-    glyph->do_vert_hints = 1;
-
-    glyph->do_horz_snapping = FT_BOOL( hint_mode == FT_RENDER_MODE_MONO ||
-                                       hint_mode == FT_RENDER_MODE_LCD  );
-
-    glyph->do_vert_snapping = FT_BOOL( hint_mode == FT_RENDER_MODE_MONO  ||
-                                       hint_mode == FT_RENDER_MODE_LCD_V );
-
-    glyph->do_stem_adjust   = FT_BOOL( hint_mode != FT_RENDER_MODE_LIGHT );
-
-    for ( dimension = 0; dimension < 2; dimension++ )
-    {
-      /* load outline coordinates into glyph */
-      psh3_glyph_load_points( glyph, dimension );
-
-      /* compute local extrema */
-      psh3_glyph_compute_extrema( glyph );
-
-      /* compute aligned stem/hints positions */
-      psh3_hint_table_align_hints( &glyph->hint_tables[dimension],
-                                   glyph->globals,
-                                   dimension,
-                                   glyph );
-
-      /* find strong points, align them, then interpolate others */
-      psh3_glyph_find_strong_points( glyph, dimension );
-      psh3_glyph_interpolate_strong_points( glyph, dimension );
-      psh3_glyph_interpolate_normal_points( glyph, dimension );
-      psh3_glyph_interpolate_other_points( glyph, dimension );
-
-      /* save hinted coordinates back to outline */
-      psh3_glyph_save_points( glyph, dimension );
-    }
-
-  Exit:
-
-#ifndef DEBUG_HINTER
-    psh3_glyph_done( glyph );
-#endif
-
-    return error;
-  }
-
-
-/* END */
--- a/src/pshinter/pshalgo3.h
+++ /dev/null
@@ -1,255 +1,0 @@
-/***************************************************************************/
-/*                                                                         */
-/*  pshalgo3.h                                                             */
-/*                                                                         */
-/*    PostScript hinting algorithm 3 (specification).                      */
-/*                                                                         */
-/*  Copyright 2001, 2002 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.                                        */
-/*                                                                         */
-/***************************************************************************/
-
-
-#ifndef __PSHALGO3_H__
-#define __PSHALGO3_H__
-
-
-#include "pshrec.h"
-#include "pshglob.h"
-#include FT_TRIGONOMETRY_H
-
-
-FT_BEGIN_HEADER
-
-
-  /* handle to Hint structure */
-  typedef struct PSH3_HintRec_*  PSH3_Hint;
-
-  /* hint bit-flags */
-  typedef enum
-  {
-    PSH3_HINT_GHOST  = PS_HINT_FLAG_GHOST,
-    PSH3_HINT_BOTTOM = PS_HINT_FLAG_BOTTOM,
-    PSH3_HINT_ACTIVE = 4,
-    PSH3_HINT_FITTED = 8
-
-  } PSH3_Hint_Flags;
-
-
-#define psh3_hint_is_active( x )  ( ( (x)->flags & PSH3_HINT_ACTIVE ) != 0 )
-#define psh3_hint_is_ghost( x )   ( ( (x)->flags & PSH3_HINT_GHOST  ) != 0 )
-#define psh3_hint_is_fitted( x )  ( ( (x)->flags & PSH3_HINT_FITTED ) != 0 )
-
-#define psh3_hint_activate( x )    (x)->flags |=  PSH3_HINT_ACTIVE
-#define psh3_hint_deactivate( x )  (x)->flags &= ~PSH3_HINT_ACTIVE
-#define psh3_hint_set_fitted( x )  (x)->flags |=  PSH3_HINT_FITTED
-
-  /* hint structure */
-  typedef struct  PSH3_HintRec_
-  {
-    FT_Int     org_pos;
-    FT_Int     org_len;
-    FT_Pos     cur_pos;
-    FT_Pos     cur_len;
-    FT_UInt    flags;
-    PSH3_Hint  parent;
-    FT_Int     order;
-
-  } PSH3_HintRec;
-
-
-  /* this is an interpolation zone used for strong points;  */
-  /* weak points are interpolated according to their strong */
-  /* neighbours                                             */
-  typedef struct  PSH3_ZoneRec_
-  {
-    FT_Fixed  scale;
-    FT_Fixed  delta;
-    FT_Pos    min;
-    FT_Pos    max;
-
-  } PSH3_ZoneRec, *PSH3_Zone;
-
-
-  typedef struct  PSH3_Hint_TableRec_
-  {
-    FT_UInt        max_hints;
-    FT_UInt        num_hints;
-    PSH3_Hint      hints;
-    PSH3_Hint*     sort;
-    PSH3_Hint*     sort_global;
-    FT_UInt        num_zones;
-    PSH3_ZoneRec*  zones;
-    PSH3_Zone      zone;
-    PS_Mask_Table  hint_masks;
-    PS_Mask_Table  counter_masks;
-
-  } PSH3_Hint_TableRec, *PSH3_Hint_Table;
-
-
-  typedef struct PSH3_PointRec_*    PSH3_Point;
-  typedef struct PSH3_ContourRec_*  PSH3_Contour;
-
-  enum
-  {
-    PSH3_DIR_NONE  =  4,
-    PSH3_DIR_UP    = -1,
-    PSH3_DIR_DOWN  =  1,
-    PSH3_DIR_LEFT  = -2,
-    PSH3_DIR_RIGHT =  2
-  };
-
-#define PSH3_DIR_HORIZONTAL  2
-#define PSH3_DIR_VERTICAL    1
-
-#define PSH3_DIR_COMPARE( d1, d2 )  ( (d1) == (d2) || (d1) == -(d2) )
-#define PSH3_DIR_IS_HORIZONTAL( d )  PSH3_DIR_COMPARE( d, PSH3_DIR_HORIZONTAL )
-#define PSH3_DIR_IS_VERTICAL( d )    PSH3_DIR_COMPARE( d, PSH3_DIR_VERTICAL )
-
-
- /* the following bit-flags are computed once by the glyph */
- /* analyzer, for both dimensions                          */
-  enum
-  {
-    PSH3_POINT_OFF         = 1,   /* point is off the curve          */
-    PSH3_POINT_SMOOTH      = 2,   /* point is smooth                 */
-    PSH3_POINT_INFLEX      = 4    /* point is inflection             */
-  };
-
-#define psh3_point_is_smooth( p )  ( (p)->flags & PSH3_POINT_SMOOTH )
-#define psh3_point_is_off( p )     ( (p)->flags & PSH3_POINT_OFF    )
-#define psh3_point_is_inflex( p )  ( (p)->flags & PSH3_POINT_INFLEX )
-
-#define psh3_point_set_smooth( p )  (p)->flags |= PSH3_POINT_SMOOTH
-#define psh3_point_set_off( p )     (p)->flags |= PSH3_POINT_OFF
-#define psh3_point_set_inflex( p )  (p)->flags |= PSH3_POINT_INFLEX
-
-  /* the following bit-flags are re-computed for each dimension */
-  enum
-  {
-    PSH3_POINT_STRONG   = 16,   /* point is strong                             */
-    PSH3_POINT_FITTED   = 32,   /* point is already fitted                     */
-    PSH3_POINT_EXTREMUM = 64,   /* point is local extremum                     */
-    PSH3_POINT_POSITIVE = 128,  /* extremum has positive contour flow          */
-    PSH3_POINT_NEGATIVE = 256,  /* extremum has negative contour flow          */
-    PSH3_POINT_EDGE_MIN = 512,  /* point is aligned to left/bottom stem edge   */
-    PSH3_POINT_EDGE_MAX = 1024  /* point is aligned to top/right stem edge     */
-  };
-
-#define psh3_point_is_strong( p )    ( (p)->flags2 & PSH3_POINT_STRONG )
-#define psh3_point_is_fitted( p )    ( (p)->flags2 & PSH3_POINT_FITTED )
-#define psh3_point_is_extremum( p )  ( (p)->flags2 & PSH3_POINT_EXTREMUM )
-#define psh3_point_is_positive( p )  ( (p)->flags2 & PSH3_POINT_POSITIVE )
-#define psh3_point_is_negative( p )  ( (p)->flags2 & PSH3_POINT_NEGATIVE )
-#define psh3_point_is_edge_min( p )  ( (p)->flags2 & PSH3_POINT_EDGE_MIN )
-#define psh3_point_is_edge_max( p )  ( (p)->flags2 & PSH3_POINT_EDGE_MAX )
-
-#define psh3_point_set_strong( p )    (p)->flags2 |= PSH3_POINT_STRONG
-#define psh3_point_set_fitted( p )    (p)->flags2 |= PSH3_POINT_FITTED
-#define psh3_point_set_extremum( p )  (p)->flags2 |= PSH3_POINT_EXTREMUM
-#define psh3_point_set_positive( p )  (p)->flags2 |= PSH3_POINT_POSITIVE
-#define psh3_point_set_negative( p )  (p)->flags2 |= PSH3_POINT_NEGATIVE
-#define psh3_point_set_edge_min( p )  (p)->flags2 |= PSH3_POINT_EDGE_MIN
-#define psh3_point_set_edge_max( p )  (p)->flags2 |= PSH3_POINT_EDGE_MAX
-
-
-  typedef struct  PSH3_PointRec_
-  {
-    PSH3_Point    prev;
-    PSH3_Point    next;
-    PSH3_Contour  contour;
-    FT_UInt       flags;
-    FT_UInt       flags2;
-    FT_Char       dir_in;
-    FT_Char       dir_out;
-    FT_Angle      angle_in;
-    FT_Angle      angle_out;
-    PSH3_Hint     hint;
-    FT_Pos        org_u;
-    FT_Pos        org_v;
-    FT_Pos        cur_u;
-#ifdef DEBUG_HINTER
-    FT_Pos        org_x;
-    FT_Pos        cur_x;
-    FT_Pos        org_y;
-    FT_Pos        cur_y;
-    FT_UInt       flags_x;
-    FT_UInt       flags_y;
-#endif
-
-  } PSH3_PointRec;
-
-
-#define PSH3_POINT_EQUAL_ORG( a, b )  ( (a)->org_u == (b)->org_u && \
-                                        (a)->org_v == (b)->org_v )
-
-#define PSH3_POINT_ANGLE( a, b )  FT_Atan2( (b)->org_u - (a)->org_u,  \
-                                            (b)->org_v - (a)->org_v )
-
-  typedef struct  PSH3_ContourRec_
-  {
-    PSH3_Point  start;
-    FT_UInt     count;
-
-  } PSH3_ContourRec;
-
-
-  typedef struct  PSH3_GlyphRec_
-  {
-    FT_UInt             num_points;
-    FT_UInt             num_contours;
-
-    PSH3_Point          points;
-    PSH3_Contour        contours;
-
-    FT_Memory           memory;
-    FT_Outline*         outline;
-    PSH_Globals         globals;
-    PSH3_Hint_TableRec  hint_tables[2];
-
-    FT_Bool             vertical;
-    FT_Int              major_dir;
-    FT_Int              minor_dir;
-
-    FT_Bool             do_horz_hints;
-    FT_Bool             do_vert_hints;
-    FT_Bool             do_horz_snapping;
-    FT_Bool             do_vert_snapping;
-    FT_Bool             do_stem_adjust;
-
-  } PSH3_GlyphRec, *PSH3_Glyph;
-
-
-#ifdef DEBUG_HINTER
-  extern PSH3_Hint_Table  ps3_debug_hint_table;
-
-  typedef void
-  (*PSH3_HintFunc)( PSH3_Hint  hint,
-                    FT_Bool    vertical );
-
-  extern PSH3_HintFunc    ps3_debug_hint_func;
-
-  extern PSH3_Glyph       ps3_debug_glyph;
-#endif
-
-
-  extern FT_Error
-  ps3_hints_apply( PS_Hints        ps_hints,
-                   FT_Outline*     outline,
-                   PSH_Globals     globals,
-                   FT_Render_Mode  hint_mode );
-
-
-FT_END_HEADER
-
-
-#endif /* __PSHALGO3_H__ */
-
-
-/* END */
--- a/src/pshinter/pshglob.c
+++ b/src/pshinter/pshglob.c
@@ -5,7 +5,7 @@
 /*    PostScript hinter global hinting management (body).                  */
 /*    Inspired by the new auto-hinter module.                              */
 /*                                                                         */
-/*  Copyright 2001, 2002 by                                                */
+/*  Copyright 2001, 2002, 2003 by                                          */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used        */
@@ -78,6 +78,8 @@
   }
 
 
+#if 0
+
   /* org_width is is font units, result in device pixels, 26.6 format */
   FT_LOCAL_DEF( FT_Pos )
   psh_dimension_snap_width( PSH_Dimension  dimension,
@@ -121,6 +123,8 @@
 
     return width;
   }
+
+#endif /* 0 */
 
 
   /*************************************************************************/
--- a/src/pshinter/pshglob.h
+++ b/src/pshinter/pshglob.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    PostScript hinter global hinting management.                         */
 /*                                                                         */
-/*  Copyright 2001, 2002 by                                                */
+/*  Copyright 2001, 2002, 2003 by                                          */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -159,11 +159,13 @@
   psh_globals_funcs_init( PSH_Globals_FuncsRec*  funcs );
 
 
+#if 0
   /* snap a stem width to fitter coordinates.  `org_width' is in font */
   /* units.  The result is in device pixels (26.6 format).            */
   FT_LOCAL( FT_Pos )
   psh_dimension_snap_width( PSH_Dimension  dimension,
                             FT_Int         org_width );
+#endif
 
   /* snap a stem to one or two blue zones */
   FT_LOCAL( void )
--- a/src/pshinter/pshinter.c
+++ b/src/pshinter/pshinter.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType PostScript Hinting module                                   */
 /*                                                                         */
-/*  Copyright 2001 by                                                      */
+/*  Copyright 2001, 2003 by                                                */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -21,9 +21,7 @@
 #include <ft2build.h>
 #include "pshrec.c"
 #include "pshglob.c"
-#include "pshalgo1.c"
-#include "pshalgo2.c"
-#include "pshalgo3.c"
+#include "pshalgo.c"
 #include "pshmod.c"
 
 
--- a/src/pshinter/pshrec.c
+++ b/src/pshinter/pshrec.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType PostScript hints recorder (body).                           */
 /*                                                                         */
-/*  Copyright 2001, 2002 by                                                */
+/*  Copyright 2001, 2002, 2003 by                                          */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -1139,7 +1139,7 @@
     funcs->stem  = (T1_Hints_SetStemFunc) t1_hints_stem;
     funcs->stem3 = (T1_Hints_SetStem3Func)ps_hints_t1stem3;
     funcs->reset = (T1_Hints_ResetFunc)   ps_hints_t1reset;
-    funcs->apply = (T1_Hints_ApplyFunc)   PS_HINTS_APPLY_FUNC;
+    funcs->apply = (T1_Hints_ApplyFunc)   ps_hints_apply;
   }
 
 
@@ -1204,7 +1204,7 @@
     funcs->stems   = (T2_Hints_StemsFunc)  t2_hints_stems;
     funcs->hintmask= (T2_Hints_MaskFunc)   ps_hints_t2mask;
     funcs->counter = (T2_Hints_CounterFunc)ps_hints_t2counter;
-    funcs->apply   = (T2_Hints_ApplyFunc)  PS_HINTS_APPLY_FUNC;
+    funcs->apply   = (T2_Hints_ApplyFunc)  ps_hints_apply;
   }
 
 
--- a/src/pshinter/rules.mk
+++ b/src/pshinter/rules.mk
@@ -26,12 +26,10 @@
 
 # PSHINTER driver sources (i.e., C files)
 #
-PSHINTER_DRV_SRC := $(PSHINTER_DIR_)pshrec.c   \
-                    $(PSHINTER_DIR_)pshglob.c  \
-                    $(PSHINTER_DIR_)pshmod.c   \
-                    $(PSHINTER_DIR_)pshalgo1.c \
-                    $(PSHINTER_DIR_)pshalgo2.c \
-                    $(PSHINTER_DIR_)pshalgo3.c
+PSHINTER_DRV_SRC := $(PSHINTER_DIR_)pshrec.c  \
+                    $(PSHINTER_DIR_)pshglob.c \
+                    $(PSHINTER_DIR_)pshmod.c  \
+                    $(PSHINTER_DIR_)pshalgo.c
 
 
 # PSHINTER driver headers
--- a/tests/gview.c
+++ b/tests/gview.c
@@ -7,9 +7,7 @@
 
 /* include FreeType internals to debug hints */
 #include <../src/pshinter/pshrec.h>
-#include <../src/pshinter/pshalgo1.h>
-#include <../src/pshinter/pshalgo2.h>
-#include <../src/pshinter/pshalgo3.h>
+#include <../src/pshinter/pshalgo.h>
 
 #include <../src/autohint/ahtypes.h>
 
@@ -358,122 +356,20 @@
   }
 }
 
- /************************************************************************/
- /************************************************************************/
- /*****                                                              *****/
- /*****            POSTSCRIPT HINTER ALGORITHM 1 ROUTINES            *****/
- /*****                                                              *****/
- /************************************************************************/
- /************************************************************************/
 
-#include <../src/pshinter/pshalgo1.h>
-
-static int pshint_cpos     = 0;
-static int pshint_vertical = -1;
-
-static void
-draw_ps1_hint( PSH1_Hint   hint, FT_Bool  vertical )
-{
-  int        x1, x2;
-  NV_Vector  v;
-
-
-  if ( pshint_vertical != vertical )
-  {
-    if (vertical)
-      pshint_cpos = 40;
-    else
-      pshint_cpos = 10;
-
-    pshint_vertical = vertical;
-  }
-
-  if (vertical)
-  {
-    if ( !option_show_vert_hints )
-      return;
-
-    v.x = hint->cur_pos;
-    v.y = 0;
-    nv_vector_transform( &v, &size_transform );
-    x1 = (int)(v.x + 0.5);
-
-    v.x = hint->cur_pos + hint->cur_len;
-    v.y = 0;
-    nv_vector_transform( &v, &size_transform );
-    x2 = (int)(v.x + 0.5);
-
-    nv_pixmap_fill_rect( target, x1, 0, 1, target->height,
-                         psh1_hint_is_ghost(hint)
-                         ? GHOST_HINT_COLOR : STEM_HINT_COLOR );
-
-    if ( psh1_hint_is_ghost(hint) )
-    {
-      x1 --;
-      x2 = x1 + 2;
-    }
-    else
-      nv_pixmap_fill_rect( target, x2, 0, 1, target->height,
-                           psh1_hint_is_ghost(hint)
-                           ? GHOST_HINT_COLOR : STEM_HINT_COLOR );
-
-    nv_pixmap_fill_rect( target, x1, pshint_cpos, x2+1-x1, 1,
-                         STEM_JOIN_COLOR );
-  }
-  else
-  {
-    if (!option_show_horz_hints)
-      return;
-
-    v.y = hint->cur_pos;
-    v.x = 0;
-    nv_vector_transform( &v, &size_transform );
-    x1 = (int)(v.y + 0.5);
-
-    v.y = hint->cur_pos + hint->cur_len;
-    v.x = 0;
-    nv_vector_transform( &v, &size_transform );
-    x2 = (int)(v.y + 0.5);
-
-    nv_pixmap_fill_rect( target, 0, x1, target->width, 1,
-                         psh1_hint_is_ghost(hint)
-                         ? GHOST_HINT_COLOR : STEM_HINT_COLOR );
-
-    if ( psh1_hint_is_ghost(hint) )
-    {
-      x1 --;
-      x2 = x1 + 2;
-    }
-    else
-      nv_pixmap_fill_rect( target, 0, x2, target->width, 1,
-                           psh1_hint_is_ghost(hint)
-                           ? GHOST_HINT_COLOR : STEM_HINT_COLOR );
-
-    nv_pixmap_fill_rect( target, pshint_cpos, x2, 1, x1+1-x2,
-                         STEM_JOIN_COLOR );
-  }
-
-#if 0
-  printf( "[%7.3f %7.3f] %c\n", hint->cur_pos/64.0, (hint->cur_pos+hint->cur_len)/64.0, vertical ? 'v' : 'h' );
-#endif
-
-  pshint_cpos += 10;
-}
-
-
-
  /************************************************************************/
  /************************************************************************/
  /*****                                                              *****/
- /*****            POSTSCRIPT HINTER ALGORITHM 2 ROUTINES            *****/
+ /*****            POSTSCRIPT HINTER ALGORITHM ROUTINES              *****/
  /*****                                                              *****/
  /************************************************************************/
  /************************************************************************/
 
-#include <../src/pshinter/pshalgo2.h>
+#include <../src/pshinter/pshalgo.h>
 
 static void
-draw_ps2_hint( PSH2_Hint   hint, FT_Bool  vertical )
+draw_ps_hint( PSH_Hint  hint, 
+              FT_Bool   vertical )
 {
   int        x1, x2;
   NV_Vector  v;
@@ -488,155 +384,6 @@
     pshint_vertical = vertical;
   }
 
-  if (vertical)
-  {
-    if ( !option_show_vert_hints )
-      return;
-
-    v.x = hint->cur_pos;
-    v.y = 0;
-    nv_vector_transform( &v, &size_transform );
-    x1 = (int)(v.x + 0.5);
-
-    v.x = hint->cur_pos + hint->cur_len;
-    v.y = 0;
-    nv_vector_transform( &v, &size_transform );
-    x2 = (int)(v.x + 0.5);
-
-    nv_pixmap_fill_rect( target, x1, 0, 1, target->height,
-                         psh2_hint_is_ghost(hint)
-                         ? GHOST_HINT_COLOR : STEM_HINT_COLOR );
-
-    if ( psh2_hint_is_ghost(hint) )
-    {
-      x1 --;
-      x2 = x1 + 2;
-    }
-    else
-      nv_pixmap_fill_rect( target, x2, 0, 1, target->height,
-                           psh2_hint_is_ghost(hint)
-                           ? GHOST_HINT_COLOR : STEM_HINT_COLOR );
-
-    nv_pixmap_fill_rect( target, x1, pshint_cpos, x2+1-x1, 1,
-                         STEM_JOIN_COLOR );
-  }
-  else
-  {
-    if (!option_show_horz_hints)
-      return;
-
-    v.y = hint->cur_pos;
-    v.x = 0;
-    nv_vector_transform( &v, &size_transform );
-    x1 = (int)(v.y + 0.5);
-
-    v.y = hint->cur_pos + hint->cur_len;
-    v.x = 0;
-    nv_vector_transform( &v, &size_transform );
-    x2 = (int)(v.y + 0.5);
-
-    nv_pixmap_fill_rect( target, 0, x1, target->width, 1,
-                         psh2_hint_is_ghost(hint)
-                         ? GHOST_HINT_COLOR : STEM_HINT_COLOR );
-
-    if ( psh2_hint_is_ghost(hint) )
-    {
-      x1 --;
-      x2 = x1 + 2;
-    }
-    else
-      nv_pixmap_fill_rect( target, 0, x2, target->width, 1,
-                           psh2_hint_is_ghost(hint)
-                           ? GHOST_HINT_COLOR : STEM_HINT_COLOR );
-
-    nv_pixmap_fill_rect( target, pshint_cpos, x2, 1, x1+1-x2,
-                         STEM_JOIN_COLOR );
-  }
-
-#if 0
-  printf( "[%7.3f %7.3f] %c\n", hint->cur_pos/64.0, (hint->cur_pos+hint->cur_len)/64.0, vertical ? 'v' : 'h' );
-#endif
-
-  pshint_cpos += 10;
-}
-
-
-static void
-ps2_draw_control_points( void )
-{
-  if ( ps2_debug_glyph )
-  {
-    PSH2_Glyph    glyph = ps2_debug_glyph;
-    PSH2_Point    point = glyph->points;
-    FT_UInt       count = glyph->num_points;
-    NV_Transform  transform, *trans = &transform;
-    NV_Path       vert_rect;
-    NV_Path       horz_rect;
-    NV_Path       dot, circle;
-
-    for ( ; count > 0; count--, point++ )
-    {
-      NV_Vector  vec;
-
-      vec.x = point->cur_x;
-      vec.y = point->cur_y;
-      nv_vector_transform( &vec, &size_transform );
-
-      nv_transform_set_translate( trans, vec.x, vec.y );
-
-      if ( option_show_smooth && !psh2_point_is_smooth(point) )
-      {
-        nv_painter_set_color( painter, SMOOTH_COLOR, 256 );
-        nv_painter_fill_path( painter, trans, 0, symbol_circle );
-      }
-
-      if (option_show_horz_hints)
-      {
-        if ( point->flags_y & PSH2_POINT_STRONG )
-        {
-          nv_painter_set_color( painter, STRONG_COLOR, 256 );
-          nv_painter_fill_path( painter, trans, 0, symbol_rect_h );
-        }
-      }
-
-      if (option_show_vert_hints)
-      {
-        if ( point->flags_x & PSH2_POINT_STRONG )
-        {
-          nv_painter_set_color( painter, STRONG_COLOR, 256 );
-          nv_painter_fill_path( painter, trans, 0, symbol_rect_v );
-        }
-      }
-    }
-  }
-}
-
- /************************************************************************/
- /************************************************************************/
- /*****                                                              *****/
- /*****            POSTSCRIPT HINTER ALGORITHM 3 ROUTINES            *****/
- /*****                                                              *****/
- /************************************************************************/
- /************************************************************************/
-
-#include <../src/pshinter/pshalgo3.h>
-
-static void
-draw_ps3_hint( PSH3_Hint   hint, FT_Bool  vertical )
-{
-  int        x1, x2;
-  NV_Vector  v;
-
-  if ( pshint_vertical != vertical )
-  {
-    if (vertical)
-      pshint_cpos = 40;
-    else
-      pshint_cpos = 10;
-
-    pshint_vertical = vertical;
-  }
-
   if (!vertical)
   {
     if ( !option_show_vert_hints )
@@ -653,10 +400,10 @@
     x2 = (int)(v.x + 0.5);
 
     nv_pixmap_fill_rect( target, x1, 0, 1, target->height,
-                         psh3_hint_is_ghost(hint)
+                         psh_hint_is_ghost( hint )
                          ? GHOST_HINT_COLOR : STEM_HINT_COLOR );
 
-    if ( psh3_hint_is_ghost(hint) )
+    if ( psh_hint_is_ghost( hint ) )
     {
       x1 --;
       x2 = x1 + 2;
@@ -663,7 +410,7 @@
     }
     else
       nv_pixmap_fill_rect( target, x2, 0, 1, target->height,
-                           psh3_hint_is_ghost(hint)
+                           psh_hint_is_ghost( hint )
                            ? GHOST_HINT_COLOR : STEM_HINT_COLOR );
 
     nv_pixmap_fill_rect( target, x1, pshint_cpos, x2+1-x1, 1,
@@ -685,10 +432,10 @@
     x2 = (int)(v.y + 0.5);
 
     nv_pixmap_fill_rect( target, 0, x1, target->width, 1,
-                         psh3_hint_is_ghost(hint)
+                         psh_hint_is_ghost( hint )
                          ? GHOST_HINT_COLOR : STEM_HINT_COLOR );
 
-    if ( psh3_hint_is_ghost(hint) )
+    if ( psh_hint_is_ghost(hint) )
     {
       x1 --;
       x2 = x1 + 2;
@@ -695,7 +442,7 @@
     }
     else
       nv_pixmap_fill_rect( target, 0, x2, target->width, 1,
-                           psh3_hint_is_ghost(hint)
+                           psh_hint_is_ghost(hint)
                            ? GHOST_HINT_COLOR : STEM_HINT_COLOR );
 
     nv_pixmap_fill_rect( target, pshint_cpos, x2, 1, x1+1-x2,
@@ -711,12 +458,12 @@
 
 
 static void
-ps3_draw_control_points( void )
+ps_draw_control_points( void )
 {
-  if ( ps3_debug_glyph )
+  if ( ps_debug_glyph )
   {
-    PSH3_Glyph    glyph = ps3_debug_glyph;
-    PSH3_Point    point = glyph->points;
+    PSH_Glyph     glyph = ps_debug_glyph;
+    PSH_Point     point = glyph->points;
     FT_UInt       count = glyph->num_points;
     NV_Transform  transform, *trans = &transform;
     NV_Path       vert_rect;
@@ -733,7 +480,7 @@
 
       nv_transform_set_translate( trans, vec.x, vec.y );
 
-      if ( option_show_smooth && !psh3_point_is_smooth(point) )
+      if ( option_show_smooth && !psh_point_is_smooth(point) )
       {
         nv_painter_set_color( painter, SMOOTH_COLOR, 256 );
         nv_painter_fill_path( painter, trans, 0, symbol_circle );
@@ -741,7 +488,7 @@
 
       if (option_show_horz_hints)
       {
-        if ( point->flags_y & PSH3_POINT_STRONG )
+        if ( point->flags_y & PSH_POINT_STRONG )
         {
           nv_painter_set_color( painter, STRONG_COLOR, 256 );
           nv_painter_fill_path( painter, trans, 0, symbol_rect_h );
@@ -750,7 +497,7 @@
 
       if (option_show_vert_hints)
       {
-        if ( point->flags_x & PSH3_POINT_STRONG )
+        if ( point->flags_x & PSH_POINT_STRONG )
         {
           nv_painter_set_color( painter, STRONG_COLOR, 256 );
           nv_painter_fill_path( painter, trans, 0, symbol_rect_v );
@@ -1104,9 +851,7 @@
 
   pshint_vertical    = -1;
 
-  ps1_debug_hint_func = option_show_ps_hints ? draw_ps1_hint : 0;
-  ps2_debug_hint_func = option_show_ps_hints ? draw_ps2_hint : 0;
-  ps3_debug_hint_func = option_show_ps_hints ? draw_ps3_hint : 0;
+  ps_debug_hint_func = option_show_ps_hints ? draw_ps_hint : 0;
 
   ah_debug_hinter = NULL;