shithub: freetype+ttf2subf

Download patch

ref: f546bacdcfcadd13c3b93332635530e58fc62ce3
parent: 5972e9abf82ba20c29215c3f8d9c75efa12ca243
author: David Turner <[email protected]>
date: Sun Feb 1 11:59:06 EST 2004

* src/sfnt/Jamfile: removing "ttcmap" from the list of sources

        * src/cache/*, include/freetype/cache/*: fixing a bug after heavy
        testing. The current sources are now "release candidates" for the
        final version of the cache sub-system

        * Jamfile: updating "refdoc" target, and adding "autohint" to the
        list of modules to build. Both the autohinter and autofitter will be
        built by default. But which one will be used is determined by
        the content of "ftmodule.h"

        * src/autofit/*: much updates, but the code is still buggy as hell.
        Aargh..

git/fs: mount .git/fs: mount/attach disallowed
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2004-02-01  David Turner  <[email protected]>
+
+        * src/sfnt/Jamfile: removing "ttcmap" from the list of sources
+
+        * src/cache/*, include/freetype/cache/*: fixing a bug after heavy
+        testing. The current sources are now "release candidates" for the
+        final version of the cache sub-system
+
+        * Jamfile: updating "refdoc" target, and adding "autohint" to the
+        list of modules to build. Both the autohinter and autofitter will be
+        built by default. But which one will be used is determined by
+        the content of "ftmodule.h"
+
+        * src/autofit/*: much updates, but the code is still buggy as hell.
+        Aargh..
+
 2004-01-31  Werner Lemberg  <[email protected]>
 
 	* src/cff/cffgload.c (cff_operator_seac): Fix magnitude of
--- a/Jamfile
+++ b/Jamfile
@@ -147,7 +147,7 @@
 
 actions RefDoc
 {
-  python $(FT2_SRC)/tools/docmaker/docmaker.py --prefix=ft2 --title=FreeType-2.1.5 --output=$(DOC_DIR)  $(FT2_INCLUDE)/freetype/*.h  $(FT2_INCLUDE)/freetype/config/*.h  $(FT2_INCLUDE)/freetype/cache/*.h
+  python $(FT2_SRC)/tools/docmaker/docmaker.py --prefix=ft2 --title=FreeType-2.1.8 --output=$(DOC_DIR)  $(FT2_INCLUDE)/freetype/*.h  $(FT2_INCLUDE)/freetype/config/*.h  $(FT2_INCLUDE)/freetype/cache/*.h
 }
 
 RefDoc  refdoc ;
--- a/include/freetype/cache/ftccache.h
+++ b/include/freetype/cache/ftccache.h
@@ -1,261 +1,271 @@
-/***************************************************************************/
-/*                                                                         */
-/*  ftccache.h                                                             */
-/*                                                                         */
-/*    FreeType internal cache interface (specification).                   */
-/*                                                                         */
-/*  Copyright 2000-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.                                        */
-/*                                                                         */
-/***************************************************************************/
-
-
-#ifndef __FTCCACHE_H__
-#define __FTCCACHE_H__
-
-
-#include FT_CACHE_INTERNAL_MRU_H
-
-FT_BEGIN_HEADER
-
-  /* handle to cache object */
-  typedef struct FTC_CacheRec_*  FTC_Cache;
-
-  /* handle to cache class */
-  typedef const struct FTC_CacheClassRec_*  FTC_CacheClass;
-
-
-  /*************************************************************************/
-  /*************************************************************************/
-  /*****                                                               *****/
-  /*****                   CACHE NODE DEFINITIONS                      *****/
-  /*****                                                               *****/
-  /*************************************************************************/
-  /*************************************************************************/
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* Each cache controls one or more cache nodes.  Each node is part of    */
-  /* the global_lru list of the manager.  Its `data' field however is used */
-  /* as a reference count for now.                                         */
-  /*                                                                       */
-  /* A node can be anything, depending on the type of information held by  */
-  /* the cache.  It can be an individual glyph image, a set of bitmaps     */
-  /* glyphs for a given size, some metrics, etc.                           */
-  /*                                                                       */
-  /*************************************************************************/
-
-  /* structure size should be 20 bytes on 32-bits machines */
-  typedef struct  FTC_NodeRec_
-  {
-    FTC_MruNodeRec  mru;          /* circular mru list pointer           */
-    FTC_Node        link;         /* used for hashing                    */
-    FT_UInt32       hash;         /* used for hashing too                */
-    FT_UShort       cache_index;  /* index of cache the node belongs to  */
-    FT_Short        ref_count;    /* reference count for this node       */
-
-  } FTC_NodeRec;
-
-
-#define FTC_NODE( x )    ( (FTC_Node)(x) )
-#define FTC_NODE_P( x )  ( (FTC_Node*)(x) )
-
-#define FTC_NODE__NEXT(x)  FTC_NODE( (x)->mru.next )
-#define FTC_NODE__PREV(x)  FTC_NODE( (x)->mru.prev )
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* These functions are exported so that they can be called from          */
-  /* user-provided cache classes; otherwise, they are really part of the   */
-  /* cache sub-system internals.                                           */
-  /*                                                                       */
-
-  /* reserved for manager's use */
-  FT_EXPORT( void )
-  ftc_node_destroy( FTC_Node     node,
-                    FTC_Manager  manager );
-
-
-  /*************************************************************************/
-  /*************************************************************************/
-  /*****                                                               *****/
-  /*****                       CACHE DEFINITIONS                       *****/
-  /*****                                                               *****/
-  /*************************************************************************/
-  /*************************************************************************/
-
-  /* initialize a new cache node */
-  typedef FT_Error
-  (*FTC_Node_NewFunc)( FTC_Node    *pnode,
-                       FT_Pointer   query,
-                       FTC_Cache    cache );
-
-  typedef FT_ULong
-  (*FTC_Node_WeightFunc)( FTC_Node   node,
-                          FTC_Cache  cache );
-
-  /* compare a node to a given key pair */
-  typedef FT_Bool
-  (*FTC_Node_CompareFunc)( FTC_Node    node,
-                           FT_Pointer  key,
-                           FTC_Cache   cache );
-
-
-  typedef void
-  (*FTC_Node_FreeFunc)( FTC_Node   node,
-                        FTC_Cache  cache );
-
-  typedef FT_Error
-  (*FTC_Cache_InitFunc)( FTC_Cache  cache );
-
-  typedef void
-  (*FTC_Cache_DoneFunc)( FTC_Cache  cache );
-
-
-  typedef struct  FTC_CacheClassRec_
-  {
-    FTC_Node_NewFunc      node_new;
-    FTC_Node_WeightFunc   node_weight;
-    FTC_Node_CompareFunc  node_compare;
-    FTC_Node_CompareFunc  node_remove_faceid;
-    FTC_Node_FreeFunc     node_free;
-
-    FT_UInt               cache_size;
-    FTC_Cache_InitFunc    cache_init;
-    FTC_Cache_DoneFunc    cache_done;
-
-  } FTC_CacheClassRec;
-
-
-  /* each cache really implements a dynamic hash table to manage its nodes */
-  typedef struct  FTC_CacheRec_
-  {
-    FT_UFast           p;
-    FT_UFast           mask;
-    FT_Long            slack;
-    FTC_Node*          buckets;
-
-    FTC_CacheClassRec  clazz;       /* local copy, for speed  */
-
-    FTC_Manager        manager;
-    FT_Memory          memory;
-    FT_UInt            index;       /* in manager's table     */
-
-    FTC_CacheClass     org_class;   /* original class pointer */
-
-  } FTC_CacheRec;
-
-
-#define FTC_CACHE( x )    ( (FTC_Cache)(x) )
-#define FTC_CACHE_P( x )  ( (FTC_Cache*)(x) )
-
-
-  /* default cache initialize */
-  FT_EXPORT( FT_Error )
-  FTC_Cache_Init( FTC_Cache  cache );
-
-  /* default cache finalizer */
-  FT_EXPORT( void )
-  FTC_Cache_Done( FTC_Cache  cache );
-
-  /* Call this function to lookup the cache.  If no corresponding
-   * node is found, a new one is automatically created.  This function
-   * is capable of flushing the cache adequately to make room for the
-   * new cache object.
-   */
-  FT_EXPORT( FT_Error )
-  FTC_Cache_Lookup( FTC_Cache   cache,
-                    FT_UInt32   hash,
-                    FT_Pointer  query,
-                    FTC_Node   *anode );
-
-  FT_EXPORT( FT_Error )
-  FTC_Cache_NewNode( FTC_Cache   cache,
-                     FT_UInt32   hash,
-                     FT_Pointer  query,
-                     FTC_Node   *anode );
-
-  /* Remove all nodes that relate to a given face_id.  This is useful
-   * when un-installing fonts.  Note that if a cache node relates to
-   * the face_id, but is locked (i.e., has 'ref_count > 0'), the node
-   * will _not_ be destroyed, but its internal face_id reference will
-   * be modified.
-   *
-   * The final result will be that the node will never come back
-   * in further lookup requests, and will be flushed on demand from
-   * the cache normally when its reference count reaches 0.
-   */
-  FT_EXPORT( void )
-  FTC_Cache_RemoveFaceID( FTC_Cache   cache,
-                          FTC_FaceID  face_id );
-
-
-
-#define FTC_CACHE_LOOKUP_CMP( cache, nodecmp, hash, query, node, error )   \
-  FT_BEGIN_STMNT                                                           \
-    FTC_Node             *_bucket, *_pnode, _node;                         \
-    FTC_Cache             _cache   = FTC_CACHE(cache);                     \
-    FT_UInt32             _hash    = (FT_UInt32)(hash);                    \
-    FTC_Node_CompareFunc  _nodcomp = (FTC_Node_CompareFunc)(nodecmp);      \
-    FT_UInt               _idx;                                            \
-                                                                           \
-                                                                           \
-    error = 0;                                                             \
-    _idx  = _hash & _cache->mask;                                          \
-    if ( _idx < _cache->p )                                                \
-      _idx = _hash & (_cache->mask*2 + 1);                                 \
-                                                                           \
-    _bucket = _pnode = _cache->buckets + _idx;                             \
-    for (;;)                                                               \
-    {                                                                      \
-      _node = *_pnode;                                                     \
-      if ( _node == NULL )                                                 \
-        goto _NewNode;                                                     \
-                                                                           \
-      if ( _node->hash == _hash && _nodcomp( _node, query, _cache ) )      \
-        break;                                                             \
-                                                                           \
-      _pnode = &_node->link;                                               \
-    }                                                                      \
-                                                                           \
-    if ( _node != *_bucket )                                               \
-    {                                                                      \
-      *_pnode     = _node->link;                                           \
-      _node->link = *_bucket;                                              \
-      *_bucket    = _node;                                                 \
-    }                                                                      \
-                                                                           \
-    {                                                                      \
-      FTC_Manager  _manager = _cache->manager;                             \
-                                                                           \
-                                                                           \
-      if ( _node != _manager->nodes_list )                                 \
-        FTC_MruNode_Up( (FTC_MruNode*)&_manager->nodes_list,               \
-                        (FTC_MruNode)_node );                              \
-    }                                                                      \
-    goto _Ok;                                                              \
-                                                                           \
-  _NewNode:                                                                \
-    error = FTC_Cache_NewNode( _cache, _hash, query, &_node );             \
-                                                                           \
-  _Ok:                                                                     \
-    *(FTC_Node*)&(node) = _node;                                           \
-  FT_END_STMNT
-
-
- /* */
-
-FT_END_HEADER
-
-
-#endif /* __FTCCACHE_H__ */
-
-
-/* END */
+/***************************************************************************/
+/*                                                                         */
+/*  ftccache.h                                                             */
+/*                                                                         */
+/*    FreeType internal cache interface (specification).                   */
+/*                                                                         */
+/*  Copyright 2000-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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __FTCCACHE_H__
+#define __FTCCACHE_H__
+
+
+#include FT_CACHE_INTERNAL_MRU_H
+
+FT_BEGIN_HEADER
+
+  /* handle to cache object */
+  typedef struct FTC_CacheRec_*  FTC_Cache;
+
+  /* handle to cache class */
+  typedef const struct FTC_CacheClassRec_*  FTC_CacheClass;
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                   CACHE NODE DEFINITIONS                      *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Each cache controls one or more cache nodes.  Each node is part of    */
+  /* the global_lru list of the manager.  Its `data' field however is used */
+  /* as a reference count for now.                                         */
+  /*                                                                       */
+  /* A node can be anything, depending on the type of information held by  */
+  /* the cache.  It can be an individual glyph image, a set of bitmaps     */
+  /* glyphs for a given size, some metrics, etc.                           */
+  /*                                                                       */
+  /*************************************************************************/
+
+  /* structure size should be 20 bytes on 32-bits machines */
+  typedef struct  FTC_NodeRec_
+  {
+    FTC_MruNodeRec  mru;          /* circular mru list pointer           */
+    FTC_Node        link;         /* used for hashing                    */
+    FT_UInt32       hash;         /* used for hashing too                */
+    FT_UShort       cache_index;  /* index of cache the node belongs to  */
+    FT_Short        ref_count;    /* reference count for this node       */
+
+  } FTC_NodeRec;
+
+
+#define FTC_NODE( x )    ( (FTC_Node)(x) )
+#define FTC_NODE_P( x )  ( (FTC_Node*)(x) )
+
+#define FTC_NODE__NEXT(x)  FTC_NODE( (x)->mru.next )
+#define FTC_NODE__PREV(x)  FTC_NODE( (x)->mru.prev )
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* These functions are exported so that they can be called from          */
+  /* user-provided cache classes; otherwise, they are really part of the   */
+  /* cache sub-system internals.                                           */
+  /*                                                                       */
+
+  /* reserved for manager's use */
+  FT_EXPORT( void )
+  ftc_node_destroy( FTC_Node     node,
+                    FTC_Manager  manager );
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                       CACHE DEFINITIONS                       *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  /* initialize a new cache node */
+  typedef FT_Error
+  (*FTC_Node_NewFunc)( FTC_Node    *pnode,
+                       FT_Pointer   query,
+                       FTC_Cache    cache );
+
+  typedef FT_ULong
+  (*FTC_Node_WeightFunc)( FTC_Node   node,
+                          FTC_Cache  cache );
+
+  /* compare a node to a given key pair */
+  typedef FT_Bool
+  (*FTC_Node_CompareFunc)( FTC_Node    node,
+                           FT_Pointer  key,
+                           FTC_Cache   cache );
+
+
+  typedef void
+  (*FTC_Node_FreeFunc)( FTC_Node   node,
+                        FTC_Cache  cache );
+
+  typedef FT_Error
+  (*FTC_Cache_InitFunc)( FTC_Cache  cache );
+
+  typedef void
+  (*FTC_Cache_DoneFunc)( FTC_Cache  cache );
+
+
+  typedef struct  FTC_CacheClassRec_
+  {
+    FTC_Node_NewFunc      node_new;
+    FTC_Node_WeightFunc   node_weight;
+    FTC_Node_CompareFunc  node_compare;
+    FTC_Node_CompareFunc  node_remove_faceid;
+    FTC_Node_FreeFunc     node_free;
+
+    FT_UInt               cache_size;
+    FTC_Cache_InitFunc    cache_init;
+    FTC_Cache_DoneFunc    cache_done;
+
+  } FTC_CacheClassRec;
+
+
+  /* each cache really implements a dynamic hash table to manage its nodes */
+  typedef struct  FTC_CacheRec_
+  {
+    FT_UFast           p;
+    FT_UFast           mask;
+    FT_Long            slack;
+    FTC_Node*          buckets;
+
+    FTC_CacheClassRec  clazz;       /* local copy, for speed  */
+
+    FTC_Manager        manager;
+    FT_Memory          memory;
+    FT_UInt            index;       /* in manager's table     */
+
+    FTC_CacheClass     org_class;   /* original class pointer */
+
+  } FTC_CacheRec;
+
+
+#define FTC_CACHE( x )    ( (FTC_Cache)(x) )
+#define FTC_CACHE_P( x )  ( (FTC_Cache*)(x) )
+
+
+  /* default cache initialize */
+  FT_EXPORT( FT_Error )
+  FTC_Cache_Init( FTC_Cache  cache );
+
+  /* default cache finalizer */
+  FT_EXPORT( void )
+  FTC_Cache_Done( FTC_Cache  cache );
+
+  /* Call this function to lookup the cache.  If no corresponding
+   * node is found, a new one is automatically created.  This function
+   * is capable of flushing the cache adequately to make room for the
+   * new cache object.
+   */
+  FT_EXPORT( FT_Error )
+  FTC_Cache_Lookup( FTC_Cache   cache,
+                    FT_UInt32   hash,
+                    FT_Pointer  query,
+                    FTC_Node   *anode );
+
+  FT_EXPORT( FT_Error )
+  FTC_Cache_NewNode( FTC_Cache   cache,
+                     FT_UInt32   hash,
+                     FT_Pointer  query,
+                     FTC_Node   *anode );
+
+  /* Remove all nodes that relate to a given face_id.  This is useful
+   * when un-installing fonts.  Note that if a cache node relates to
+   * the face_id, but is locked (i.e., has 'ref_count > 0'), the node
+   * will _not_ be destroyed, but its internal face_id reference will
+   * be modified.
+   *
+   * The final result will be that the node will never come back
+   * in further lookup requests, and will be flushed on demand from
+   * the cache normally when its reference count reaches 0.
+   */
+  FT_EXPORT( void )
+  FTC_Cache_RemoveFaceID( FTC_Cache   cache,
+                          FTC_FaceID  face_id );
+
+
+#ifdef FTC_INLINE
+
+#define FTC_CACHE_LOOKUP_CMP( cache, nodecmp, hash, query, node, error )   \
+  FT_BEGIN_STMNT                                                           \
+    FTC_Node             *_bucket, *_pnode, _node;                         \
+    FTC_Cache             _cache   = FTC_CACHE(cache);                     \
+    FT_UInt32             _hash    = (FT_UInt32)(hash);                    \
+    FTC_Node_CompareFunc  _nodcomp = (FTC_Node_CompareFunc)(nodecmp);      \
+    FT_UInt               _idx;                                            \
+                                                                           \
+                                                                           \
+    error = 0;                                                             \
+    _idx  = _hash & _cache->mask;                                          \
+    if ( _idx < _cache->p )                                                \
+      _idx = _hash & (_cache->mask*2 + 1);                                 \
+                                                                           \
+    _bucket = _pnode = _cache->buckets + _idx;                             \
+    for (;;)                                                               \
+    {                                                                      \
+      _node = *_pnode;                                                     \
+      if ( _node == NULL )                                                 \
+        goto _NewNode;                                                     \
+                                                                           \
+      if ( _node->hash == _hash && _nodcomp( _node, query, _cache ) )      \
+        break;                                                             \
+                                                                           \
+      _pnode = &_node->link;                                               \
+    }                                                                      \
+                                                                           \
+    if ( _node != *_bucket )                                               \
+    {                                                                      \
+      *_pnode     = _node->link;                                           \
+      _node->link = *_bucket;                                              \
+      *_bucket    = _node;                                                 \
+    }                                                                      \
+                                                                           \
+    {                                                                      \
+      FTC_Manager  _manager = _cache->manager;                             \
+                                                                           \
+                                                                           \
+      if ( _node != _manager->nodes_list )                                 \
+        FTC_MruNode_Up( (FTC_MruNode*)&_manager->nodes_list,               \
+                        (FTC_MruNode)_node );                              \
+    }                                                                      \
+    goto _Ok;                                                              \
+                                                                           \
+  _NewNode:                                                                \
+    error = FTC_Cache_NewNode( _cache, _hash, query, &_node );             \
+                                                                           \
+  _Ok:                                                                     \
+    *(FTC_Node*)&(node) = _node;                                           \
+  FT_END_STMNT
+
+#else /* !FTC_INLINE */
+
+#define FTC_CACHE_LOOKUP_CMP( cache, nodecmp, hash, query, node, error )   \
+  FT_BEGIN_STMNT                                                           \
+    error = FTC_Cache_Lookup( FTC_CACHE(cache), hash, query,               \
+                              (FTC_Node*)&(node) );                        \
+  FT_END_STMNT
+
+#endif /* !FTC_INLINE */
+
+ /* */
+
+FT_END_HEADER
+
+
+#endif /* __FTCCACHE_H__ */
+
+
+/* END */
--- a/include/freetype/cache/ftcglyph.h
+++ b/include/freetype/cache/ftcglyph.h
@@ -1,296 +1,297 @@
-/***************************************************************************/
-/*                                                                         */
-/*  ftcglyph.h                                                             */
-/*                                                                         */
-/*    FreeType abstract glyph cache (specification).                       */
-/*                                                                         */
-/*  Copyright 2000-2001, 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.                                        */
-/*                                                                         */
-/***************************************************************************/
-
-
-  /*
-   *
-   *  FTC_GCache is an _abstract_ cache object optimized to store glyph
-   *  data.  It works as follows:
-   *
-   *   - It manages FTC_GNode objects. Each one of them can hold one or more
-   *     glyph `items'.  Item types are not specified in the FTC_GCache but
-   *     in classes that extend it.
-   *
-   *   - Glyph attributes, like face ID, character size, render mode, etc.,
-   *     can be grouped into abstract `glyph families'.  This avoids storing
-   *     the attributes within the FTC_GCache, since it is likely that many
-   *     FTC_GNodes will belong to the same family in typical uses.
-   *
-   *   - Each FTC_GNode is thus an FTC_Node with two additional fields:
-   *
-   *       * gindex: A glyph index, or the first index in a glyph range.
-   *       * family: A pointer to a glyph `family'.
-   *
-   *   - Family types are not fully specific in the FTC_Family type, but
-   *     by classes that extend it.
-   *
-   *  Note that both FTC_ImageCache and FTC_SBitCache extend FTC_GCache.
-   *  They share an FTC_Family sub-class called FTC_BasicFamily which is
-   *  used to store the following data: face ID, pixel/point sizes, load
-   *  flags.  For more details see the file `src/cache/ftcbasic.c'.
-   *
-   *  Client applications can extend FTC_GNode with their own FTC_GNode
-   *  and FTC_Family sub-classes to implement more complex caches (e.g.,
-   *  handling automatic synthesis, like obliquing & emboldening, colored
-   *  glyphs, etc.).
-   *
-   *  See also the FTC_ICache & FTC_SCache classes in `ftcimage.h' and
-   *  `ftcsbits.h', which both extend FTC_GCache with additional
-   *  optimizations.
-   *
-   *  A typical FTC_GCache implementation must provide at least the
-   *  following:
-   *
-   *  - FTC_GNode sub-class, e.g. MyNode, with relevant methods:
-   *        my_node_new            (must call FTC_GNode_Init)
-   *        my_node_free           (must call FTC_GNode_Done)
-   *        my_node_compare        (must call FTC_GNode_Compare)
-   *        my_node_remove_faceid  (must call ftc_gnode_unselect in case
-   *                                of match)
-   *
-   *  - FTC_Family sub-class, e.g. MyFamily, with relevant methods:
-   *        my_family_compare
-   *        my_family_init
-   *        my_family_reset (optional)
-   *        my_family_done
-   *
-   *  - FTC_GQuery sub-class, e.g. MyQuery, to hold cache-specific query
-   *    data.
-   *
-   *  - Constant structures for a FTC_GNodeClass.
-   *
-   *  - MyCacheNew() can be implemented easily as a call to the convenience
-   *    function FTC_GCache_New.
-   *
-   *  - MyCacheLookup with a call to FTC_GCache_Lookup.  This function will
-   *    automatically:
-   *
-   *    - Search for the corresponding family in the cache, or create
-   *      a new one if necessary.  Put it in FTC_GQUERY(myquery).family
-   *
-   *    - Call FTC_Cache_Lookup.
-   *
-   *    If it returns NULL, you should create a new node, then call
-   *    ftc_cache_add as usual.
-   */
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* Important: The functions defined in this file are only used to        */
-  /*            implement an abstract glyph cache class.  You need to      */
-  /*            provide additional logic to implement a complete cache.    */
-  /*                                                                       */
-  /*************************************************************************/
-
-
-  /*************************************************************************/
-  /*************************************************************************/
-  /*************************************************************************/
-  /*************************************************************************/
-  /*************************************************************************/
-  /*********                                                       *********/
-  /*********             WARNING, THIS IS BETA CODE.               *********/
-  /*********                                                       *********/
-  /*************************************************************************/
-  /*************************************************************************/
-  /*************************************************************************/
-  /*************************************************************************/
-  /*************************************************************************/
-
-
-#ifndef __FTCGLYPH_H__
-#define __FTCGLYPH_H__
-
-
-#include <ft2build.h>
-#include FT_CACHE_INTERNAL_MANAGER_H
-
-
-FT_BEGIN_HEADER
-
-
- /*
-  *  We can group glyphs into `families'.  Each family correspond to a
-  *  given face ID, character size, transform, etc.
-  *
-  *  Families are implemented as MRU list nodes.  They are
-  *  reference-counted.
-  */
-
-  typedef struct  FTC_FamilyRec_
-  {
-    FTC_MruNodeRec    mrunode;
-    FT_UInt           num_nodes; /* current number of nodes in this family */
-    FTC_Cache         cache;
-    FTC_MruListClass  clazz;
-
-  } FTC_FamilyRec, *FTC_Family;
-
-#define  FTC_FAMILY(x)    ( (FTC_Family)(x) )
-#define  FTC_FAMILY_P(x)  ( (FTC_Family*)(x) )
-
-
-  typedef struct  FTC_GNodeRec_
-  {
-    FTC_NodeRec      node;
-    FTC_Family       family;
-    FT_UInt          gindex;
-
-  } FTC_GNodeRec, *FTC_GNode;
-
-#define FTC_GNODE( x )    ( (FTC_GNode)(x) )
-#define FTC_GNODE_P( x )  ( (FTC_GNode*)(x) )
-
-
-  typedef struct  FTC_GQueryRec_
-  {
-    FT_UInt      gindex;
-    FTC_Family   family;
-
-  } FTC_GQueryRec, *FTC_GQuery;
-
-#define FTC_GQUERY( x )  ( (FTC_GQuery)(x) )
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* These functions are exported so that they can be called from          */
-  /* user-provided cache classes; otherwise, they are really part of the   */
-  /* cache sub-system internals.                                           */
-  /*                                                                       */
-
-  /* must be called by derived FTC_Node_InitFunc routines */
-  FT_EXPORT( void )
-  FTC_GNode_Init( FTC_GNode   node,
-                  FT_UInt     gindex,  /* glyph index for node */
-                  FTC_Family  family );
-
-  /* returns TRUE iff the query's glyph index correspond to the node;  */
-  /* this assumes that the "family" and "hash" fields of the query are */
-  /* already correctly set                                             */
-  FT_EXPORT( FT_Bool )
-  FTC_GNode_Compare( FTC_GNode   gnode,
-                     FTC_GQuery  gquery );
-
-  /* call this function to clear a node's family -- this is necessary */
-  /* to implement the `node_remove_faceid' cache method correctly     */
-  FT_EXPORT( void )
-  FTC_GNode_UnselectFamily( FTC_GNode  gnode,
-                            FTC_Cache  cache );
-
-  /* must be called by derived FTC_Node_DoneFunc routines */
-  FT_EXPORT( void )
-  FTC_GNode_Done( FTC_GNode  node,
-                  FTC_Cache  cache );
-
-
-  FT_EXPORT( void )
-  FTC_Family_Init( FTC_Family  family,
-                   FTC_Cache   cache );
-
-  typedef struct FTC_GCacheRec_
-  {
-    FTC_CacheRec    cache;
-    FTC_MruListRec  families;
-
-  } FTC_GCacheRec, *FTC_GCache;
-
-#define FTC_GCACHE( x )  ((FTC_GCache)(x))
-
-
-  /* can be used as @FTC_Cache_InitFunc */
-  FT_EXPORT( FT_Error )
-  FTC_GCache_Init( FTC_GCache  cache );
-
-
-  /* can be used as @FTC_Cache_DoneFunc */
-  FT_EXPORT( void )
-  FTC_GCache_Done( FTC_GCache  cache );
-
-
-  /* the glyph cache class adds fields for the family implementation */
-  typedef struct  FTC_GCacheClassRec_
-  {
-    FTC_CacheClassRec  clazz;
-    FTC_MruListClass   family_class;
-
-  } FTC_GCacheClassRec;
-
-  typedef const FTC_GCacheClassRec*   FTC_GCacheClass;
-
-#define FTC_GCACHE_CLASS( x )  ((FTC_GCacheClass)(x))
-
-#define FTC_CACHE__GCACHE_CLASS( x ) \
-          FTC_GCACHE_CLASS( FTC_CACHE(x)->org_class )
-#define FTC_CACHE__FAMILY_CLASS( x ) \
-          ((FTC_MruListClass) FTC_CACHE__GCACHE_CLASS(x)->family_class)
-
-
-  /* convenience function; use it instead of FTC_Manager_Register_Cache */
-  FT_EXPORT( FT_Error )
-  FTC_GCache_New( FTC_Manager       manager,
-                  FTC_GCacheClass   clazz,
-                  FTC_GCache       *acache );
-
-  FT_EXPORT( FT_Error )
-  FTC_GCache_Lookup( FTC_GCache   cache,
-                     FT_UInt32    hash,
-                     FT_UInt      gindex,
-                     FTC_GQuery   query,
-                     FTC_Node    *anode );
-
-
-#define FTC_GCACHE_LOOKUP_CMP( cache, famcmp, nodecmp, hash,                \
-                               gindex, query, node, error )                 \
-  FT_BEGIN_STMNT                                                            \
-    FTC_GCache               _gcache   = FTC_GCACHE( cache );               \
-    FTC_Family               _family;                                       \
-    FTC_GQuery               _gquery   = (FTC_GQuery)( query );             \
-    FTC_MruNode_CompareFunc  _fcompare = (FTC_MruNode_CompareFunc)(famcmp); \
-                                                                            \
-                                                                            \
-    _gquery->gindex = (gindex);                                             \
-                                                                            \
-    FTC_MRULIST_LOOP( &_gcache->families, _family )                         \
-    {                                                                       \
-      if ( _fcompare( (FTC_MruNode)_family, _gquery ) )                     \
-      {                                                                     \
-        _gquery->family = _family;                                          \
-        goto _FamilyFound;                                                  \
-      }                                                                     \
-    }                                                                       \
-    FTC_MRULIST_LOOP_END();                                                 \
-                                                                            \
-    error = FTC_MruList_New( &_gcache->families,                            \
-                             _gquery,                                       \
-                             (FTC_MruNode*)&_gquery->family );              \
-    if ( !error )                                                           \
-    {                                                                       \
-    _FamilyFound:                                                           \
-      FTC_CACHE_LOOKUP_CMP( cache, nodecmp, hash, query, node, error );     \
-    }                                                                       \
-  FT_END_STMNT
-  /* */
-
-FT_END_HEADER
-
-
-#endif /* __FTCGLYPH_H__ */
-
-
-/* END */
+/***************************************************************************/
+/*                                                                         */
+/*  ftcglyph.h                                                             */
+/*                                                                         */
+/*    FreeType abstract glyph cache (specification).                       */
+/*                                                                         */
+/*  Copyright 2000-2001, 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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+  /*
+   *
+   *  FTC_GCache is an _abstract_ cache object optimized to store glyph
+   *  data.  It works as follows:
+   *
+   *   - It manages FTC_GNode objects. Each one of them can hold one or more
+   *     glyph `items'.  Item types are not specified in the FTC_GCache but
+   *     in classes that extend it.
+   *
+   *   - Glyph attributes, like face ID, character size, render mode, etc.,
+   *     can be grouped into abstract `glyph families'.  This avoids storing
+   *     the attributes within the FTC_GCache, since it is likely that many
+   *     FTC_GNodes will belong to the same family in typical uses.
+   *
+   *   - Each FTC_GNode is thus an FTC_Node with two additional fields:
+   *
+   *       * gindex: A glyph index, or the first index in a glyph range.
+   *       * family: A pointer to a glyph `family'.
+   *
+   *   - Family types are not fully specific in the FTC_Family type, but
+   *     by classes that extend it.
+   *
+   *  Note that both FTC_ImageCache and FTC_SBitCache extend FTC_GCache.
+   *  They share an FTC_Family sub-class called FTC_BasicFamily which is
+   *  used to store the following data: face ID, pixel/point sizes, load
+   *  flags.  For more details see the file `src/cache/ftcbasic.c'.
+   *
+   *  Client applications can extend FTC_GNode with their own FTC_GNode
+   *  and FTC_Family sub-classes to implement more complex caches (e.g.,
+   *  handling automatic synthesis, like obliquing & emboldening, colored
+   *  glyphs, etc.).
+   *
+   *  See also the FTC_ICache & FTC_SCache classes in `ftcimage.h' and
+   *  `ftcsbits.h', which both extend FTC_GCache with additional
+   *  optimizations.
+   *
+   *  A typical FTC_GCache implementation must provide at least the
+   *  following:
+   *
+   *  - FTC_GNode sub-class, e.g. MyNode, with relevant methods:
+   *        my_node_new            (must call FTC_GNode_Init)
+   *        my_node_free           (must call FTC_GNode_Done)
+   *        my_node_compare        (must call FTC_GNode_Compare)
+   *        my_node_remove_faceid  (must call ftc_gnode_unselect in case
+   *                                of match)
+   *
+   *  - FTC_Family sub-class, e.g. MyFamily, with relevant methods:
+   *        my_family_compare
+   *        my_family_init
+   *        my_family_reset (optional)
+   *        my_family_done
+   *
+   *  - FTC_GQuery sub-class, e.g. MyQuery, to hold cache-specific query
+   *    data.
+   *
+   *  - Constant structures for a FTC_GNodeClass.
+   *
+   *  - MyCacheNew() can be implemented easily as a call to the convenience
+   *    function FTC_GCache_New.
+   *
+   *  - MyCacheLookup with a call to FTC_GCache_Lookup.  This function will
+   *    automatically:
+   *
+   *    - Search for the corresponding family in the cache, or create
+   *      a new one if necessary.  Put it in FTC_GQUERY(myquery).family
+   *
+   *    - Call FTC_Cache_Lookup.
+   *
+   *    If it returns NULL, you should create a new node, then call
+   *    ftc_cache_add as usual.
+   */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Important: The functions defined in this file are only used to        */
+  /*            implement an abstract glyph cache class.  You need to      */
+  /*            provide additional logic to implement a complete cache.    */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*********                                                       *********/
+  /*********             WARNING, THIS IS BETA CODE.               *********/
+  /*********                                                       *********/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+#ifndef __FTCGLYPH_H__
+#define __FTCGLYPH_H__
+
+
+#include <ft2build.h>
+#include FT_CACHE_INTERNAL_MANAGER_H
+
+
+FT_BEGIN_HEADER
+
+
+ /*
+  *  We can group glyphs into `families'.  Each family correspond to a
+  *  given face ID, character size, transform, etc.
+  *
+  *  Families are implemented as MRU list nodes.  They are
+  *  reference-counted.
+  */
+
+  typedef struct  FTC_FamilyRec_
+  {
+    FTC_MruNodeRec    mrunode;
+    FT_UInt           num_nodes; /* current number of nodes in this family */
+    FTC_Cache         cache;
+    FTC_MruListClass  clazz;
+
+  } FTC_FamilyRec, *FTC_Family;
+
+#define  FTC_FAMILY(x)    ( (FTC_Family)(x) )
+#define  FTC_FAMILY_P(x)  ( (FTC_Family*)(x) )
+
+
+  typedef struct  FTC_GNodeRec_
+  {
+    FTC_NodeRec      node;
+    FTC_Family       family;
+    FT_UInt          gindex;
+
+  } FTC_GNodeRec, *FTC_GNode;
+
+#define FTC_GNODE( x )    ( (FTC_GNode)(x) )
+#define FTC_GNODE_P( x )  ( (FTC_GNode*)(x) )
+
+
+  typedef struct  FTC_GQueryRec_
+  {
+    FT_UInt      gindex;
+    FTC_Family   family;
+
+  } FTC_GQueryRec, *FTC_GQuery;
+
+#define FTC_GQUERY( x )  ( (FTC_GQuery)(x) )
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* These functions are exported so that they can be called from          */
+  /* user-provided cache classes; otherwise, they are really part of the   */
+  /* cache sub-system internals.                                           */
+  /*                                                                       */
+
+  /* must be called by derived FTC_Node_InitFunc routines */
+  FT_EXPORT( void )
+  FTC_GNode_Init( FTC_GNode   node,
+                  FT_UInt     gindex,  /* glyph index for node */
+                  FTC_Family  family );
+
+  /* returns TRUE iff the query's glyph index correspond to the node;  */
+  /* this assumes that the "family" and "hash" fields of the query are */
+  /* already correctly set                                             */
+  FT_EXPORT( FT_Bool )
+  FTC_GNode_Compare( FTC_GNode   gnode,
+                     FTC_GQuery  gquery );
+
+  /* call this function to clear a node's family -- this is necessary */
+  /* to implement the `node_remove_faceid' cache method correctly     */
+  FT_EXPORT( void )
+  FTC_GNode_UnselectFamily( FTC_GNode  gnode,
+                            FTC_Cache  cache );
+
+  /* must be called by derived FTC_Node_DoneFunc routines */
+  FT_EXPORT( void )
+  FTC_GNode_Done( FTC_GNode  node,
+                  FTC_Cache  cache );
+
+
+  FT_EXPORT( void )
+  FTC_Family_Init( FTC_Family  family,
+                   FTC_Cache   cache );
+
+  typedef struct FTC_GCacheRec_
+  {
+    FTC_CacheRec    cache;
+    FTC_MruListRec  families;
+
+  } FTC_GCacheRec, *FTC_GCache;
+
+#define FTC_GCACHE( x )  ((FTC_GCache)(x))
+
+
+  /* can be used as @FTC_Cache_InitFunc */
+  FT_EXPORT( FT_Error )
+  FTC_GCache_Init( FTC_GCache  cache );
+
+
+  /* can be used as @FTC_Cache_DoneFunc */
+  FT_EXPORT( void )
+  FTC_GCache_Done( FTC_GCache  cache );
+
+
+  /* the glyph cache class adds fields for the family implementation */
+  typedef struct  FTC_GCacheClassRec_
+  {
+    FTC_CacheClassRec  clazz;
+    FTC_MruListClass   family_class;
+
+  } FTC_GCacheClassRec;
+
+  typedef const FTC_GCacheClassRec*   FTC_GCacheClass;
+
+#define FTC_GCACHE_CLASS( x )  ((FTC_GCacheClass)(x))
+
+#define FTC_CACHE__GCACHE_CLASS( x ) \
+          FTC_GCACHE_CLASS( FTC_CACHE(x)->org_class )
+#define FTC_CACHE__FAMILY_CLASS( x ) \
+          ((FTC_MruListClass) FTC_CACHE__GCACHE_CLASS(x)->family_class)
+
+
+  /* convenience function; use it instead of FTC_Manager_Register_Cache */
+  FT_EXPORT( FT_Error )
+  FTC_GCache_New( FTC_Manager       manager,
+                  FTC_GCacheClass   clazz,
+                  FTC_GCache       *acache );
+
+  FT_EXPORT( FT_Error )
+  FTC_GCache_Lookup( FTC_GCache   cache,
+                     FT_UInt32    hash,
+                     FT_UInt      gindex,
+                     FTC_GQuery   query,
+                     FTC_Node    *anode );
+
+
+#ifdef FTC_INLINE
+
+#define FTC_GCACHE_LOOKUP_CMP( cache, famcmp, nodecmp, hash,                \
+                               gindex, query, node, error )                 \
+  FT_BEGIN_STMNT                                                            \
+    FTC_GCache               _gcache   = FTC_GCACHE( cache );               \
+    FTC_GQuery               _gquery   = (FTC_GQuery)( query );             \
+    FTC_MruNode_CompareFunc  _fcompare = (FTC_MruNode_CompareFunc)(famcmp); \
+                                                                            \
+                                                                            \
+    _gquery->gindex = (gindex);                                             \
+                                                                            \
+    FTC_MRULIST_LOOKUP_CMP( &_gcache->families, _gquery, _fcompare,         \
+                            _gquery->family, error );                       \
+    if ( !error )                                                           \
+    {                                                                       \
+      FTC_CACHE_LOOKUP_CMP( cache, nodecmp, hash, query, node, error );     \
+    }                                                                       \
+  FT_END_STMNT
+  /* */
+
+#else /* !FTC_INLINE */
+
+#define FTC_GCACHE_LOOKUP_CMP( cache, famcmp, nodecmp, hash,                \
+                               gindex, query, node, error )                 \
+   FT_BEGIN_STMNT                                                           \
+     error = FTC_GCache_Lookup( FTC_GCACHE(cache), hash, gindex, FTC_GQUERY(query),     \
+                                (FTC_Node*) &(node) );                      \
+   FT_END_STMNT
+
+#endif /* !FTC_INLINE */
+
+
+FT_END_HEADER
+
+
+#endif /* __FTCGLYPH_H__ */
+
+
+/* END */
--- a/include/freetype/cache/ftcmru.h
+++ b/include/freetype/cache/ftcmru.h
@@ -1,239 +1,246 @@
-/***************************************************************************/
-/*                                                                         */
-/*  ftcmru.h                                                               */
-/*                                                                         */
-/*    Simple MRU list-cache (specification).                               */
-/*                                                                         */
-/*  Copyright 2000-2001, 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.                                        */
-/*                                                                         */
-/***************************************************************************/
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* An MRU is a list that cannot hold more than a certain number of       */
-  /* elements (`max_elements').  All elements in the list are sorted in    */
-  /* least-recently-used order, i.e., the `oldest' element is at the tail  */
-  /* of the list.                                                          */
-  /*                                                                       */
-  /* When doing a lookup (either through `Lookup()' or `Lookup_Node()'),   */
-  /* the list is searched for an element with the corresponding key.  If   */
-  /* it is found, the element is moved to the head of the list and is      */
-  /* returned.                                                             */
-  /*                                                                       */
-  /* If no corresponding element is found, the lookup routine will try to  */
-  /* obtain a new element with the relevant key.  If the list is already   */
-  /* full, the oldest element from the list is discarded and replaced by a */
-  /* new one; a new element is added to the list otherwise.                */
-  /*                                                                       */
-  /* Note that it is possible to pre-allocate the element list nodes.      */
-  /* This is handy if `max_elements' is sufficiently small, as it saves    */
-  /* allocations/releases during the lookup process.                       */
-  /*                                                                       */
-  /*************************************************************************/
-
-
-#ifndef __FTCMRU_H__
-#define __FTCMRU_H__
-
-
-#include <ft2build.h>
-#include FT_FREETYPE_H
-
-#ifdef FREETYPE_H
-#error "freetype.h of FreeType 1 has been loaded!"
-#error "Please fix the directory search order for header files"
-#error "so that freetype.h of FreeType 2 is found first."
-#endif
-
-#define  xxFT_DEBUG_ERROR
-#define  FTC_INLINE
-
-FT_BEGIN_HEADER
-
-  typedef struct FTC_MruNodeRec_*  FTC_MruNode;
-
-  typedef struct  FTC_MruNodeRec_
-  {
-    FTC_MruNode  next;
-    FTC_MruNode  prev;
-
-  } FTC_MruNodeRec;
-
-
-  FT_EXPORT( void )
-  FTC_MruNode_Prepend( FTC_MruNode  *plist,
-                       FTC_MruNode   node );
-
-  FT_EXPORT( void )
-  FTC_MruNode_Up( FTC_MruNode  *plist,
-                  FTC_MruNode   node );
-
-  FT_EXPORT( void )
-  FTC_MruNode_Remove( FTC_MruNode  *plist,
-                      FTC_MruNode   node );
-
-
-  typedef struct FTC_MruListRec_*              FTC_MruList;
-
-  typedef struct FTC_MruListClassRec_ const *  FTC_MruListClass;
-
-
-  typedef FT_Int
-  (*FTC_MruNode_CompareFunc)( FTC_MruNode  node,
-                              FT_Pointer   key );
-
-  typedef FT_Error
-  (*FTC_MruNode_InitFunc)( FTC_MruNode  node,
-                           FT_Pointer   key,
-                           FT_Pointer   data );
-
-  typedef FT_Error
-  (*FTC_MruNode_ResetFunc)( FTC_MruNode  node,
-                            FT_Pointer   key,
-                            FT_Pointer   data );
-
-  typedef void
-  (*FTC_MruNode_DoneFunc)( FTC_MruNode  node,
-                           FT_Pointer   data );
-
-
-  typedef struct  FTC_MruListClassRec_
-  {
-    FT_UInt                  node_size;
-    FTC_MruNode_CompareFunc  node_compare;
-    FTC_MruNode_InitFunc     node_init;
-    FTC_MruNode_ResetFunc    node_reset;
-    FTC_MruNode_DoneFunc     node_done;
-
-  } FTC_MruListClassRec;
-
-  typedef struct  FTC_MruListRec_
-  {
-    FT_UInt              num_nodes;
-    FT_UInt              max_nodes;
-    FTC_MruNode          nodes;
-    FT_Pointer           data;
-    FTC_MruListClassRec  clazz;
-    FT_Memory            memory;
-
-  } FTC_MruListRec;
-
-
-  FT_EXPORT( void )
-  FTC_MruList_Init( FTC_MruList       list,
-                    FTC_MruListClass  clazz,
-                    FT_UInt           max_nodes,
-                    FT_Pointer        data,
-                    FT_Memory         memory );
-
-  FT_EXPORT( void )
-  FTC_MruList_Reset( FTC_MruList  list );
-
-
-  FT_EXPORT( void )
-  FTC_MruList_Done( FTC_MruList  list );
-
-  FT_EXPORT( FTC_MruNode )
-  FTC_MruList_Find( FTC_MruList  list,
-                    FT_Pointer   key );
-
-  FT_EXPORT( FT_Error )
-  FTC_MruList_New( FTC_MruList   list,
-                   FT_Pointer    key,
-                   FTC_MruNode  *anode );
-
-  FT_EXPORT( FT_Error )
-  FTC_MruList_Lookup( FTC_MruList   list,
-                      FT_Pointer    key,
-                      FTC_MruNode  *pnode );
-                      
-
-  FT_EXPORT( void )
-  FTC_MruList_Remove( FTC_MruList  list,
-                      FTC_MruNode  node );
-
-  FT_EXPORT( void )
-  FTC_MruList_RemoveSelection( FTC_MruList              list,
-                               FTC_MruNode_CompareFunc  selection,
-                               FT_Pointer               key );
-
-
-#ifdef FTC_INLINE
-
-#define FTC_MRULIST_LOOKUP( list, key, node, error )                     \
-  FT_BEGIN_STMNT                                                         \
-    FTC_MruNode_CompareFunc  _compare = (list)->clazz.node_compare;      \
-    FTC_MruNode              _first, _node;                              \
-                                                                         \
-                                                                         \
-    error  = 0;                                                          \
-    _first = (list)->nodes;                                              \
-    _node  = NULL;                                                       \
-                                                                         \
-    if ( _first )                                                        \
-    {                                                                    \
-      _node = _first;                                                    \
-      do                                                                 \
-      {                                                                  \
-        if ( _compare( _node, (key) ) )                                  \
-        {                                                                \
-          *(FTC_MruNode*)&(node) = _node;                                \
-          goto _Ok;                                                      \
-        }                                                                \
-        _node = _node->next;                                             \
-                                                                         \
-      } while ( _node != _first) ;                                       \
-    }                                                                    \
-                                                                         \
-    error = FTC_MruList_New( (list), (key), (FTC_MruNode*)&(node) );     \
-  _Ok:                                                                   \
-    ;                                                                    \
-  FT_END_STMNT
-
-#else  /* !FTC_INLINE */
-
-#define FTC_MRULIST_LOOKUP_CMP( list, key, node, error ) \
-  error = FTC_MruList_Lookup( (list), (key), (FTC_MruNode*)&(node) ) 
-
-#endif /* !FTC_INLINE */
-
-
-#define FTC_MRULIST_LOOP( list, node )        \
-  FT_BEGIN_STMNT                              \
-    FTC_MruNode  _first = (list)->nodes;      \
-                                              \
-                                              \
-    if ( _first )                             \
-    {                                         \
-      FTC_MruNode  _node = _first;            \
-                                              \
-                                              \
-      do                                      \
-      {                                       \
-        *(FTC_MruNode*)&(node) = _node;
-
-
-#define FTC_MRULIST_LOOP_END()               \
-        _node = _node->next;                 \
-                                             \
-      } while ( _node != _first );           \
-    }                                        \
-  FT_END_STMNT
-
- /* */
-
-FT_END_HEADER
-
-
-#endif /* __FTCMRU_H__ */
-
-
-/* END */
+/***************************************************************************/
+/*                                                                         */
+/*  ftcmru.h                                                               */
+/*                                                                         */
+/*    Simple MRU list-cache (specification).                               */
+/*                                                                         */
+/*  Copyright 2000-2001, 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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* An MRU is a list that cannot hold more than a certain number of       */
+  /* elements (`max_elements').  All elements in the list are sorted in    */
+  /* least-recently-used order, i.e., the `oldest' element is at the tail  */
+  /* of the list.                                                          */
+  /*                                                                       */
+  /* When doing a lookup (either through `Lookup()' or `Lookup_Node()'),   */
+  /* the list is searched for an element with the corresponding key.  If   */
+  /* it is found, the element is moved to the head of the list and is      */
+  /* returned.                                                             */
+  /*                                                                       */
+  /* If no corresponding element is found, the lookup routine will try to  */
+  /* obtain a new element with the relevant key.  If the list is already   */
+  /* full, the oldest element from the list is discarded and replaced by a */
+  /* new one; a new element is added to the list otherwise.                */
+  /*                                                                       */
+  /* Note that it is possible to pre-allocate the element list nodes.      */
+  /* This is handy if `max_elements' is sufficiently small, as it saves    */
+  /* allocations/releases during the lookup process.                       */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#ifndef __FTCMRU_H__
+#define __FTCMRU_H__
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+#ifdef FREETYPE_H
+#error "freetype.h of FreeType 1 has been loaded!"
+#error "Please fix the directory search order for header files"
+#error "so that freetype.h of FreeType 2 is found first."
+#endif
+
+#define  xxFT_DEBUG_ERROR
+#define  FTC_INLINE
+
+FT_BEGIN_HEADER
+
+  typedef struct FTC_MruNodeRec_*  FTC_MruNode;
+
+  typedef struct  FTC_MruNodeRec_
+  {
+    FTC_MruNode  next;
+    FTC_MruNode  prev;
+
+  } FTC_MruNodeRec;
+
+
+  FT_EXPORT( void )
+  FTC_MruNode_Prepend( FTC_MruNode  *plist,
+                       FTC_MruNode   node );
+
+  FT_EXPORT( void )
+  FTC_MruNode_Up( FTC_MruNode  *plist,
+                  FTC_MruNode   node );
+
+  FT_EXPORT( void )
+  FTC_MruNode_Remove( FTC_MruNode  *plist,
+                      FTC_MruNode   node );
+
+
+  typedef struct FTC_MruListRec_*              FTC_MruList;
+
+  typedef struct FTC_MruListClassRec_ const *  FTC_MruListClass;
+
+
+  typedef FT_Int
+  (*FTC_MruNode_CompareFunc)( FTC_MruNode  node,
+                              FT_Pointer   key );
+
+  typedef FT_Error
+  (*FTC_MruNode_InitFunc)( FTC_MruNode  node,
+                           FT_Pointer   key,
+                           FT_Pointer   data );
+
+  typedef FT_Error
+  (*FTC_MruNode_ResetFunc)( FTC_MruNode  node,
+                            FT_Pointer   key,
+                            FT_Pointer   data );
+
+  typedef void
+  (*FTC_MruNode_DoneFunc)( FTC_MruNode  node,
+                           FT_Pointer   data );
+
+
+  typedef struct  FTC_MruListClassRec_
+  {
+    FT_UInt                  node_size;
+    FTC_MruNode_CompareFunc  node_compare;
+    FTC_MruNode_InitFunc     node_init;
+    FTC_MruNode_ResetFunc    node_reset;
+    FTC_MruNode_DoneFunc     node_done;
+
+  } FTC_MruListClassRec;
+
+  typedef struct  FTC_MruListRec_
+  {
+    FT_UInt              num_nodes;
+    FT_UInt              max_nodes;
+    FTC_MruNode          nodes;
+    FT_Pointer           data;
+    FTC_MruListClassRec  clazz;
+    FT_Memory            memory;
+
+  } FTC_MruListRec;
+
+
+  FT_EXPORT( void )
+  FTC_MruList_Init( FTC_MruList       list,
+                    FTC_MruListClass  clazz,
+                    FT_UInt           max_nodes,
+                    FT_Pointer        data,
+                    FT_Memory         memory );
+
+  FT_EXPORT( void )
+  FTC_MruList_Reset( FTC_MruList  list );
+
+
+  FT_EXPORT( void )
+  FTC_MruList_Done( FTC_MruList  list );
+
+  FT_EXPORT( FTC_MruNode )
+  FTC_MruList_Find( FTC_MruList  list,
+                    FT_Pointer   key );
+
+  FT_EXPORT( FT_Error )
+  FTC_MruList_New( FTC_MruList   list,
+                   FT_Pointer    key,
+                   FTC_MruNode  *anode );
+
+  FT_EXPORT( FT_Error )
+  FTC_MruList_Lookup( FTC_MruList   list,
+                      FT_Pointer    key,
+                      FTC_MruNode  *pnode );
+                      
+
+  FT_EXPORT( void )
+  FTC_MruList_Remove( FTC_MruList  list,
+                      FTC_MruNode  node );
+
+  FT_EXPORT( void )
+  FTC_MruList_RemoveSelection( FTC_MruList              list,
+                               FTC_MruNode_CompareFunc  selection,
+                               FT_Pointer               key );
+
+
+#ifdef FTC_INLINE
+
+#define FTC_MRULIST_LOOKUP_CMP( list, key, compare, node, error )           \
+  FT_BEGIN_STMNT                                                            \
+    FTC_MruNode*             _pfirst  = &(list)->nodes;                     \
+    FTC_MruNode_CompareFunc  _compare = (FTC_MruNode_CompareFunc)(compare); \
+    FTC_MruNode              _first, _node;                              \
+                                                                         \
+                                                                         \
+    error  = 0;                                                          \
+    _first = *(_pfirst);                                                 \
+    _node  = NULL;                                                       \
+                                                                         \
+    if ( _first )                                                        \
+    {                                                                    \
+      _node = _first;                                                    \
+      do                                                                 \
+      {                                                                  \
+        if ( _compare( _node, (key) ) )                                  \
+        {                                                                \
+          if ( _node != _first )                                         \
+            FTC_MruNode_Up( _pfirst, _node );                            \
+                                                                         \
+          *(FTC_MruNode*)&(node) = _node;                                \
+          goto _MruOk;                                                   \
+        }                                                                \
+        _node = _node->next;                                             \
+                                                                         \
+      } while ( _node != _first) ;                                       \
+    }                                                                    \
+                                                                         \
+    error = FTC_MruList_New( (list), (key), (FTC_MruNode*)&(node) );     \
+  _MruOk:                                                                \
+    ;                                                                    \
+  FT_END_STMNT
+
+#define FTC_MRULIST_LOOKUP( list, key, node, error ) \
+  FTC_MRULIST_LOOKUP_CMP( list, key, (list)->clazz.node_compare, node, error )
+
+#else  /* !FTC_INLINE */
+
+#define FTC_MRULIST_LOOKUP( list, key, node, error ) \
+  error = FTC_MruList_Lookup( (list), (key), (FTC_MruNode*)&(node) ) 
+
+#endif /* !FTC_INLINE */
+
+
+#define FTC_MRULIST_LOOP( list, node )        \
+  FT_BEGIN_STMNT                              \
+    FTC_MruNode  _first = (list)->nodes;      \
+                                              \
+                                              \
+    if ( _first )                             \
+    {                                         \
+      FTC_MruNode  _node = _first;            \
+                                              \
+                                              \
+      do                                      \
+      {                                       \
+        *(FTC_MruNode*)&(node) = _node;
+
+
+#define FTC_MRULIST_LOOP_END()               \
+        _node = _node->next;                 \
+                                             \
+      } while ( _node != _first );           \
+    }                                        \
+  FT_END_STMNT
+
+ /* */
+
+FT_END_HEADER
+
+
+#endif /* __FTCMRU_H__ */
+
+
+/* END */
--- a/src/autofit/Jamfile
+++ b/src/autofit/Jamfile
@@ -1,11 +1,11 @@
-SubDir FT2_TOP src autofit ;
-
+SubDir FT2_TOP src autofit ;
+
 {
   local  _sources ;
 
   if $(FT2_MULTI)
   {
-    _sources = afangles afglobal afhints aflatin ;
+    _sources = afangles afglobal afhints aflatin afloader afmodule ;
   }
   else
   {
--- a/src/autofit/afhints.c
+++ b/src/autofit/afhints.c
@@ -1,938 +1,938 @@
-#include "afhints.h"
-
-#ifdef AF_DEBUG
-
-#include <stdio.h>
-
-  void
-  af_glyph_hints_dump_edges( AF_GlyphHints  hints )
-  {
-    AF_Edge     edges;
-    AF_Edge     edge_limit;
-    AF_Segment  segments;
-    FT_Int      dimension;
-
-
-    edges      = hints->horz_edges;
-    edge_limit = edges + hints->num_hedges;
-    segments   = hints->horz_segments;
-
-    for ( dimension = 1; dimension >= 0; dimension-- )
-    {
-      AF_Edge   edge;
-
-
-      printf ( "Table of %s edges:\n",
-               !dimension ? "vertical" : "horizontal" );
-      printf ( "  [ index |  pos |  dir  | link |"
-               " serif | blue | opos  |  pos  ]\n" );
-
-      for ( edge = edges; edge < edge_limit; edge++ )
-      {
-        printf ( "  [ %5d | %4d | %5s | %4d | %5d |  %c  | %5.2f | %5.2f ]\n",
-                 edge - edges,
-                 (int)edge->fpos,
-                 edge->dir == AF_DIR_UP
-                   ? "up"
-                   : ( edge->dir == AF_DIR_DOWN
-                         ? "down"
-                         : ( edge->dir == AF_DIR_LEFT
-                               ? "left"
-                               : ( edge->dir == AF_DIR_RIGHT
-                                     ? "right"
-                                     : "none" ) ) ),
-                 edge->link ? ( edge->link - edges ) : -1,
-                 edge->serif ? ( edge->serif - edges ) : -1,
-                 edge->blue_edge ? 'y' : 'n',
-                 edge->opos / 64.0,
-                 edge->pos / 64.0 );
-      }
-
-      edges      = hints->vert_edges;
-      edge_limit = edges + hints->num_vedges;
-      segments   = hints->vert_segments;
-    }
-  }
-
-
-  /* A function used to dump the array of linked segments */
-  void
-  af_glyph_hints_dump_segments( AF_GlyphHints  hints )
-  {
-    AF_Segment  segments;
-    AF_Segment  segment_limit;
-    AF_Point    points;
-    FT_Int      dimension;
-
-
-    points        = hints->points;
-    segments      = hints->horz_segments;
-    segment_limit = segments + hints->num_hsegments;
-
-    for ( dimension = 1; dimension >= 0; dimension-- )
-    {
-      AF_Segment  seg;
-
-
-      printf ( "Table of %s segments:\n",
-               !dimension ? "vertical" : "horizontal" );
-      printf ( "  [ index |  pos |  dir  | link | serif |"
-               " numl | first | start ]\n" );
-
-      for ( seg = segments; seg < segment_limit; seg++ )
-      {
-        printf ( "  [ %5d | %4d | %5s | %4d | %5d | %4d | %5d | %5d ]\n",
-                 seg - segments,
-                 (int)seg->pos,
-                 seg->dir == AF_DIR_UP
-                   ? "up"
-                   : ( seg->dir == AF_DIR_DOWN
-                         ? "down"
-                         : ( seg->dir == AF_DIR_LEFT
-                               ? "left"
-                               : ( seg->dir == AF_DIR_RIGHT
-                                     ? "right"
-                                     : "none" ) ) ),
-                 seg->link ? ( seg->link - segments ) : -1,
-                 seg->serif ? ( seg->serif - segments ) : -1,
-                 (int)seg->num_linked,
-                 seg->first - points,
-                 seg->last - points );
-      }
-
-      segments      = hints->vert_segments;
-      segment_limit = segments + hints->num_vsegments;
-    }
-  }
-
-#endif /* AF_DEBUG */
-
-
-  /* compute the direction value of a given vector */
-  FT_LOCAL_DEF( AF_Direction )
-  af_direction_compute( FT_Pos  dx,
-                        FT_Pos  dy )
-  {
-    AF_Direction  dir;
-    FT_Pos        ax = ABS( dx );
-    FT_Pos        ay = ABS( dy );
-
-
-    dir = AF_DIR_NONE;
-
-    /* atan(1/12) == 4.7 degrees */
-
-    /* test for vertical direction */
-    if ( ax * 12 < ay )
-    {
-      dir = dy > 0 ? AF_DIR_UP : AF_DIR_DOWN;
-    }
-    /* test for horizontal direction */
-    else if ( ay * 12 < ax )
-    {
-      dir = dx > 0 ? AF_DIR_RIGHT : AF_DIR_LEFT;
-    }
-
-    return dir;
-  }
-
-
-  /* compute all inflex points in a given glyph */
-  static void
-  af_glyph_hints_compute_inflections( AF_GlyphHints  hints )
-  {
-    AF_Point*  contour       = hints->contours;
-    AF_Point*  contour_limit = contour + hints->num_contours;
-
-
-    /* do each contour separately */
-    for ( ; contour < contour_limit; contour++ )
-    {
-      AF_Point   point = contour[0];
-      AF_Point   first = point;
-      AF_Point   start = point;
-      AF_Point   end   = point;
-      AF_Point   before;
-      AF_Point   after;
-      AF_Angle   angle_in, angle_seg, angle_out;
-      AF_Angle   diff_in, diff_out;
-      FT_Int     finished = 0;
-
-
-      /* compute first segment in contour */
-      first = point;
-
-      start = end = first;
-      do
-      {
-        end = end->next;
-        if ( end == first )
-          goto Skip;
-
-      } while ( end->fx == first->fx && end->fy == first->fy );
-
-      angle_seg = af_angle_atan( end->fx - start->fx,
-                                 end->fy - start->fy );
-
-      /* extend the segment start whenever possible */
-      before = start;
-      do
-      {
-        do
-        {
-          start  = before;
-          before = before->prev;
-          if ( before == first )
-            goto Skip;
-
-        } while ( before->fx == start->fx && before->fy == start->fy );
-
-        angle_in = af_angle_atan( start->fx - before->fx,
-                                  start->fy - before->fy );
-
-      } while ( angle_in == angle_seg );
-
-      first   = start;
-      diff_in = af_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 ( end->fx == after->fx && end->fy == after->fy );
-
-          angle_out = af_angle_atan( after->fx - end->fx,
-                                     after->fy - end->fy );
-
-        } while ( angle_out == angle_seg );
-
-        diff_out = af_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
-          {
-            start->flags |= AF_FLAG_INFLECTION;
-            start = start->next;
-
-          } while ( start != end );
-
-          start->flags |= AF_FLAG_INFLECTION;
-        }
-
-        start     = end;
-        end       = after;
-        angle_seg = angle_out;
-        diff_in   = diff_out;
-
-      } while ( !finished );
-
-    Skip:
-      ;
-    }
-  }
-
-
-
-  FT_LOCAL_DEF( void )
-  af_glyph_hints_init( AF_GlyphHints  hints,
-                       FT_Memory      memory )
-  {
-    FT_ZERO( hints );
-    hints->memory = memory;
-  }
-
-
-
-  FT_LOCAL_DEF( void )
-  af_glyph_hints_done( AF_GlyphHints  hints )
-  {
-    if ( hints && hints->memory )
-    {
-      FT_Memory     memory = hints->memory;
-      AF_Dimension  dim;
-
-     /* note that we don't need to free the segment and edge
-      * buffers, since they're really within the hints->points array
-      */
-      for ( dim = 0; dim < 2; dim++ )
-      {
-        AF_AxisHints  axis = &hints->axis[ dim ];
-
-        axis->num_segments = 0;
-        axis->num_edges    = 0;
-        axis->segments     = NULL;
-        axis->edges        = NULL;
-      }
-
-      FT_FREE( hints->contours );
-      hints->max_contours = 0;
-      hints->num_contours = 0;
-
-      FT_FREE( hints->points );
-      hints->num_points = 0;
-      hints->max_points = 0;
-
-      hints->memory = NULL;
-    }
-  }
-
-
-
-  FT_LOCAL_DEF( FT_Error )
-  af_glyph_hints_reset( AF_GlyphHints  hints,
-                        AF_Scaler      scaler,
-                        FT_Outline*    outline )
-  {
-    FT_Error     error        = FT_Err_Ok;
-    AF_Point     points;
-    FT_UInt      old_max, new_max;
-    FT_Fixed     x_scale = scaler->x_scale;
-    FT_Fixed     y_scale = scaler->y_scale;
-    FT_Pos       x_delta = scaler->x_delta;
-    FT_Pos       y_delta = scaler->y_delta;
-    FT_Memory    memory  = hints->memory;
-
-    hints->scaler_flags = scaler->flags;
-    hints->other_flags  = 0;
-
-    hints->num_points    = 0;
-    hints->num_contours  = 0;
-
-    hints->axis[0].num_segments = 0;
-    hints->axis[0].num_edges    = 0;
-    hints->axis[1].num_segments = 0;
-    hints->axis[1].num_edges    = 0;
-
-   /* first of all, reallocate the contours array when necessary
-    */
-    new_max = (FT_UInt) outline->n_contours;
-    old_max = hints->max_contours;
-    if ( new_max > old_max )
-    {
-      new_max = (new_max + 3) & ~3;
-
-      if ( FT_RENEW_ARRAY( hints->contours, old_max, new_max ) )
-        goto Exit;
-
-      hints->max_contours = new_max;
-    }
-
-   /* then, reallocate the points, segments & edges arrays if needed --
-    * note that we reserved two additional point positions, used to
-    * hint metrics appropriately
-    */
-    new_max = (FT_UInt)( outline->n_points + 2 );
-    old_max = hints->max_points;
-    if ( new_max > old_max )
-    {
-      FT_Byte*    items;
-      FT_ULong    off1, off2, off3;
-
-     /* we store in a single buffer the following arrays:
-      *
-      *  - an array of   N  AF_PointRec   items
-      *  - an array of 2*N  AF_SegmentRec items
-      *  - an array of 2*N  AF_EdgeRec    items
-      *
-      */
-
-      new_max = ( new_max + 2 + 7 ) & ~7;
-
-#undef  OFF_INCREMENT
-#define OFF_INCREMENT( _off, _type, _count )   \
-     ( FT_PAD_CEIL( _off, sizeof(_type) ) + (_count)*sizeof(_type))
-
-      off1 = OFF_INCREMENT( 0, AF_PointRec, new_max );
-      off2 = OFF_INCREMENT( off1, AF_SegmentRec, new_max );
-      off3 = OFF_INCREMENT( off2, AF_EdgeRec, new_max*2 );
-
-      FT_FREE( hints->points );
-
-      if ( FT_ALLOC( items, off3 ) )
-      {
-        hints->max_points       = 0;
-        hints->axis[0].segments = NULL;
-        hints->axis[0].edges    = NULL;
-        hints->axis[1].segments = NULL;
-        hints->axis[1].edges    = NULL;
-        goto Exit;
-      }
-
-     /* readjust some pointers
-      */
-      hints->max_points       = new_max;
-      hints->points           = (AF_Point) items;
-
-      hints->axis[0].segments = (AF_Segment)( items + off1 );
-      hints->axis[1].segments = hints->axis[0].segments + new_max;
-
-      hints->axis[0].edges    = (AF_Edge)   ( items + off2 );
-      hints->axis[1].edges    = hints->axis[0].edges + new_max;
-    }
-
-    hints->num_points   = outline->n_points;
-    hints->num_contours = outline->n_contours;
-
-
-    /* We can't rely on the value of `FT_Outline.flags' to know the fill  */
-    /* direction used for a glyph, given that some fonts are broken (e.g. */
-    /* the Arphic ones).  We thus recompute it each time we need to.      */
-    /*                                                                    */
-    hints->axis[ AF_DIMENSION_HORZ ].major_dir = AF_DIR_UP;
-    hints->axis[ AF_DIMENSION_VERT ].major_dir = AF_DIR_LEFT;
-
-    if ( FT_Outline_Get_Orientation( outline ) == FT_ORIENTATION_POSTSCRIPT )
-    {
-      hints->axis[ AF_DIMENSION_HORZ ].major_dir = AF_DIR_DOWN;
-      hints->axis[ AF_DIMENSION_VERT ].major_dir = AF_DIR_RIGHT;
-    }
-
-    hints->x_scale = x_scale;
-    hints->y_scale = y_scale;
-    hints->x_delta = x_delta;
-    hints->y_delta = y_delta;
-
-    points = hints->points;
-    if ( hints->num_points == 0 )
-      goto Exit;
-
-    {
-      AF_Point  point;
-      AF_Point  point_limit = points + hints->num_points;
-
-
-      /* compute coordinates & bezier flags */
-      {
-        FT_Vector*  vec = outline->points;
-        char*       tag = outline->tags;
-
-
-        for ( point = points; point < point_limit; point++, vec++, tag++ )
-        {
-          point->fx = vec->x;
-          point->fy = vec->y;
-          point->ox = point->x = FT_MulFix( vec->x, x_scale ) + x_delta;
-          point->oy = point->y = FT_MulFix( vec->y, y_scale ) + y_delta;
-
-          switch ( FT_CURVE_TAG( *tag ) )
-          {
-          case FT_CURVE_TAG_CONIC:
-            point->flags = AF_FLAG_CONIC;
-            break;
-          case FT_CURVE_TAG_CUBIC:
-            point->flags = AF_FLAG_CUBIC;
-            break;
-          default:
-            point->flags = 0;
-            ;
-          }
-        }
-      }
-
-      /* compute `next' and `prev' */
-      {
-        FT_Int    contour_index;
-        AF_Point  prev;
-        AF_Point  first;
-        AF_Point  end;
-
-
-        contour_index = 0;
-
-        first = points;
-        end   = points + outline->contours[0];
-        prev  = end;
-
-        for ( point = points; point < point_limit; point++ )
-        {
-          point->prev = prev;
-          if ( point < end )
-          {
-            point->next = point + 1;
-            prev        = point;
-          }
-          else
-          {
-            point->next = first;
-            contour_index++;
-            if ( point + 1 < point_limit )
-            {
-              end   = points + outline->contours[contour_index];
-              first = point + 1;
-              prev  = end;
-            }
-          }
-        }
-      }
-
-      /* set-up the contours array */
-      {
-        AF_Point*  contour       = hints->contours;
-        AF_Point*  contour_limit = contour + hints->num_contours;
-        short*     end           = outline->contours;
-        short      idx           = 0;
-
-
-        for ( ; contour < contour_limit; contour++, end++ )
-        {
-          contour[0] = points + idx;
-          idx        = (short)( end[0] + 1 );
-        }
-      }
-
-      /* compute directions of in & out vectors */
-      {
-        for ( point = points; point < point_limit; point++ )
-        {
-          AF_Point   prev;
-          AF_Point   next;
-          FT_Pos     in_x, in_y, out_x, out_y;
-
-
-          prev   = point->prev;
-          in_x   = point->fx - prev->fx;
-          in_y   = point->fy - prev->fy;
-
-          point->in_dir = af_direction_compute( in_x, in_y );
-
-          next   = point->next;
-          out_x  = next->fx - point->fx;
-          out_y  = next->fy - point->fy;
-
-          point->out_dir = af_direction_compute( out_x, out_y );
-
-          if ( point->flags & ( AF_FLAG_CONIC | AF_FLAG_CUBIC ) )
-          {
-          Is_Weak_Point:
-            point->flags |= AF_FLAG_WEAK_INTERPOLATION;
-          }
-          else if ( point->out_dir == point->in_dir )
-          {
-            AF_Angle  angle_in, angle_out, delta;
-
-
-            if ( point->out_dir != AF_DIR_NONE )
-              goto Is_Weak_Point;
-
-            angle_in  = af_angle_atan( in_x, in_y );
-            angle_out = af_angle_atan( out_x, out_y );
-            delta     = af_angle_diff( angle_in, angle_out );
-
-            if ( delta < 2 && delta > -2 )
-              goto Is_Weak_Point;
-          }
-          else if ( point->in_dir == -point->out_dir )
-            goto Is_Weak_Point;
-        }
-      }
-    }
-
-   /* compute inflection points
-    */
-    af_glyph_hints_compute_inflections( hints );
-
-  Exit:
-    return error;
-  }
-
-
-
-
- /*
-  *
-  *  E D G E   P O I N T   G R I D - F I T T I N G
-  *
-  */
-
-
-  FT_LOCAL_DEF( void )
-  af_glyph_hints_align_edge_points( AF_GlyphHints  hints,
-                                    AF_Dimension   dim )
-  {
-    AF_AxisHints  axis       = & hints->axis[ dim ];
-    AF_Edge       edges      = axis->edges;
-    AF_Edge       edge_limit = edges + axis->num_edges;
-    AF_Edge       edge;
-
-    for ( edge = edges; edge < edge_limit; edge++ )
-    {
-      /* move the points of each segment     */
-      /* in each edge to the edge's position */
-      AF_Segment  seg = edge->first;
-
-
-      do
-      {
-        AF_Point  point = seg->first;
-
-
-        for (;;)
-        {
-          if ( dim == AF_DIMENSION_HORZ )
-          {
-            point->x      = edge->pos;
-            point->flags |= AF_FLAG_TOUCH_X;
-          }
-          else
-          {
-            point->y      = edge->pos;
-            point->flags |= AF_FLAG_TOUCH_Y;
-          }
-
-          if ( point == seg->last )
-            break;
-
-          point = point->next;
-        }
-
-        seg = seg->edge_next;
-
-      } while ( seg != edge->first );
-    }
-  }
-
-
- /*
-  *
-  *  S T R O N G   P O I N T   I N T E R P O L A T I O N
-  *
-  */
-
-
-  /* hint the strong points -- this is equivalent to the TrueType `IP' */
-  /* hinting instruction                                               */
-  FT_LOCAL_DEF( void )
-  af_glyph_hints_align_strong_points( AF_GlyphHints  hints,
-                                      AF_Dimension   dim )
-  {
-    AF_Point      points      = hints->points;
-    AF_Point      point_limit = points + hints->num_points;
-    AF_AxisHints  axis        = &hints->axis[dim];
-    AF_Edge       edges       = axis->edges;
-    AF_Edge       edge_limit  = edges + axis->num_edges;
-    AF_Flags      touch_flag;
-
-
-    if ( dim == AF_DIMENSION_HORZ )
-      touch_flag = AF_FLAG_TOUCH_X;
-    else
-      touch_flag  = AF_FLAG_TOUCH_Y;
-
-    if ( edges < edge_limit )
-    {
-      AF_Point  point;
-      AF_Edge   edge;
-
-      for ( point = points; point < point_limit; point++ )
-      {
-        FT_Pos  u, ou, fu;  /* point position */
-        FT_Pos  delta;
-
-
-        if ( point->flags & touch_flag )
-          continue;
-
-        /* if this point is candidate to weak interpolation, we will  */
-        /* interpolate it after all strong points have been processed */
-        if (  ( point->flags & AF_FLAG_WEAK_INTERPOLATION ) &&
-             !( point->flags & AF_FLAG_INFLECTION )         )
-          continue;
-
-        if ( dim == AF_DIMENSION_VERT )
-        {
-          u  = point->fy;
-          ou = point->oy;
-        }
-        else
-        {
-          u  = point->fx;
-          ou = point->ox;
-        }
-
-        fu = u;
-
-        /* is the point before the first edge? */
-        edge  = edges;
-        delta = edge->fpos - u;
-        if ( delta >= 0 )
-        {
-          u = edge->pos - ( edge->opos - ou );
-          goto Store_Point;
-        }
-
-        /* is the point after the last edge? */
-        edge  = edge_limit - 1;
-        delta = u - edge->fpos;
-        if ( delta >= 0 )
-        {
-          u = edge->pos + ( ou - edge->opos );
-          goto Store_Point;
-        }
-
-        {
-          FT_UInt  min, max, mid;
-          FT_Pos   fpos;
-
-
-          /* find enclosing edges */
-          min = 0;
-          max = edge_limit - edges;
-
-          while ( min < max )
-          {
-            mid  = ( max + min ) >> 1;
-            edge = edges + mid;
-            fpos = edge->fpos;
-
-            if ( u < fpos )
-              max = mid;
-            else if ( u > fpos )
-              min = mid + 1;
-            else
-            {
-              /* we are on the edge */
-              u = edge->pos;
-              goto Store_Point;
-            }
-          }
-
-          {
-            AF_Edge  before = edges + min - 1;
-            AF_Edge  after  = edges + min + 0;
-
-
-            /* assert( before && after && before != after ) */
-            if ( before->scale == 0 )
-              before->scale = FT_DivFix( after->pos - before->pos,
-                                         after->fpos - before->fpos );
-
-            u = before->pos + FT_MulFix( fu - before->fpos,
-                                         before->scale );
-          }
-        }
-
-
-      Store_Point:
-
-        /* save the point position */
-        if ( dim == AF_DIMENSION_HORZ )
-          point->x = u;
-        else
-          point->y = u;
-
-        point->flags |= touch_flag;
-      }
-    }
-  }
-
-
- /*
-  *
-  *  W E A K   P O I N T   I N T E R P O L A T I O N
-  *
-  */
-
-  static void
-  af_iup_shift( AF_Point  p1,
-                AF_Point  p2,
-                AF_Point  ref )
-  {
-    AF_Point  p;
-    FT_Pos    delta = ref->u - ref->v;
-
-
-    for ( p = p1; p < ref; p++ )
-      p->u = p->v + delta;
-
-    for ( p = ref + 1; p <= p2; p++ )
-      p->u = p->v + delta;
-  }
-
-
-  static void
-  af_iup_interp( AF_Point  p1,
-                 AF_Point  p2,
-                 AF_Point  ref1,
-                 AF_Point  ref2 )
-  {
-    AF_Point  p;
-    FT_Pos    u;
-    FT_Pos    v1 = ref1->v;
-    FT_Pos    v2 = ref2->v;
-    FT_Pos    d1 = ref1->u - v1;
-    FT_Pos    d2 = ref2->u - v2;
-
-
-    if ( p1 > p2 )
-      return;
-
-    if ( v1 == v2 )
-    {
-      for ( p = p1; p <= p2; p++ )
-      {
-        u = p->v;
-
-        if ( u <= v1 )
-          u += d1;
-        else
-          u += d2;
-
-        p->u = u;
-      }
-      return;
-    }
-
-    if ( v1 < v2 )
-    {
-      for ( p = p1; p <= p2; p++ )
-      {
-        u = p->v;
-
-        if ( u <= v1 )
-          u += d1;
-        else if ( u >= v2 )
-          u += d2;
-        else
-          u = ref1->u + FT_MulDiv( u - v1, ref2->u - ref1->u, v2 - v1 );
-
-        p->u = u;
-      }
-    }
-    else
-    {
-      for ( p = p1; p <= p2; p++ )
-      {
-        u = p->v;
-
-        if ( u <= v2 )
-          u += d2;
-        else if ( u >= v1 )
-          u += d1;
-        else
-          u = ref1->u + FT_MulDiv( u - v1, ref2->u - ref1->u, v2 - v1 );
-
-        p->u = u;
-      }
-    }
-  }
-
-
-  FT_LOCAL_DEF( void )
-  af_glyph_hints_align_weak_points( AF_GlyphHints  hints,
-                                    AF_Dimension   dim )
-  {
-    AF_Point    points        = hints->points;
-    AF_Point    point_limit   = points + hints->num_points;
-    AF_Point*   contour       = hints->contours;
-    AF_Point*   contour_limit = contour + hints->num_contours;
-    AF_Flags    touch_flag;
-    AF_Point    point;
-    AF_Point    end_point;
-    AF_Point    first_point;
-
-
-    /* PASS 1: Move segment points to edge positions */
-
-    if ( dim == AF_DIMENSION_HORZ )
-    {
-      touch_flag = AF_FLAG_TOUCH_X;
-
-      for ( point = points; point < point_limit; point++ )
-      {
-        point->u = point->x;
-        point->v = point->ox;
-      }
-    }
-    else
-    {
-      touch_flag = AF_FLAG_TOUCH_Y;
-
-      for ( point = points; point < point_limit; points++ )
-      {
-        point->u = point->y;
-        point->v = point->oy;
-      }
-    }
-
-    point   = points;
-
-    for ( ; contour < contour_limit; contour++ )
-    {
-      point       = *contour;
-      end_point   = point->prev;
-      first_point = point;
-
-      while ( point <= end_point && !( point->flags & touch_flag ) )
-        point++;
-
-      if ( point <= end_point )
-      {
-        AF_Point  first_touched = point;
-        AF_Point  cur_touched   = point;
-
-
-        point++;
-        while ( point <= end_point )
-        {
-          if ( point->flags & touch_flag )
-          {
-            /* we found two successive touched points; we interpolate */
-            /* all contour points between them                        */
-            af_iup_interp( cur_touched + 1, point - 1,
-                           cur_touched, point );
-            cur_touched = point;
-          }
-          point++;
-        }
-
-        if ( cur_touched == first_touched )
-        {
-          /* this is a special case: only one point was touched in the */
-          /* contour; we thus simply shift the whole contour           */
-          af_iup_shift( first_point, end_point, cur_touched );
-        }
-        else
-        {
-          /* now interpolate after the last touched point to the end */
-          /* of the contour                                          */
-          af_iup_interp( cur_touched + 1, end_point,
-                         cur_touched, first_touched );
-
-          /* if the first contour point isn't touched, interpolate */
-          /* from the contour start to the first touched point     */
-          if ( first_touched > points )
-            af_iup_interp( first_point, first_touched - 1,
-                           cur_touched, first_touched );
-        }
-      }
-    }
-
-    /* now save the interpolated values back to x/y */
-    if ( dim == AF_DIMENSION_HORZ )
-    {
-      for ( point = points; point < point_limit; point++ )
-        point->x = point->u;
-    }
-    else
-    {
-      for ( point = points; point < point_limit; point++ )
-        point->y = point->u;
-    }
-  }
-
-
-
-
+#include "afhints.h"
+
+#ifdef AF_DEBUG
+
+#include <stdio.h>
+
+  void
+  af_glyph_hints_dump_edges( AF_GlyphHints  hints )
+  {
+    AF_Edge     edges;
+    AF_Edge     edge_limit;
+    AF_Segment  segments;
+    FT_Int      dimension;
+
+
+    edges      = hints->horz_edges;
+    edge_limit = edges + hints->num_hedges;
+    segments   = hints->horz_segments;
+
+    for ( dimension = 1; dimension >= 0; dimension-- )
+    {
+      AF_Edge   edge;
+
+
+      printf ( "Table of %s edges:\n",
+               !dimension ? "vertical" : "horizontal" );
+      printf ( "  [ index |  pos |  dir  | link |"
+               " serif | blue | opos  |  pos  ]\n" );
+
+      for ( edge = edges; edge < edge_limit; edge++ )
+      {
+        printf ( "  [ %5d | %4d | %5s | %4d | %5d |  %c  | %5.2f | %5.2f ]\n",
+                 edge - edges,
+                 (int)edge->fpos,
+                 edge->dir == AF_DIR_UP
+                   ? "up"
+                   : ( edge->dir == AF_DIR_DOWN
+                         ? "down"
+                         : ( edge->dir == AF_DIR_LEFT
+                               ? "left"
+                               : ( edge->dir == AF_DIR_RIGHT
+                                     ? "right"
+                                     : "none" ) ) ),
+                 edge->link ? ( edge->link - edges ) : -1,
+                 edge->serif ? ( edge->serif - edges ) : -1,
+                 edge->blue_edge ? 'y' : 'n',
+                 edge->opos / 64.0,
+                 edge->pos / 64.0 );
+      }
+
+      edges      = hints->vert_edges;
+      edge_limit = edges + hints->num_vedges;
+      segments   = hints->vert_segments;
+    }
+  }
+
+
+  /* A function used to dump the array of linked segments */
+  void
+  af_glyph_hints_dump_segments( AF_GlyphHints  hints )
+  {
+    AF_Segment  segments;
+    AF_Segment  segment_limit;
+    AF_Point    points;
+    FT_Int      dimension;
+
+
+    points        = hints->points;
+    segments      = hints->horz_segments;
+    segment_limit = segments + hints->num_hsegments;
+
+    for ( dimension = 1; dimension >= 0; dimension-- )
+    {
+      AF_Segment  seg;
+
+
+      printf ( "Table of %s segments:\n",
+               !dimension ? "vertical" : "horizontal" );
+      printf ( "  [ index |  pos |  dir  | link | serif |"
+               " numl | first | start ]\n" );
+
+      for ( seg = segments; seg < segment_limit; seg++ )
+      {
+        printf ( "  [ %5d | %4d | %5s | %4d | %5d | %4d | %5d | %5d ]\n",
+                 seg - segments,
+                 (int)seg->pos,
+                 seg->dir == AF_DIR_UP
+                   ? "up"
+                   : ( seg->dir == AF_DIR_DOWN
+                         ? "down"
+                         : ( seg->dir == AF_DIR_LEFT
+                               ? "left"
+                               : ( seg->dir == AF_DIR_RIGHT
+                                     ? "right"
+                                     : "none" ) ) ),
+                 seg->link ? ( seg->link - segments ) : -1,
+                 seg->serif ? ( seg->serif - segments ) : -1,
+                 (int)seg->num_linked,
+                 seg->first - points,
+                 seg->last - points );
+      }
+
+      segments      = hints->vert_segments;
+      segment_limit = segments + hints->num_vsegments;
+    }
+  }
+
+#endif /* AF_DEBUG */
+
+
+  /* compute the direction value of a given vector */
+  FT_LOCAL_DEF( AF_Direction )
+  af_direction_compute( FT_Pos  dx,
+                        FT_Pos  dy )
+  {
+    AF_Direction  dir;
+    FT_Pos        ax = ABS( dx );
+    FT_Pos        ay = ABS( dy );
+
+
+    dir = AF_DIR_NONE;
+
+    /* atan(1/12) == 4.7 degrees */
+
+    /* test for vertical direction */
+    if ( ax * 12 < ay )
+    {
+      dir = dy > 0 ? AF_DIR_UP : AF_DIR_DOWN;
+    }
+    /* test for horizontal direction */
+    else if ( ay * 12 < ax )
+    {
+      dir = dx > 0 ? AF_DIR_RIGHT : AF_DIR_LEFT;
+    }
+
+    return dir;
+  }
+
+
+  /* compute all inflex points in a given glyph */
+  static void
+  af_glyph_hints_compute_inflections( AF_GlyphHints  hints )
+  {
+    AF_Point*  contour       = hints->contours;
+    AF_Point*  contour_limit = contour + hints->num_contours;
+
+
+    /* do each contour separately */
+    for ( ; contour < contour_limit; contour++ )
+    {
+      AF_Point   point = contour[0];
+      AF_Point   first = point;
+      AF_Point   start = point;
+      AF_Point   end   = point;
+      AF_Point   before;
+      AF_Point   after;
+      AF_Angle   angle_in, angle_seg, angle_out;
+      AF_Angle   diff_in, diff_out;
+      FT_Int     finished = 0;
+
+
+      /* compute first segment in contour */
+      first = point;
+
+      start = end = first;
+      do
+      {
+        end = end->next;
+        if ( end == first )
+          goto Skip;
+
+      } while ( end->fx == first->fx && end->fy == first->fy );
+
+      angle_seg = af_angle_atan( end->fx - start->fx,
+                                 end->fy - start->fy );
+
+      /* extend the segment start whenever possible */
+      before = start;
+      do
+      {
+        do
+        {
+          start  = before;
+          before = before->prev;
+          if ( before == first )
+            goto Skip;
+
+        } while ( before->fx == start->fx && before->fy == start->fy );
+
+        angle_in = af_angle_atan( start->fx - before->fx,
+                                  start->fy - before->fy );
+
+      } while ( angle_in == angle_seg );
+
+      first   = start;
+      diff_in = af_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 ( end->fx == after->fx && end->fy == after->fy );
+
+          angle_out = af_angle_atan( after->fx - end->fx,
+                                     after->fy - end->fy );
+
+        } while ( angle_out == angle_seg );
+
+        diff_out = af_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
+          {
+            start->flags |= AF_FLAG_INFLECTION;
+            start = start->next;
+
+          } while ( start != end );
+
+          start->flags |= AF_FLAG_INFLECTION;
+        }
+
+        start     = end;
+        end       = after;
+        angle_seg = angle_out;
+        diff_in   = diff_out;
+
+      } while ( !finished );
+
+    Skip:
+      ;
+    }
+  }
+
+
+
+  FT_LOCAL_DEF( void )
+  af_glyph_hints_init( AF_GlyphHints  hints,
+                       FT_Memory      memory )
+  {
+    FT_ZERO( hints );
+    hints->memory = memory;
+  }
+
+
+
+  FT_LOCAL_DEF( void )
+  af_glyph_hints_done( AF_GlyphHints  hints )
+  {
+    if ( hints && hints->memory )
+    {
+      FT_Memory     memory = hints->memory;
+      AF_Dimension  dim;
+
+     /* note that we don't need to free the segment and edge
+      * buffers, since they're really within the hints->points array
+      */
+      for ( dim = 0; dim < 2; dim++ )
+      {
+        AF_AxisHints  axis = &hints->axis[ dim ];
+
+        axis->num_segments = 0;
+        axis->num_edges    = 0;
+        axis->segments     = NULL;
+        axis->edges        = NULL;
+      }
+
+      FT_FREE( hints->contours );
+      hints->max_contours = 0;
+      hints->num_contours = 0;
+
+      FT_FREE( hints->points );
+      hints->num_points = 0;
+      hints->max_points = 0;
+
+      hints->memory = NULL;
+    }
+  }
+
+
+
+  FT_LOCAL_DEF( FT_Error )
+  af_glyph_hints_reset( AF_GlyphHints  hints,
+                        AF_Scaler      scaler,
+                        FT_Outline*    outline )
+  {
+    FT_Error     error        = FT_Err_Ok;
+    AF_Point     points;
+    FT_UInt      old_max, new_max;
+    FT_Fixed     x_scale = scaler->x_scale;
+    FT_Fixed     y_scale = scaler->y_scale;
+    FT_Pos       x_delta = scaler->x_delta;
+    FT_Pos       y_delta = scaler->y_delta;
+    FT_Memory    memory  = hints->memory;
+
+    hints->scaler_flags = scaler->flags;
+    hints->other_flags  = 0;
+
+    hints->num_points    = 0;
+    hints->num_contours  = 0;
+
+    hints->axis[0].num_segments = 0;
+    hints->axis[0].num_edges    = 0;
+    hints->axis[1].num_segments = 0;
+    hints->axis[1].num_edges    = 0;
+
+   /* first of all, reallocate the contours array when necessary
+    */
+    new_max = (FT_UInt) outline->n_contours;
+    old_max = hints->max_contours;
+    if ( new_max > old_max )
+    {
+      new_max = (new_max + 3) & ~3;
+
+      if ( FT_RENEW_ARRAY( hints->contours, old_max, new_max ) )
+        goto Exit;
+
+      hints->max_contours = new_max;
+    }
+
+   /* then, reallocate the points, segments & edges arrays if needed --
+    * note that we reserved two additional point positions, used to
+    * hint metrics appropriately
+    */
+    new_max = (FT_UInt)( outline->n_points + 2 );
+    old_max = hints->max_points;
+    if ( new_max > old_max )
+    {
+      FT_Byte*    items;
+      FT_ULong    off1, off2, off3;
+
+     /* we store in a single buffer the following arrays:
+      *
+      *  - an array of   N  AF_PointRec   items
+      *  - an array of 2*N  AF_SegmentRec items
+      *  - an array of 2*N  AF_EdgeRec    items
+      *
+      */
+
+      new_max = ( new_max + 2 + 7 ) & ~7;
+
+#undef  OFF_INCREMENT
+#define OFF_INCREMENT( _off, _type, _count )   \
+     ( FT_PAD_CEIL( _off, sizeof(_type) ) + (_count)*sizeof(_type))
+
+      off1 = OFF_INCREMENT( 0, AF_PointRec, new_max );
+      off2 = OFF_INCREMENT( off1, AF_SegmentRec, new_max );
+      off3 = OFF_INCREMENT( off2, AF_EdgeRec, new_max*2 );
+
+      FT_FREE( hints->points );
+
+      if ( FT_ALLOC( items, off3 ) )
+      {
+        hints->max_points       = 0;
+        hints->axis[0].segments = NULL;
+        hints->axis[0].edges    = NULL;
+        hints->axis[1].segments = NULL;
+        hints->axis[1].edges    = NULL;
+        goto Exit;
+      }
+
+     /* readjust some pointers
+      */
+      hints->max_points       = new_max;
+      hints->points           = (AF_Point) items;
+
+      hints->axis[0].segments = (AF_Segment)( items + off1 );
+      hints->axis[1].segments = hints->axis[0].segments + new_max;
+
+      hints->axis[0].edges    = (AF_Edge)   ( items + off2 );
+      hints->axis[1].edges    = hints->axis[0].edges + new_max;
+    }
+
+    hints->num_points   = outline->n_points;
+    hints->num_contours = outline->n_contours;
+
+
+    /* We can't rely on the value of `FT_Outline.flags' to know the fill  */
+    /* direction used for a glyph, given that some fonts are broken (e.g. */
+    /* the Arphic ones).  We thus recompute it each time we need to.      */
+    /*                                                                    */
+    hints->axis[ AF_DIMENSION_HORZ ].major_dir = AF_DIR_UP;
+    hints->axis[ AF_DIMENSION_VERT ].major_dir = AF_DIR_LEFT;
+
+    if ( FT_Outline_Get_Orientation( outline ) == FT_ORIENTATION_POSTSCRIPT )
+    {
+      hints->axis[ AF_DIMENSION_HORZ ].major_dir = AF_DIR_DOWN;
+      hints->axis[ AF_DIMENSION_VERT ].major_dir = AF_DIR_RIGHT;
+    }
+
+    hints->x_scale = x_scale;
+    hints->y_scale = y_scale;
+    hints->x_delta = x_delta;
+    hints->y_delta = y_delta;
+
+    points = hints->points;
+    if ( hints->num_points == 0 )
+      goto Exit;
+
+    {
+      AF_Point  point;
+      AF_Point  point_limit = points + hints->num_points;
+
+
+      /* compute coordinates & bezier flags */
+      {
+        FT_Vector*  vec = outline->points;
+        char*       tag = outline->tags;
+
+
+        for ( point = points; point < point_limit; point++, vec++, tag++ )
+        {
+          point->fx = vec->x;
+          point->fy = vec->y;
+          point->ox = point->x = FT_MulFix( vec->x, x_scale ) + x_delta;
+          point->oy = point->y = FT_MulFix( vec->y, y_scale ) + y_delta;
+
+          switch ( FT_CURVE_TAG( *tag ) )
+          {
+          case FT_CURVE_TAG_CONIC:
+            point->flags = AF_FLAG_CONIC;
+            break;
+          case FT_CURVE_TAG_CUBIC:
+            point->flags = AF_FLAG_CUBIC;
+            break;
+          default:
+            point->flags = 0;
+            ;
+          }
+        }
+      }
+
+      /* compute `next' and `prev' */
+      {
+        FT_Int    contour_index;
+        AF_Point  prev;
+        AF_Point  first;
+        AF_Point  end;
+
+
+        contour_index = 0;
+
+        first = points;
+        end   = points + outline->contours[0];
+        prev  = end;
+
+        for ( point = points; point < point_limit; point++ )
+        {
+          point->prev = prev;
+          if ( point < end )
+          {
+            point->next = point + 1;
+            prev        = point;
+          }
+          else
+          {
+            point->next = first;
+            contour_index++;
+            if ( point + 1 < point_limit )
+            {
+              end   = points + outline->contours[contour_index];
+              first = point + 1;
+              prev  = end;
+            }
+          }
+        }
+      }
+
+      /* set-up the contours array */
+      {
+        AF_Point*  contour       = hints->contours;
+        AF_Point*  contour_limit = contour + hints->num_contours;
+        short*     end           = outline->contours;
+        short      idx           = 0;
+
+
+        for ( ; contour < contour_limit; contour++, end++ )
+        {
+          contour[0] = points + idx;
+          idx        = (short)( end[0] + 1 );
+        }
+      }
+
+      /* compute directions of in & out vectors */
+      {
+        for ( point = points; point < point_limit; point++ )
+        {
+          AF_Point   prev;
+          AF_Point   next;
+          FT_Pos     in_x, in_y, out_x, out_y;
+
+
+          prev   = point->prev;
+          in_x   = point->fx - prev->fx;
+          in_y   = point->fy - prev->fy;
+
+          point->in_dir = af_direction_compute( in_x, in_y );
+
+          next   = point->next;
+          out_x  = next->fx - point->fx;
+          out_y  = next->fy - point->fy;
+
+          point->out_dir = af_direction_compute( out_x, out_y );
+
+          if ( point->flags & ( AF_FLAG_CONIC | AF_FLAG_CUBIC ) )
+          {
+          Is_Weak_Point:
+            point->flags |= AF_FLAG_WEAK_INTERPOLATION;
+          }
+          else if ( point->out_dir == point->in_dir )
+          {
+            AF_Angle  angle_in, angle_out, delta;
+
+
+            if ( point->out_dir != AF_DIR_NONE )
+              goto Is_Weak_Point;
+
+            angle_in  = af_angle_atan( in_x, in_y );
+            angle_out = af_angle_atan( out_x, out_y );
+            delta     = af_angle_diff( angle_in, angle_out );
+
+            if ( delta < 2 && delta > -2 )
+              goto Is_Weak_Point;
+          }
+          else if ( point->in_dir == -point->out_dir )
+            goto Is_Weak_Point;
+        }
+      }
+    }
+
+   /* compute inflection points
+    */
+    af_glyph_hints_compute_inflections( hints );
+
+  Exit:
+    return error;
+  }
+
+
+
+
+ /*
+  *
+  *  E D G E   P O I N T   G R I D - F I T T I N G
+  *
+  */
+
+
+  FT_LOCAL_DEF( void )
+  af_glyph_hints_align_edge_points( AF_GlyphHints  hints,
+                                    AF_Dimension   dim )
+  {
+    AF_AxisHints  axis       = & hints->axis[ dim ];
+    AF_Edge       edges      = axis->edges;
+    AF_Edge       edge_limit = edges + axis->num_edges;
+    AF_Edge       edge;
+
+    for ( edge = edges; edge < edge_limit; edge++ )
+    {
+      /* move the points of each segment     */
+      /* in each edge to the edge's position */
+      AF_Segment  seg = edge->first;
+
+
+      do
+      {
+        AF_Point  point = seg->first;
+
+
+        for (;;)
+        {
+          if ( dim == AF_DIMENSION_HORZ )
+          {
+            point->x      = edge->pos;
+            point->flags |= AF_FLAG_TOUCH_X;
+          }
+          else
+          {
+            point->y      = edge->pos;
+            point->flags |= AF_FLAG_TOUCH_Y;
+          }
+
+          if ( point == seg->last )
+            break;
+
+          point = point->next;
+        }
+
+        seg = seg->edge_next;
+
+      } while ( seg != edge->first );
+    }
+  }
+
+
+ /*
+  *
+  *  S T R O N G   P O I N T   I N T E R P O L A T I O N
+  *
+  */
+
+
+  /* hint the strong points -- this is equivalent to the TrueType `IP' */
+  /* hinting instruction                                               */
+  FT_LOCAL_DEF( void )
+  af_glyph_hints_align_strong_points( AF_GlyphHints  hints,
+                                      AF_Dimension   dim )
+  {
+    AF_Point      points      = hints->points;
+    AF_Point      point_limit = points + hints->num_points;
+    AF_AxisHints  axis        = &hints->axis[dim];
+    AF_Edge       edges       = axis->edges;
+    AF_Edge       edge_limit  = edges + axis->num_edges;
+    AF_Flags      touch_flag;
+
+
+    if ( dim == AF_DIMENSION_HORZ )
+      touch_flag = AF_FLAG_TOUCH_X;
+    else
+      touch_flag  = AF_FLAG_TOUCH_Y;
+
+    if ( edges < edge_limit )
+    {
+      AF_Point  point;
+      AF_Edge   edge;
+
+      for ( point = points; point < point_limit; point++ )
+      {
+        FT_Pos  u, ou, fu;  /* point position */
+        FT_Pos  delta;
+
+
+        if ( point->flags & touch_flag )
+          continue;
+
+        /* if this point is candidate to weak interpolation, we will  */
+        /* interpolate it after all strong points have been processed */
+        if (  ( point->flags & AF_FLAG_WEAK_INTERPOLATION ) &&
+             !( point->flags & AF_FLAG_INFLECTION )         )
+          continue;
+
+        if ( dim == AF_DIMENSION_VERT )
+        {
+          u  = point->fy;
+          ou = point->oy;
+        }
+        else
+        {
+          u  = point->fx;
+          ou = point->ox;
+        }
+
+        fu = u;
+
+        /* is the point before the first edge? */
+        edge  = edges;
+        delta = edge->fpos - u;
+        if ( delta >= 0 )
+        {
+          u = edge->pos - ( edge->opos - ou );
+          goto Store_Point;
+        }
+
+        /* is the point after the last edge? */
+        edge  = edge_limit - 1;
+        delta = u - edge->fpos;
+        if ( delta >= 0 )
+        {
+          u = edge->pos + ( ou - edge->opos );
+          goto Store_Point;
+        }
+
+        {
+          FT_UInt  min, max, mid;
+          FT_Pos   fpos;
+
+
+          /* find enclosing edges */
+          min = 0;
+          max = edge_limit - edges;
+
+          while ( min < max )
+          {
+            mid  = ( max + min ) >> 1;
+            edge = edges + mid;
+            fpos = edge->fpos;
+
+            if ( u < fpos )
+              max = mid;
+            else if ( u > fpos )
+              min = mid + 1;
+            else
+            {
+              /* we are on the edge */
+              u = edge->pos;
+              goto Store_Point;
+            }
+          }
+
+          {
+            AF_Edge  before = edges + min - 1;
+            AF_Edge  after  = edges + min + 0;
+
+
+            /* assert( before && after && before != after ) */
+            if ( before->scale == 0 )
+              before->scale = FT_DivFix( after->pos - before->pos,
+                                         after->fpos - before->fpos );
+
+            u = before->pos + FT_MulFix( fu - before->fpos,
+                                         before->scale );
+          }
+        }
+
+
+      Store_Point:
+
+        /* save the point position */
+        if ( dim == AF_DIMENSION_HORZ )
+          point->x = u;
+        else
+          point->y = u;
+
+        point->flags |= touch_flag;
+      }
+    }
+  }
+
+
+ /*
+  *
+  *  W E A K   P O I N T   I N T E R P O L A T I O N
+  *
+  */
+
+  static void
+  af_iup_shift( AF_Point  p1,
+                AF_Point  p2,
+                AF_Point  ref )
+  {
+    AF_Point  p;
+    FT_Pos    delta = ref->u - ref->v;
+
+
+    for ( p = p1; p < ref; p++ )
+      p->u = p->v + delta;
+
+    for ( p = ref + 1; p <= p2; p++ )
+      p->u = p->v + delta;
+  }
+
+
+  static void
+  af_iup_interp( AF_Point  p1,
+                 AF_Point  p2,
+                 AF_Point  ref1,
+                 AF_Point  ref2 )
+  {
+    AF_Point  p;
+    FT_Pos    u;
+    FT_Pos    v1 = ref1->v;
+    FT_Pos    v2 = ref2->v;
+    FT_Pos    d1 = ref1->u - v1;
+    FT_Pos    d2 = ref2->u - v2;
+
+
+    if ( p1 > p2 )
+      return;
+
+    if ( v1 == v2 )
+    {
+      for ( p = p1; p <= p2; p++ )
+      {
+        u = p->v;
+
+        if ( u <= v1 )
+          u += d1;
+        else
+          u += d2;
+
+        p->u = u;
+      }
+      return;
+    }
+
+    if ( v1 < v2 )
+    {
+      for ( p = p1; p <= p2; p++ )
+      {
+        u = p->v;
+
+        if ( u <= v1 )
+          u += d1;
+        else if ( u >= v2 )
+          u += d2;
+        else
+          u = ref1->u + FT_MulDiv( u - v1, ref2->u - ref1->u, v2 - v1 );
+
+        p->u = u;
+      }
+    }
+    else
+    {
+      for ( p = p1; p <= p2; p++ )
+      {
+        u = p->v;
+
+        if ( u <= v2 )
+          u += d2;
+        else if ( u >= v1 )
+          u += d1;
+        else
+          u = ref1->u + FT_MulDiv( u - v1, ref2->u - ref1->u, v2 - v1 );
+
+        p->u = u;
+      }
+    }
+  }
+
+
+  FT_LOCAL_DEF( void )
+  af_glyph_hints_align_weak_points( AF_GlyphHints  hints,
+                                    AF_Dimension   dim )
+  {
+    AF_Point    points        = hints->points;
+    AF_Point    point_limit   = points + hints->num_points;
+    AF_Point*   contour       = hints->contours;
+    AF_Point*   contour_limit = contour + hints->num_contours;
+    AF_Flags    touch_flag;
+    AF_Point    point;
+    AF_Point    end_point;
+    AF_Point    first_point;
+
+
+    /* PASS 1: Move segment points to edge positions */
+
+    if ( dim == AF_DIMENSION_HORZ )
+    {
+      touch_flag = AF_FLAG_TOUCH_X;
+
+      for ( point = points; point < point_limit; point++ )
+      {
+        point->u = point->x;
+        point->v = point->ox;
+      }
+    }
+    else
+    {
+      touch_flag = AF_FLAG_TOUCH_Y;
+
+      for ( point = points; point < point_limit; point++ )
+      {
+        point->u = point->y;
+        point->v = point->oy;
+      }
+    }
+
+    point   = points;
+
+    for ( ; contour < contour_limit; contour++ )
+    {
+      point       = *contour;
+      end_point   = point->prev;
+      first_point = point;
+
+      while ( point <= end_point && !( point->flags & touch_flag ) )
+        point++;
+
+      if ( point <= end_point )
+      {
+        AF_Point  first_touched = point;
+        AF_Point  cur_touched   = point;
+
+
+        point++;
+        while ( point <= end_point )
+        {
+          if ( point->flags & touch_flag )
+          {
+            /* we found two successive touched points; we interpolate */
+            /* all contour points between them                        */
+            af_iup_interp( cur_touched + 1, point - 1,
+                           cur_touched, point );
+            cur_touched = point;
+          }
+          point++;
+        }
+
+        if ( cur_touched == first_touched )
+        {
+          /* this is a special case: only one point was touched in the */
+          /* contour; we thus simply shift the whole contour           */
+          af_iup_shift( first_point, end_point, cur_touched );
+        }
+        else
+        {
+          /* now interpolate after the last touched point to the end */
+          /* of the contour                                          */
+          af_iup_interp( cur_touched + 1, end_point,
+                         cur_touched, first_touched );
+
+          /* if the first contour point isn't touched, interpolate */
+          /* from the contour start to the first touched point     */
+          if ( first_touched > points )
+            af_iup_interp( first_point, first_touched - 1,
+                           cur_touched, first_touched );
+        }
+      }
+    }
+
+    /* now save the interpolated values back to x/y */
+    if ( dim == AF_DIMENSION_HORZ )
+    {
+      for ( point = points; point < point_limit; point++ )
+        point->x = point->u;
+    }
+    else
+    {
+      for ( point = points; point < point_limit; point++ )
+        point->y = point->u;
+    }
+  }
+
+
+
+
--- a/src/autofit/aflatin.c
+++ b/src/autofit/aflatin.c
@@ -374,12 +374,28 @@
 
     axis = & metrics->axis[ dim ];
 
-    if ( axis->scale == scale && axis->delta == delta )
+    if ( axis->org_scale == scale && axis->org_delta == delta )
       return;
 
+    axis->org_scale = scale;
+    axis->org_delta = delta;
+
+   /* XXX: TODO: Correct Y and X scale according to Chester rules
+    */
     axis->scale = scale;
     axis->delta = delta;
 
+    if ( dim == AF_DIMENSION_HORZ )
+    {
+      metrics->scaler.x_scale = scale;
+      metrics->scaler.x_delta = delta;
+    }
+    else
+    {
+      metrics->scaler.y_scale = scale;
+      metrics->scaler.y_delta = delta;
+    }
+
    /* scale the standard widths
     */
     for ( nn = 0; nn < axis->width_count; nn++ )
@@ -419,6 +435,8 @@
   af_latin_metrics_scale( AF_LatinMetrics  metrics,
                           AF_Scaler        scaler )
   {
+    metrics->scaler = scaler[0];
+
     af_latin_metrics_scale_dim( metrics, scaler, AF_DIMENSION_HORZ );
     af_latin_metrics_scale_dim( metrics, scaler, AF_DIMENSION_VERT );
   }
@@ -1120,7 +1138,6 @@
 
   static FT_Error
   af_latin_hints_init( AF_GlyphHints    hints,
-                       AF_Scaler        scaler,
                        FT_Outline*      outline,
                        AF_LatinMetrics  metrics )
   {
@@ -1127,7 +1144,7 @@
     FT_Error        error;
     FT_Render_Mode  mode;
 
-    error = af_glyph_hints_reset( hints, scaler, outline );
+    error = af_glyph_hints_reset( hints, &metrics->scaler, outline );
     if (error)
       goto Exit;
 
@@ -1135,7 +1152,7 @@
    /* compute flags depending on render mode, etc...
     */
 
-    mode = scaler->render_mode;
+    mode = metrics->scaler.render_mode;
 
    /* we snap the width of vertical stems for the monochrome and
     * horizontal LCD rendering targets only.
@@ -1716,12 +1733,10 @@
 
   static FT_Error
   af_latin_hints_apply( AF_GlyphHints    hints,
-                        AF_Scaler        scaler,
                         AF_LatinMetrics  metrics )
   {
     AF_Dimension  dim;
 
-    FT_UNUSED( scaler );
     FT_UNUSED( metrics );
 
     for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
--- a/src/autofit/aflatin.h
+++ b/src/autofit/aflatin.h
@@ -81,6 +81,9 @@
     FT_UInt          blue_count;
     AF_LatinBlueRec  blues[ AF_LATIN_BLUE_MAX ];
 
+    FT_Fixed         org_scale;
+    FT_Pos           org_delta;
+
   } AF_LatinAxisRec, *AF_LatinAxis;
 
 
@@ -89,6 +92,7 @@
     AF_ScriptMetricsRec   root;
     FT_UInt               units_per_em;
     AF_LatinAxisRec       axis[ AF_DIMENSION_MAX ];
+    AF_ScalerRec          scaler;
 
   } AF_LatinMetricsRec, *AF_LatinMetrics;
 
--- a/src/autofit/afloader.c
+++ b/src/autofit/afloader.c
@@ -1,505 +1,431 @@
-#include "afloader.h"
-#include "afhints.h"
-#include "afglobal.h"
-#include "aflatin.h"
-
-  FT_LOCAL_DEF( void )
-  af_loader_init( AF_Loader  loader,
-                  FT_Memory  memory )
-  {
-    FT_ZERO( loader );
-
-    af_glyph_hints_init( &loader->hints, memory );
-  }
-
-
-  FT_LOCAL_DEF( FT_Error )
-  af_loader_reset( AF_Loader   loader,
-                   FT_Face     face )
-  {
-    FT_Error   error = 0;
-
-    FT_ZERO( loader );
-
-    loader->face    = face;
-    loader->gloader = face->slot->internal->loader;
-    loader->globals = (AF_FaceGlobals) face->autohint.data;
-
-    if ( loader->globals == NULL )
-    {
-      error = af_face_globals_new( &face, &loader->globals );
-      if ( !error )
-      {
-        face->autohint.data      = (FT_Pointer) loader->globals;
-        face->autohint.finalizer = (FT_Generic_Finalizer) af_face_globals_free;
-      }
-    }
-    return error;
-  }
-
-
-  FT_LOCAL_DEF( void )
-  af_loader_done( AF_Loader   loader )
-  {
-    loader->face    = face;
-    loader->globals = NULL;
-    loader->gloader = NULL;
-  }
-
-
-  static FT_Error
-  af_hinter_load_g( AF_Loader  loader,
-                    AF_Scaler  scaler,
-                    FT_UInt    glyph_index,
-                    FT_Int32   load_flags,
-                    FT_UInt    depth )
-  {
-    FT_Error          error    = 0;
-    FT_Face           face     = loader->face;
-    AF_FaceGlobals    globals  = loader->globals;
-    FT_GlyphLoader    gloader  = loader->gloader;
-    AF_ScriptMetrics  metrics  = loader->metrics;
-    AF_GlyphHints     hints    = &loader->hints;
-    FT_GlyphSlot      slot     = face->glyph;
-    FT_Slot_Internal  internal = slot->internal;
-
-    error = FT_Load_Glyph( face, glyph_index, load_flags );
-    if ( error )
-      goto Exit;
-
-    loader->transformed = internal->glyph_transformed;
-    if ( loader->transformed )
-    {
-      FT_Matrix  inverse;
-
-      loader->trans_matrix = internal->glyph_matrix;
-      loader->trans_delta  = internal->glyph_delta;
-
-      inverse = loader->trans_matrix;
-      FT_Matrix_Invert( &inverse );
-      FT_Vector_Transform( &loader->trans_delta, &inverse );
-    }
-
-    /* set linear metrics */
-    slot->linearHoriAdvance = slot->metrics.horiAdvance;
-    slot->linearVertAdvance = slot->metrics.vertAdvance;
-
-    switch ( slot->format )
-    {
-      case FT_GLYPH_FORMAT_OUTLINE:
-       /* translate the loaded glyph when an internal transform
-        * is needed
-        */
-        if ( loader->transformed )
-        {
-          FT_Vector*  point = slot->outline.points;
-          FT_Vector*  limit = point + slot->outline.n_points;
-
-          for ( ; point < limit; point++ )
-          {
-            point->x += loader->trans_delta.x;
-            point->y += loader->trans_delta.y;
-          }
-        }
-
-        /* copy the outline points in the loader's current               */
-        /* extra points which is used to keep original glyph coordinates */
-        error = FT_GlyphLoader_CheckPoints( gloader,
-                                            slot->outline.n_points + 2,
-                                            slot->outline.n_contours );
-        if ( error )
-          goto Exit;
-
-        FT_ARRAY_COPY( gloader->current.extra_points,
-                       slot->outline.points,
-                       slot->outline.n_points );
-
-        FT_ARRAY_COPY( gloader->current.outline.contours,
-                       slot->outline.contours,
-                       slot->outline.n_contours );
-
-        FT_ARRAY_COPY( gloader->current.outline.tags,
-                       slot->outline.tags,
-                       slot->outline.n_points );
-
-        gloader->current.outline.n_points   = slot->outline.n_points;
-        gloader->current.outline.n_contours = slot->outline.n_contours;
-
-        /* compute original phantom points */
-        loader->pp1.x = hints->x_delta;
-        loader->pp1.y = hints->y_delta;
-        loader->pp2.x = FT_MulFix( slot->metrics.horiAdvance,
-                                   hints->x_scale ) + hints->x_delta;
-        loader->pp2.y = hints->y_delta;
-
-        /* be sure to check for spacing glyphs */
-        if ( slot->outline.n_points == 0 )
-          goto Hint_Metrics;
-
-        /* now load the slot image into the auto-outline and run the */
-        /* automatic hinting process                                 */
-        error = metrics->clazz->script_hints_init( hints, scaler,
-                                                   &gloader->current.outline,
-                                                   metrics );
-        if ( error )
-          goto Exit;
-
-        /* apply the hints */
-        error = metrics->clazz->script_hints_apply( hints, scaler,
-                                                    &gloader->current.outline,
-                                                    metrics );
-        if ( error )
-          goto Exit;
-
-        /* we now need to hint the metrics according to the change in */
-        /* width/positioning that occured during the hinting process  */
-        {
-          FT_Pos   old_advance, old_rsb, old_lsb, new_lsb;
-          AF_Edge  edge1 = outline->vert_edges;     /* leftmost edge  */
-          AF_Edge  edge2 = edge1 +
-                           outline->num_vedges - 1; /* rightmost edge */
-
-
-          old_advance = hinter->pp2.x;
-          old_rsb     = old_advance - edge2->opos;
-          old_lsb     = edge1->opos;
-          new_lsb     = edge1->pos;
-
-          hinter->pp1.x = FT_PIX_ROUND( new_lsb    - old_lsb );
-          hinter->pp2.x = FT_PIX_ROUND( edge2->pos + old_rsb );
-
-#if 0
-          /* try to fix certain bad advance computations */
-          if ( hinter->pp2.x + hinter->pp1.x == edge2->pos && old_rsb > 4 )
-            hinter->pp2.x += 64;
-#endif
-        }
-
-        /* good, we simply add the glyph to our loader's base */
-        FT_GlyphLoader_Add( gloader );
-        break;
-
-    case FT_GLYPH_FORMAT_COMPOSITE:
-      {
-        FT_UInt      nn, num_subglyphs = slot->num_subglyphs;
-        FT_UInt      num_base_subgs, start_point;
-        FT_SubGlyph  subglyph;
-
-
-        start_point = gloader->base.outline.n_points;
-
-        /* first of all, copy the subglyph descriptors in the glyph loader */
-        error = FT_GlyphLoader_CheckSubGlyphs( gloader, num_subglyphs );
-        if ( error )
-          goto Exit;
-
-        FT_ARRAY_COPY( gloader->current.subglyphs,
-                       slot->subglyphs,
-                       num_subglyphs );
-
-        gloader->current.num_subglyphs = num_subglyphs;
-        num_base_subgs = gloader->base.num_subglyphs;
-
-        /* now, read each subglyph independently */
-        for ( nn = 0; nn < num_subglyphs; nn++ )
-        {
-          FT_Vector  pp1, pp2;
-          FT_Pos     x, y;
-          FT_UInt    num_points, num_new_points, num_base_points;
-
-
-          /* gloader.current.subglyphs can change during glyph loading due */
-          /* to re-allocation -- we must recompute the current subglyph on */
-          /* each iteration                                                */
-          subglyph = gloader->base.subglyphs + num_base_subgs + nn;
-
-          pp1 = hinter->pp1;
-          pp2 = hinter->pp2;
-
-          num_base_points = gloader->base.outline.n_points;
-
-          error = af_loader_load_g( loader, scaler, subglyph->index,
-                                  load_flags, depth + 1 );
-          if ( error )
-            goto Exit;
-
-          /* recompute subglyph pointer */
-          subglyph = gloader->base.subglyphs + num_base_subgs + nn;
-
-          if ( subglyph->flags & FT_SUBGLYPH_FLAG_USE_MY_METRICS )
-          {
-            pp1 = hinter->pp1;
-            pp2 = hinter->pp2;
-          }
-          else
-          {
-            hinter->pp1 = pp1;
-            hinter->pp2 = pp2;
-          }
-
-          num_points     = gloader->base.outline.n_points;
-          num_new_points = num_points - num_base_points;
-
-          /* now perform the transform required for this subglyph */
-
-          if ( subglyph->flags & ( FT_SUBGLYPH_FLAG_SCALE    |
-                                   FT_SUBGLYPH_FLAG_XY_SCALE |
-                                   FT_SUBGLYPH_FLAG_2X2      ) )
-          {
-            FT_Vector*  cur   = gloader->base.outline.points +
-                                num_base_points;
-            FT_Vector*  org   = gloader->base.extra_points +
-                                num_base_points;
-            FT_Vector*  limit = cur + num_new_points;
-
-
-            for ( ; cur < limit; cur++, org++ )
-            {
-              FT_Vector_Transform( cur, &subglyph->transform );
-              FT_Vector_Transform( org, &subglyph->transform );
-            }
-          }
-
-          /* apply offset */
-
-          if ( !( subglyph->flags & FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES ) )
-          {
-            FT_Int      k = subglyph->arg1;
-            FT_UInt     l = subglyph->arg2;
-            FT_Vector*  p1;
-            FT_Vector*  p2;
-
-
-            if ( start_point + k >= num_base_points         ||
-                               l >= (FT_UInt)num_new_points )
-            {
-              error = FT_Err_Invalid_Composite;
-              goto Exit;
-            }
-
-            l += num_base_points;
-
-            /* for now, only use the current point coordinates;    */
-            /* we may consider another approach in the near future */
-            p1 = gloader->base.outline.points + start_point + k;
-            p2 = gloader->base.outline.points + start_point + l;
-
-            x = p1->x - p2->x;
-            y = p1->y - p2->y;
-          }
-          else
-          {
-            x = FT_MulFix( subglyph->arg1, hints->x_scale ) + hints->x_delta;
-            y = FT_MulFix( subglyph->arg2, hints->y_scale ) + hints->y_delta;
-
-            x = FT_PIX_ROUND(x);
-            y = FT_PIX_ROUND(y);
-          }
-
-          {
-            FT_Outline  dummy = gloader->base.outline;
-
-
-            dummy.points  += num_base_points;
-            dummy.n_points = (short)num_new_points;
-
-            FT_Outline_Translate( &dummy, x, y );
-          }
-        }
-      }
-      break;
-
-    default:
-      /* we don't support other formats (yet?) */
-      error = AF_Err_Unimplemented_Feature;
-    }
-
-  Hint_Metrics:
-    if ( depth == 0 )
-    {
-      FT_BBox  bbox;
-
-
-      /* transform the hinted outline if needed */
-      if ( hinter->transformed )
-        FT_Outline_Transform( &gloader->base.outline, &hinter->trans_matrix );
-
-      /* we must translate our final outline by -pp1.x and compute */
-      /* the new metrics                                           */
-      if ( hinter->pp1.x )
-        FT_Outline_Translate( &gloader->base.outline, -hinter->pp1.x, 0 );
-
-      FT_Outline_Get_CBox( &gloader->base.outline, &bbox );
-      bbox.xMin  = FT_PIX_FLOOR(  bbox.xMin );
-      bbox.yMin  = FT_PIX_FLOOR(  bbox.yMin );
-      bbox.xMax  = FT_PIX_CEIL( bbox.xMax );
-      bbox.yMax  = FT_PIX_CEIL( bbox.yMax );
-
-      slot->metrics.width        = bbox.xMax - bbox.xMin;
-      slot->metrics.height       = bbox.yMax - bbox.yMin;
-      slot->metrics.horiBearingX = bbox.xMin;
-      slot->metrics.horiBearingY = bbox.yMax;
-
-      /* for mono-width fonts (like Andale, Courier, etc.) we need */
-      /* to keep the original rounded advance width                */
-      if ( !FT_IS_FIXED_WIDTH( slot->face ) )
-        slot->metrics.horiAdvance = hinter->pp2.x - hinter->pp1.x;
-      else
-        slot->metrics.horiAdvance = FT_MulFix( slot->metrics.horiAdvance,
-                                               x_scale );
-
-      slot->metrics.horiAdvance = FT_PIX_ROUND( slot->metrics.horiAdvance );
-
-      /* now copy outline into glyph slot */
-      af_loader_rewind( slot->internal->loader );
-      error = af_loader_copy_points( slot->internal->loader, gloader );
-      if ( error )
-        goto Exit;
-
-      slot->outline = slot->internal->loader->base.outline;
-      slot->format  = FT_GLYPH_FORMAT_OUTLINE;
-    }
-
-#ifdef DEBUG_HINTER
-    af_debug_hinter = hinter;
-#endif
-
-  Exit:
-    return error;
-  }
-
-
-
-
-
-  /* load and hint a given glyph */
-  FT_LOCAL_DEF( FT_Error )
-  af_loader_load_g( AF_Hinter     hinter,
-                    FT_GlyphSlot  slot,
-                    FT_Size       size,
-                    FT_UInt       glyph_index,
-                    FT_Int32      load_flags )
-  {
-    FT_Face          face         = slot->face;
-    FT_Error         error;
-    FT_Fixed         x_scale      = size->metrics.x_scale;
-    FT_Fixed         y_scale      = size->metrics.y_scale;
-    AF_Face_Globals  face_globals = FACE_GLOBALS( face );
-    FT_Render_Mode   hint_mode    = FT_LOAD_TARGET_MODE( load_flags );
-
-
-    /* first of all, we need to check that we're using the correct face and */
-    /* global hints to load the glyph                                       */
-    if ( hinter->face != face || hinter->globals != face_globals )
-    {
-      hinter->face = face;
-      if ( !face_globals )
-      {
-        error = af_hinter_new_face_globals( hinter, face, 0 );
-        if ( error )
-          goto Exit;
-
-      }
-      hinter->globals = FACE_GLOBALS( face );
-      face_globals    = FACE_GLOBALS( face );
-
-    }
-
-#ifdef FT_CONFIG_CHESTER_BLUE_SCALE
-
-   /* try to optimize the y_scale so that the top of non-capital letters
-    * is aligned on a pixel boundary whenever possible
-    */
-    {
-      AF_Globals  design = &face_globals->design;
-      FT_Pos      shoot  = design->blue_shoots[AF_BLUE_SMALL_TOP];
-
-
-      /* the value of 'shoot' will be -1000 if the font doesn't have */
-      /* small latin letters; we simply check the sign here...       */
-      if ( shoot > 0 )
-      {
-        FT_Pos  scaled = FT_MulFix( shoot, y_scale );
-        FT_Pos  fitted = FT_PIX_ROUND( scaled );
-
-
-        if ( scaled != fitted )
-        {
-         /* adjust y_scale
-          */
-          y_scale = FT_MulDiv( y_scale, fitted, scaled );
-
-         /* adust x_scale
-          */
-          if ( fitted < scaled )
-            x_scale -= x_scale / 50;  /* x_scale*0.98 with integers */
-        }
-      }
-    }
-
-#endif /* FT_CONFIG_CHESTER_BLUE_SCALE */
-
-    /* now, we must check the current character pixel size to see if we */
-    /* need to rescale the global metrics                               */
-    if ( face_globals->x_scale != x_scale ||
-         face_globals->y_scale != y_scale )
-      af_hinter_scale_globals( hinter, x_scale, y_scale );
-
-    af_loader_rewind( hinter->loader );
-
-    /* reset hinting flags according to load flags and current render target */
-    hinter->do_horz_hints = FT_BOOL( !(load_flags & FT_LOAD_NO_AUTOHINT) );
-    hinter->do_vert_hints = FT_BOOL( !(load_flags & FT_LOAD_NO_AUTOHINT) );
-
-#ifdef DEBUG_HINTER
-    hinter->do_horz_hints = !af_debug_disable_vert;  /* not a bug, the meaning */
-    hinter->do_vert_hints = !af_debug_disable_horz;  /* of h/v is inverted!    */
-#endif
-
-    /* we snap the width of vertical stems for the monochrome and         */
-    /* horizontal LCD rendering targets only.  Corresponds to X snapping. */
-    hinter->do_horz_snapping = FT_BOOL( hint_mode == FT_RENDER_MODE_MONO ||
-                                        hint_mode == FT_RENDER_MODE_LCD  );
-
-    /* we snap the width of horizontal stems for the monochrome and     */
-    /* vertical LCD rendering targets only.  Corresponds to Y snapping. */
-    hinter->do_vert_snapping = FT_BOOL( hint_mode == FT_RENDER_MODE_MONO   ||
-                                        hint_mode == FT_RENDER_MODE_LCD_V  );
-
-    hinter->do_stem_adjust   = FT_BOOL( hint_mode != FT_RENDER_MODE_LIGHT );
-
-    load_flags |= FT_LOAD_NO_SCALE
-                | FT_LOAD_IGNORE_TRANSFORM;
-    load_flags &= ~FT_LOAD_RENDER;
-
-    error = af_hinter_load( hinter, glyph_index, load_flags, 0 );
-
-  Exit:
-    return error;
-  }
-
-
-  static FT_Error
-  af_loader_load_glyph( AF_Loader   loader,
-                        AF_Scaler   scaler,
-                        FT_UInt     glyph_index )
-  {
-    FT_Error  error;
-    FT_Face   face = scaler->face;
-
-    error = af_loader_reset( loader, face );
-    if ( !error )
-    {
-      AF_ScriptMetrics  metrics;
-
-      error = af_face_globals_get_metrics( globals, gindex, &metrics );
-      if ( !error )
-      {
-        metrics->clazz->script_metrics_scale( metrics, scaler );
-
-        error = af_loader_load_g( loader, scaler, metrics, glyph_index,
-                                  /* load_flags */, 0 );
-      }
-    }
-    return error;
-  }
+#include "afloader.h"
+#include "afhints.h"
+#include "afglobal.h"
+#include "aflatin.h"
+
+  FT_LOCAL_DEF( FT_Error )
+  af_loader_init( AF_Loader  loader,
+                  FT_Memory  memory )
+  {
+    FT_Error  error;
+
+    FT_ZERO( loader );
+
+    af_glyph_hints_init( &loader->hints, memory );
+
+    error = FT_GlyphLoader_New( memory, &loader->gloader );
+    if ( !error )
+    {
+      error = FT_GlyphLoader_CreateExtra( loader->gloader );
+      if ( error )
+      {
+        FT_GlyphLoader_Done( loader->gloader );
+        loader->gloader = NULL;
+      }
+    }
+    return error;
+  }
+
+
+  FT_LOCAL_DEF( FT_Error )
+  af_loader_reset( AF_Loader   loader,
+                   FT_Face     face )
+  {
+    FT_Error   error = 0;
+
+    loader->face    = face;
+    loader->gloader = face->glyph->internal->loader;
+    loader->globals = (AF_FaceGlobals) face->autohint.data;
+
+    if ( loader->globals == NULL )
+    {
+      error = af_face_globals_new( face, &loader->globals );
+      if ( !error )
+      {
+        face->autohint.data      = (FT_Pointer) loader->globals;
+        face->autohint.finalizer = (FT_Generic_Finalizer) af_face_globals_free;
+      }
+    }
+    return error;
+  }
+
+
+  FT_LOCAL_DEF( void )
+  af_loader_done( AF_Loader   loader )
+  {
+    loader->face    = NULL;
+    loader->globals = NULL;
+
+    FT_GlyphLoader_Done( loader->gloader );
+    loader->gloader = NULL;
+  }
+
+
+  static FT_Error
+  af_loader_load_g( AF_Loader  loader,
+                    AF_Scaler  scaler,
+                    FT_UInt    glyph_index,
+                    FT_Int32   load_flags,
+                    FT_UInt    depth )
+  {
+    FT_Error          error    = 0;
+    FT_Face           face     = loader->face;
+    AF_FaceGlobals    globals  = loader->globals;
+    FT_GlyphLoader    gloader  = loader->gloader;
+    AF_ScriptMetrics  metrics  = loader->metrics;
+    AF_GlyphHints     hints    = &loader->hints;
+    FT_GlyphSlot      slot     = face->glyph;
+    FT_Slot_Internal  internal = slot->internal;
+
+    error = FT_Load_Glyph( face, glyph_index, load_flags );
+    if ( error )
+      goto Exit;
+
+    loader->transformed = internal->glyph_transformed;
+    if ( loader->transformed )
+    {
+      FT_Matrix  inverse;
+
+      loader->trans_matrix = internal->glyph_matrix;
+      loader->trans_delta  = internal->glyph_delta;
+
+      inverse = loader->trans_matrix;
+      FT_Matrix_Invert( &inverse );
+      FT_Vector_Transform( &loader->trans_delta, &inverse );
+    }
+
+    /* set linear metrics */
+    slot->linearHoriAdvance = slot->metrics.horiAdvance;
+    slot->linearVertAdvance = slot->metrics.vertAdvance;
+
+    switch ( slot->format )
+    {
+      case FT_GLYPH_FORMAT_OUTLINE:
+       /* translate the loaded glyph when an internal transform
+        * is needed
+        */
+        if ( loader->transformed )
+        {
+          FT_Vector*  point = slot->outline.points;
+          FT_Vector*  limit = point + slot->outline.n_points;
+
+          for ( ; point < limit; point++ )
+          {
+            point->x += loader->trans_delta.x;
+            point->y += loader->trans_delta.y;
+          }
+        }
+
+        /* copy the outline points in the loader's current               */
+        /* extra points which is used to keep original glyph coordinates */
+        error = FT_GlyphLoader_CheckPoints( gloader,
+                                            slot->outline.n_points + 2,
+                                            slot->outline.n_contours );
+        if ( error )
+          goto Exit;
+
+        FT_ARRAY_COPY( gloader->current.extra_points,
+                       slot->outline.points,
+                       slot->outline.n_points );
+
+        FT_ARRAY_COPY( gloader->current.outline.contours,
+                       slot->outline.contours,
+                       slot->outline.n_contours );
+
+        FT_ARRAY_COPY( gloader->current.outline.tags,
+                       slot->outline.tags,
+                       slot->outline.n_points );
+
+        gloader->current.outline.n_points   = slot->outline.n_points;
+        gloader->current.outline.n_contours = slot->outline.n_contours;
+
+        /* compute original phantom points */
+        loader->pp1.x = hints->x_delta;
+        loader->pp1.y = hints->y_delta;
+        loader->pp2.x = FT_MulFix( slot->metrics.horiAdvance,
+                                   hints->x_scale ) + hints->x_delta;
+        loader->pp2.y = hints->y_delta;
+
+        /* be sure to check for spacing glyphs */
+        if ( slot->outline.n_points == 0 )
+          goto Hint_Metrics;
+
+        /* now load the slot image into the auto-outline and run the */
+        /* automatic hinting process                                 */
+        error = metrics->clazz->script_hints_init( hints,
+                                                   &gloader->current.outline,
+                                                   metrics );
+        if ( error )
+          goto Exit;
+
+        /* apply the hints */
+        metrics->clazz->script_hints_apply( hints,
+                                            &gloader->current.outline,
+                                            metrics );
+        /* we now need to hint the metrics according to the change in */
+        /* width/positioning that occured during the hinting process  */
+        {
+          FT_Pos        old_advance, old_rsb, old_lsb, new_lsb;
+          AF_AxisHints  axis  = &hints->axis[ AF_DIMENSION_HORZ ];
+          AF_Edge       edge1 = axis->edges;    /* leftmost edge  */
+          AF_Edge       edge2 = edge1 + axis->num_edges - 1; /* rightmost edge */
+
+
+          old_advance = loader->pp2.x;
+          old_rsb     = old_advance - edge2->opos;
+          old_lsb     = edge1->opos;
+          new_lsb     = edge1->pos;
+
+          loader->pp1.x = FT_PIX_ROUND( new_lsb    - old_lsb );
+          loader->pp2.x = FT_PIX_ROUND( edge2->pos + old_rsb );
+
+#if 0
+          /* try to fix certain bad advance computations */
+          if ( loader->pp2.x + loader->pp1.x == edge2->pos && old_rsb > 4 )
+            loader->pp2.x += 64;
+#endif
+        }
+
+        /* good, we simply add the glyph to our loader's base */
+        FT_GlyphLoader_Add( gloader );
+        break;
+
+    case FT_GLYPH_FORMAT_COMPOSITE:
+      {
+        FT_UInt      nn, num_subglyphs = slot->num_subglyphs;
+        FT_UInt      num_base_subgs, start_point;
+        FT_SubGlyph  subglyph;
+
+
+        start_point = gloader->base.outline.n_points;
+
+        /* first of all, copy the subglyph descriptors in the glyph loader */
+        error = FT_GlyphLoader_CheckSubGlyphs( gloader, num_subglyphs );
+        if ( error )
+          goto Exit;
+
+        FT_ARRAY_COPY( gloader->current.subglyphs,
+                       slot->subglyphs,
+                       num_subglyphs );
+
+        gloader->current.num_subglyphs = num_subglyphs;
+        num_base_subgs = gloader->base.num_subglyphs;
+
+        /* now, read each subglyph independently */
+        for ( nn = 0; nn < num_subglyphs; nn++ )
+        {
+          FT_Vector  pp1, pp2;
+          FT_Pos     x, y;
+          FT_UInt    num_points, num_new_points, num_base_points;
+
+
+          /* gloader.current.subglyphs can change during glyph loading due */
+          /* to re-allocation -- we must recompute the current subglyph on */
+          /* each iteration                                                */
+          subglyph = gloader->base.subglyphs + num_base_subgs + nn;
+
+          pp1 = loader->pp1;
+          pp2 = loader->pp2;
+
+          num_base_points = gloader->base.outline.n_points;
+
+          error = af_loader_load_g( loader, scaler, subglyph->index,
+                                    load_flags, depth + 1 );
+          if ( error )
+            goto Exit;
+
+          /* recompute subglyph pointer */
+          subglyph = gloader->base.subglyphs + num_base_subgs + nn;
+
+          if ( subglyph->flags & FT_SUBGLYPH_FLAG_USE_MY_METRICS )
+          {
+            pp1 = loader->pp1;
+            pp2 = loader->pp2;
+          }
+          else
+          {
+            loader->pp1 = pp1;
+            loader->pp2 = pp2;
+          }
+
+          num_points     = gloader->base.outline.n_points;
+          num_new_points = num_points - num_base_points;
+
+          /* now perform the transform required for this subglyph */
+
+          if ( subglyph->flags & ( FT_SUBGLYPH_FLAG_SCALE    |
+                                   FT_SUBGLYPH_FLAG_XY_SCALE |
+                                   FT_SUBGLYPH_FLAG_2X2      ) )
+          {
+            FT_Vector*  cur   = gloader->base.outline.points +
+                                num_base_points;
+            FT_Vector*  org   = gloader->base.extra_points +
+                                num_base_points;
+            FT_Vector*  limit = cur + num_new_points;
+
+
+            for ( ; cur < limit; cur++, org++ )
+            {
+              FT_Vector_Transform( cur, &subglyph->transform );
+              FT_Vector_Transform( org, &subglyph->transform );
+            }
+          }
+
+          /* apply offset */
+
+          if ( !( subglyph->flags & FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES ) )
+          {
+            FT_Int      k = subglyph->arg1;
+            FT_UInt     l = subglyph->arg2;
+            FT_Vector*  p1;
+            FT_Vector*  p2;
+
+
+            if ( start_point + k >= num_base_points         ||
+                               l >= (FT_UInt)num_new_points )
+            {
+              error = FT_Err_Invalid_Composite;
+              goto Exit;
+            }
+
+            l += num_base_points;
+
+            /* for now, only use the current point coordinates;    */
+            /* we may consider another approach in the near future */
+            p1 = gloader->base.outline.points + start_point + k;
+            p2 = gloader->base.outline.points + start_point + l;
+
+            x = p1->x - p2->x;
+            y = p1->y - p2->y;
+          }
+          else
+          {
+            x = FT_MulFix( subglyph->arg1, hints->x_scale ) + hints->x_delta;
+            y = FT_MulFix( subglyph->arg2, hints->y_scale ) + hints->y_delta;
+
+            x = FT_PIX_ROUND(x);
+            y = FT_PIX_ROUND(y);
+          }
+
+          {
+            FT_Outline  dummy = gloader->base.outline;
+
+
+            dummy.points  += num_base_points;
+            dummy.n_points = (short)num_new_points;
+
+            FT_Outline_Translate( &dummy, x, y );
+          }
+        }
+      }
+      break;
+
+    default:
+      /* we don't support other formats (yet?) */
+      error = FT_Err_Unimplemented_Feature;
+    }
+
+  Hint_Metrics:
+    if ( depth == 0 )
+    {
+      FT_BBox  bbox;
+
+
+      /* transform the hinted outline if needed */
+      if ( loader->transformed )
+        FT_Outline_Transform( &gloader->base.outline, &loader->trans_matrix );
+
+      /* we must translate our final outline by -pp1.x and compute */
+      /* the new metrics                                           */
+      if ( loader->pp1.x )
+        FT_Outline_Translate( &gloader->base.outline, -loader->pp1.x, 0 );
+
+      FT_Outline_Get_CBox( &gloader->base.outline, &bbox );
+
+      bbox.xMin  = FT_PIX_FLOOR(  bbox.xMin );
+      bbox.yMin  = FT_PIX_FLOOR(  bbox.yMin );
+      bbox.xMax  = FT_PIX_CEIL( bbox.xMax );
+      bbox.yMax  = FT_PIX_CEIL( bbox.yMax );
+
+      slot->metrics.width        = bbox.xMax - bbox.xMin;
+      slot->metrics.height       = bbox.yMax - bbox.yMin;
+      slot->metrics.horiBearingX = bbox.xMin;
+      slot->metrics.horiBearingY = bbox.yMax;
+
+      /* for mono-width fonts (like Andale, Courier, etc.) we need */
+      /* to keep the original rounded advance width                */
+#if 0
+      if ( !FT_IS_FIXED_WIDTH( slot->face ) )
+        slot->metrics.horiAdvance = loader->pp2.x - loader->pp1.x;
+      else
+        slot->metrics.horiAdvance = FT_MulFix( slot->metrics.horiAdvance,
+                                               x_scale );
+#else
+      slot->metrics.horiAdvance = loader->pp2.x - loader->pp1.x;
+#endif
+
+      slot->metrics.horiAdvance = FT_PIX_ROUND( slot->metrics.horiAdvance );
+
+      /* now copy outline into glyph slot */
+      FT_GlyphLoader_Rewind( loader->gloader );
+      error = FT_GlyphLoader_CopyPoints( loader->gloader, gloader );
+      if ( error )
+        goto Exit;
+
+      slot->outline = slot->internal->loader->base.outline;
+      slot->format  = FT_GLYPH_FORMAT_OUTLINE;
+    }
+
+#ifdef DEBUG_HINTER
+    af_debug_hinter = hinter;
+#endif
+
+  Exit:
+    return error;
+  }
+
+
+
+
+  FT_LOCAL_DEF( FT_Error )
+  af_loader_load_glyph( AF_Loader  loader,
+                        FT_Face    face,
+                        FT_UInt    gindex,
+                        FT_UInt32  load_flags )
+  {
+    FT_Error      error;
+    FT_Size       size = face->size;
+    AF_ScalerRec  scaler;
+
+    if ( !size )
+      return FT_Err_Invalid_Argument;
+
+    FT_ZERO( &scaler );
+
+    scaler.face    = face;
+    scaler.x_scale = size->metrics.x_scale;
+    scaler.x_delta = 0;  /* XXX: TODO: add support for sub-pixel hinting */
+    scaler.y_scale = size->metrics.y_scale;
+    scaler.y_delta = 0;  /* XXX: TODO: add support for sub-pixel hinting */
+
+    scaler.render_mode = FT_LOAD_TARGET_MODE( load_flags );
+    scaler.flags       = 0;  /* XXX: fix this */
+
+    error = af_loader_reset( loader, face );
+    if ( !error )
+    {
+      AF_ScriptMetrics  metrics;
+
+      error = af_face_globals_get_metrics( loader->globals, gindex, &metrics );
+      if ( !error )
+      {
+        metrics->clazz->script_metrics_scale( metrics, &scaler );
+
+        load_flags |=  FT_LOAD_NO_SCALE | FT_LOAD_IGNORE_TRANSFORM;
+        load_flags &= ~FT_LOAD_RENDER;
+
+        error = af_loader_load_g( loader, &scaler, gindex, load_flags, 0 );
+      }
+    }
+    return error;
+  }
--- a/src/autofit/afloader.h
+++ b/src/autofit/afloader.h
@@ -21,22 +21,26 @@
 
   } AF_LoaderRec, *AF_Loader;
 
-  FT_LOCAL( void )
+
+  FT_LOCAL( FT_Error )
   af_loader_init( AF_Loader  loader,
                   FT_Memory  memory );
 
+
   FT_LOCAL( FT_Error )
-  af_loader_reset( AF_Loader   loader,
-                   FT_Face     face );
+  af_loader_reset( AF_Loader  loader,
+                   FT_Face    face );
 
+
   FT_LOCAL( void )
-  af_loader_done( AF_Loader   loader );
+  af_loader_done( AF_Loader  loader );
 
+
   FT_LOCAL( FT_Error )
-  af_loader_load_glyph( AF_Loader   loader,
-                        FT_UInt     gindex,
-                        FT_UInt32   load_flags,
-                        FT_UInt     depth );
+  af_loader_load_glyph( AF_Loader  loader,
+                        FT_Face    face,
+                        FT_UInt    gindex,
+                        FT_UInt32  load_flags );
 
 /* */
 
--- a/src/autofit/afmodule.c
+++ b/src/autofit/afmodule.c
@@ -1,437 +1,68 @@
 #include "afmodule.h"
-#include "afhints.h"
-#include "afglobal.h"
-#include "aflatin.h"
+#include "afloader.h"
+#include FT_INTERNAL_OBJECTS_H
 
-  static FT_Error
-  af_hinter_load( AF_Hinter  hinter,
-                  FT_UInt    glyph_index,
-                  FT_Int32   load_flags,
-                  FT_UInt    depth )
+  typedef struct  FT_AutofitterRec_
   {
-    FT_Face           face     = hinter->face;
-    FT_GlyphSlot      slot     = face->glyph;
-    FT_Slot_Internal  internal = slot->internal;
-    FT_Fixed          x_scale  = hinter->globals->x_scale;
-    FT_Fixed          y_scale  = hinter->globals->y_scale;
-    FT_Error          error;
-    AF_Outline        outline  = hinter->glyph;
-    AF_Loader         gloader  = hinter->loader;
+    FT_ModuleRec  root;
+    AF_LoaderRec  loader[1];
 
+  } FT_AutofitterRec, *FT_Autofitter;
 
-    /* load the glyph */
-    error = FT_Load_Glyph( face, glyph_index, load_flags );
-    if ( error )
-      goto Exit;
 
-    /* Set `hinter->transformed' after loading with FT_LOAD_NO_RECURSE. */
-    hinter->transformed = internal->glyph_transformed;
+  FT_CALLBACK_DEF( FT_Error )
+  af_autofitter_init( FT_Autofitter  module )
+  {
+    return af_loader_init( module->loader, module->root.library->memory );
+  }
 
-    if ( hinter->transformed )
-    {
-      FT_Matrix  imatrix;
 
-
-      imatrix              = internal->glyph_matrix;
-      hinter->trans_delta  = internal->glyph_delta;
-      hinter->trans_matrix = imatrix;
-
-      FT_Matrix_Invert( &imatrix );
-      FT_Vector_Transform( &hinter->trans_delta, &imatrix );
-    }
-
-    /* set linear horizontal metrics */
-    slot->linearHoriAdvance = slot->metrics.horiAdvance;
-    slot->linearVertAdvance = slot->metrics.vertAdvance;
-
-    switch ( slot->format )
-    {
-    case FT_GLYPH_FORMAT_OUTLINE:
-
-      /* translate glyph outline if we need to */
-      if ( hinter->transformed )
-      {
-        FT_UInt     n     = slot->outline.n_points;
-        FT_Vector*  point = slot->outline.points;
-
-
-        for ( ; n > 0; point++, n-- )
-        {
-          point->x += hinter->trans_delta.x;
-          point->y += hinter->trans_delta.y;
-        }
-      }
-
-      /* copy the outline points in the loader's current               */
-      /* extra points which is used to keep original glyph coordinates */
-      error = af_loader_check_points( gloader, slot->outline.n_points + 2,
-                                      slot->outline.n_contours );
-      if ( error )
-        goto Exit;
-
-      FT_ARRAY_COPY( gloader->current.extra_points, slot->outline.points,
-                     slot->outline.n_points );
-
-      FT_ARRAY_COPY( gloader->current.outline.contours, slot->outline.contours,
-                     slot->outline.n_contours );
-
-      FT_ARRAY_COPY( gloader->current.outline.tags, slot->outline.tags,
-                     slot->outline.n_points );
-
-      gloader->current.outline.n_points   = slot->outline.n_points;
-      gloader->current.outline.n_contours = slot->outline.n_contours;
-
-      /* compute original phantom points */
-      hinter->pp1.x = 0;
-      hinter->pp1.y = 0;
-      hinter->pp2.x = FT_MulFix( slot->metrics.horiAdvance, x_scale );
-      hinter->pp2.y = 0;
-
-      /* be sure to check for spacing glyphs */
-      if ( slot->outline.n_points == 0 )
-        goto Hint_Metrics;
-
-      /* now load the slot image into the auto-outline and run the */
-      /* automatic hinting process                                 */
-      error = af_outline_load( outline, x_scale, y_scale, face );
-      if ( error )
-        goto Exit;
-
-      /* perform feature detection */
-      af_outline_detect_features( outline );
-
-      if ( hinter->do_vert_hints )
-      {
-        af_outline_compute_blue_edges( outline, hinter->globals );
-        af_outline_scale_blue_edges( outline, hinter->globals );
-      }
-
-      /* perform alignment control */
-      af_hinter_hint_edges( hinter );
-      af_hinter_align( hinter );
-
-      /* now save the current outline into the loader's current table */
-      af_outline_save( outline, gloader );
-
-      /* we now need to hint the metrics according to the change in */
-      /* width/positioning that occured during the hinting process  */
-      {
-        FT_Pos   old_advance, old_rsb, old_lsb, new_lsb;
-        AF_Edge  edge1 = outline->vert_edges;     /* leftmost edge  */
-        AF_Edge  edge2 = edge1 +
-                         outline->num_vedges - 1; /* rightmost edge */
-
-
-        old_advance = hinter->pp2.x;
-        old_rsb     = old_advance - edge2->opos;
-        old_lsb     = edge1->opos;
-        new_lsb     = edge1->pos;
-
-        hinter->pp1.x = FT_PIX_ROUND( new_lsb    - old_lsb );
-        hinter->pp2.x = FT_PIX_ROUND( edge2->pos + old_rsb );
-
-#if 0
-        /* try to fix certain bad advance computations */
-        if ( hinter->pp2.x + hinter->pp1.x == edge2->pos && old_rsb > 4 )
-          hinter->pp2.x += 64;
-#endif
-      }
-
-      /* good, we simply add the glyph to our loader's base */
-      af_loader_add( gloader );
-      break;
-
-    case FT_GLYPH_FORMAT_COMPOSITE:
-      {
-        FT_UInt      nn, num_subglyphs = slot->num_subglyphs;
-        FT_UInt      num_base_subgs, start_point;
-        FT_SubGlyph  subglyph;
-
-
-        start_point = gloader->base.outline.n_points;
-
-        /* first of all, copy the subglyph descriptors in the glyph loader */
-        error = af_loader_check_subglyphs( gloader, num_subglyphs );
-        if ( error )
-          goto Exit;
-
-        FT_ARRAY_COPY( gloader->current.subglyphs, slot->subglyphs,
-                       num_subglyphs );
-
-        gloader->current.num_subglyphs = num_subglyphs;
-        num_base_subgs = gloader->base.num_subglyphs;
-
-        /* now, read each subglyph independently */
-        for ( nn = 0; nn < num_subglyphs; nn++ )
-        {
-          FT_Vector  pp1, pp2;
-          FT_Pos     x, y;
-          FT_UInt    num_points, num_new_points, num_base_points;
-
-
-          /* gloader.current.subglyphs can change during glyph loading due */
-          /* to re-allocation -- we must recompute the current subglyph on */
-          /* each iteration                                                */
-          subglyph = gloader->base.subglyphs + num_base_subgs + nn;
-
-          pp1 = hinter->pp1;
-          pp2 = hinter->pp2;
-
-          num_base_points = gloader->base.outline.n_points;
-
-          error = af_hinter_load( hinter, subglyph->index,
-                                  load_flags, depth + 1 );
-          if ( error )
-            goto Exit;
-
-          /* recompute subglyph pointer */
-          subglyph = gloader->base.subglyphs + num_base_subgs + nn;
-
-          if ( subglyph->flags & FT_SUBGLYPH_FLAG_USE_MY_METRICS )
-          {
-            pp1 = hinter->pp1;
-            pp2 = hinter->pp2;
-          }
-          else
-          {
-            hinter->pp1 = pp1;
-            hinter->pp2 = pp2;
-          }
-
-          num_points     = gloader->base.outline.n_points;
-          num_new_points = num_points - num_base_points;
-
-          /* now perform the transform required for this subglyph */
-
-          if ( subglyph->flags & ( FT_SUBGLYPH_FLAG_SCALE    |
-                                   FT_SUBGLYPH_FLAG_XY_SCALE |
-                                   FT_SUBGLYPH_FLAG_2X2      ) )
-          {
-            FT_Vector*  cur   = gloader->base.outline.points +
-                                num_base_points;
-            FT_Vector*  org   = gloader->base.extra_points +
-                                num_base_points;
-            FT_Vector*  limit = cur + num_new_points;
-
-
-            for ( ; cur < limit; cur++, org++ )
-            {
-              FT_Vector_Transform( cur, &subglyph->transform );
-              FT_Vector_Transform( org, &subglyph->transform );
-            }
-          }
-
-          /* apply offset */
-
-          if ( !( subglyph->flags & FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES ) )
-          {
-            FT_Int      k = subglyph->arg1;
-            FT_UInt     l = subglyph->arg2;
-            FT_Vector*  p1;
-            FT_Vector*  p2;
-
-
-            if ( start_point + k >= num_base_points         ||
-                               l >= (FT_UInt)num_new_points )
-            {
-              error = AF_Err_Invalid_Composite;
-              goto Exit;
-            }
-
-            l += num_base_points;
-
-            /* for now, only use the current point coordinates;    */
-            /* we may consider another approach in the near future */
-            p1 = gloader->base.outline.points + start_point + k;
-            p2 = gloader->base.outline.points + start_point + l;
-
-            x = p1->x - p2->x;
-            y = p1->y - p2->y;
-          }
-          else
-          {
-            x = FT_MulFix( subglyph->arg1, x_scale );
-            y = FT_MulFix( subglyph->arg2, y_scale );
-
-            x = FT_PIX_ROUND(x);
-            y = FT_PIX_ROUND(y);
-          }
-
-          {
-            FT_Outline  dummy = gloader->base.outline;
-
-
-            dummy.points  += num_base_points;
-            dummy.n_points = (short)num_new_points;
-
-            FT_Outline_Translate( &dummy, x, y );
-          }
-        }
-      }
-      break;
-
-    default:
-      /* we don't support other formats (yet?) */
-      error = AF_Err_Unimplemented_Feature;
-    }
-
-  Hint_Metrics:
-    if ( depth == 0 )
-    {
-      FT_BBox  bbox;
-
-
-      /* transform the hinted outline if needed */
-      if ( hinter->transformed )
-        FT_Outline_Transform( &gloader->base.outline, &hinter->trans_matrix );
-
-      /* we must translate our final outline by -pp1.x and compute */
-      /* the new metrics                                           */
-      if ( hinter->pp1.x )
-        FT_Outline_Translate( &gloader->base.outline, -hinter->pp1.x, 0 );
-
-      FT_Outline_Get_CBox( &gloader->base.outline, &bbox );
-      bbox.xMin  = FT_PIX_FLOOR(  bbox.xMin );
-      bbox.yMin  = FT_PIX_FLOOR(  bbox.yMin );
-      bbox.xMax  = FT_PIX_CEIL( bbox.xMax );
-      bbox.yMax  = FT_PIX_CEIL( bbox.yMax );
-
-      slot->metrics.width        = bbox.xMax - bbox.xMin;
-      slot->metrics.height       = bbox.yMax - bbox.yMin;
-      slot->metrics.horiBearingX = bbox.xMin;
-      slot->metrics.horiBearingY = bbox.yMax;
-
-      /* for mono-width fonts (like Andale, Courier, etc.) we need */
-      /* to keep the original rounded advance width                */
-      if ( !FT_IS_FIXED_WIDTH( slot->face ) )
-        slot->metrics.horiAdvance = hinter->pp2.x - hinter->pp1.x;
-      else
-        slot->metrics.horiAdvance = FT_MulFix( slot->metrics.horiAdvance,
-                                               x_scale );
-
-      slot->metrics.horiAdvance = FT_PIX_ROUND( slot->metrics.horiAdvance );
-
-      /* now copy outline into glyph slot */
-      af_loader_rewind( slot->internal->loader );
-      error = af_loader_copy_points( slot->internal->loader, gloader );
-      if ( error )
-        goto Exit;
-
-      slot->outline = slot->internal->loader->base.outline;
-      slot->format  = FT_GLYPH_FORMAT_OUTLINE;
-    }
-
-#ifdef DEBUG_HINTER
-    af_debug_hinter = hinter;
-#endif
-
-  Exit:
-    return error;
+  FT_CALLBACK_DEF( void )
+  af_autofitter_done( FT_Autofitter  module )
+  {
+    af_loader_done( module->loader );
   }
 
 
-  /* load and hint a given glyph */
-  FT_LOCAL_DEF( FT_Error )
-  af_hinter_load_glyph( AF_Hinter     hinter,
-                        FT_GlyphSlot  slot,
-                        FT_Size       size,
-                        FT_UInt       glyph_index,
-                        FT_Int32      load_flags )
+  FT_CALLBACK_DEF( FT_Error )
+  af_autofitter_load_glyph( FT_Autofitter  module,
+                            FT_GlyphSlot   slot,
+                            FT_Size        size,
+                            FT_UInt        glyph_index,
+                            FT_Int32       load_flags )
   {
-    FT_Face          face         = slot->face;
-    FT_Error         error;
-    FT_Fixed         x_scale      = size->metrics.x_scale;
-    FT_Fixed         y_scale      = size->metrics.y_scale;
-    AF_Face_Globals  face_globals = FACE_GLOBALS( face );
-    FT_Render_Mode   hint_mode    = FT_LOAD_TARGET_MODE( load_flags );
+    return af_loader_load_glyph( module->loader, slot->face,
+                                 glyph_index, load_flags );
+  }
 
 
-    /* first of all, we need to check that we're using the correct face and */
-    /* global hints to load the glyph                                       */
-    if ( hinter->face != face || hinter->globals != face_globals )
-    {
-      hinter->face = face;
-      if ( !face_globals )
-      {
-        error = af_hinter_new_face_globals( hinter, face, 0 );
-        if ( error )
-          goto Exit;
 
-      }
-      hinter->globals = FACE_GLOBALS( face );
-      face_globals    = FACE_GLOBALS( face );
+  FT_CALLBACK_TABLE_DEF
+  const FT_AutoHinter_ServiceRec  af_autofitter_service =
+  {
+    NULL,
+    NULL,
+    NULL,
+    (FT_AutoHinter_GlyphLoadFunc) af_autofitter_load_glyph
+  };
 
-    }
 
-#ifdef FT_CONFIG_CHESTER_BLUE_SCALE
+  FT_CALLBACK_TABLE_DEF
+  const FT_Module_Class  autofit_module_class =
+  {
+    FT_MODULE_HINTER,
+    sizeof ( FT_AutofitterRec ),
 
-   /* try to optimize the y_scale so that the top of non-capital letters
-    * is aligned on a pixel boundary whenever possible
-    */
-    {
-      AF_Globals  design = &face_globals->design;
-      FT_Pos      shoot  = design->blue_shoots[AF_BLUE_SMALL_TOP];
+    "autofitter",
+    0x10000L,   /* version 1.0 of the autofitter  */
+    0x20000L,   /* requires FreeType 2.0 or above */
 
+    (const void*) &af_autofitter_service,
 
-      /* the value of 'shoot' will be -1000 if the font doesn't have */
-      /* small latin letters; we simply check the sign here...       */
-      if ( shoot > 0 )
-      {
-        FT_Pos  scaled = FT_MulFix( shoot, y_scale );
-        FT_Pos  fitted = FT_PIX_ROUND( scaled );
+    (FT_Module_Constructor) af_autofitter_init,
+    (FT_Module_Destructor)  af_autofitter_done,
+    (FT_Module_Requester)   0
+  };
 
 
-        if ( scaled != fitted )
-        {
-         /* adjust y_scale
-          */
-          y_scale = FT_MulDiv( y_scale, fitted, scaled );
-
-         /* adust x_scale
-          */
-          if ( fitted < scaled )
-            x_scale -= x_scale / 50;  /* x_scale*0.98 with integers */
-        }
-      }
-    }
-
-#endif /* FT_CONFIG_CHESTER_BLUE_SCALE */
-
-    /* now, we must check the current character pixel size to see if we */
-    /* need to rescale the global metrics                               */
-    if ( face_globals->x_scale != x_scale ||
-         face_globals->y_scale != y_scale )
-      af_hinter_scale_globals( hinter, x_scale, y_scale );
-
-    af_loader_rewind( hinter->loader );
-
-    /* reset hinting flags according to load flags and current render target */
-    hinter->do_horz_hints = FT_BOOL( !(load_flags & FT_LOAD_NO_AUTOHINT) );
-    hinter->do_vert_hints = FT_BOOL( !(load_flags & FT_LOAD_NO_AUTOHINT) );
-
-#ifdef DEBUG_HINTER
-    hinter->do_horz_hints = !af_debug_disable_vert;  /* not a bug, the meaning */
-    hinter->do_vert_hints = !af_debug_disable_horz;  /* of h/v is inverted!    */
-#endif
-
-    /* we snap the width of vertical stems for the monochrome and         */
-    /* horizontal LCD rendering targets only.  Corresponds to X snapping. */
-    hinter->do_horz_snapping = FT_BOOL( hint_mode == FT_RENDER_MODE_MONO ||
-                                        hint_mode == FT_RENDER_MODE_LCD  );
-
-    /* we snap the width of horizontal stems for the monochrome and     */
-    /* vertical LCD rendering targets only.  Corresponds to Y snapping. */
-    hinter->do_vert_snapping = FT_BOOL( hint_mode == FT_RENDER_MODE_MONO   ||
-                                        hint_mode == FT_RENDER_MODE_LCD_V  );
-
-    hinter->do_stem_adjust   = FT_BOOL( hint_mode != FT_RENDER_MODE_LIGHT );
-
-    load_flags |= FT_LOAD_NO_SCALE
-                | FT_LOAD_IGNORE_TRANSFORM;
-    load_flags &= ~FT_LOAD_RENDER;
-
-    error = af_hinter_load( hinter, glyph_index, load_flags, 0 );
-
-  Exit:
-    return error;
-  }
+/* END */
--- a/src/autofit/afmodule.h
+++ b/src/autofit/afmodule.h
@@ -1,5 +1,17 @@
 #ifndef __AFMODULE_H__
 #define __AFMODULE_H__
 
+#include <ft2build.h>
+#include FT_MODULE_H
+
+
+FT_BEGIN_HEADER
+
+  FT_CALLBACK_TABLE
+  const FT_Module_Class  autofit_module_class;
+
+
+FT_END_HEADER
+
 #endif /* __AFMODULE_H__ */
 
--- a/src/autofit/aftypes.h
+++ b/src/autofit/aftypes.h
@@ -226,12 +226,10 @@
 
 
   typedef FT_Error  (*AF_Script_InitHintsFunc)( AF_GlyphHints     hints,
-                                                AF_Scaler         scaler,
                                                 FT_Outline*       outline,
                                                 AF_ScriptMetrics  metrics );
 
   typedef void      (*AF_Script_ApplyHintsFunc)( AF_GlyphHints     hints,
-                                                 AF_Scaler         scaler,
                                                  FT_Outline*       outline,
                                                  AF_ScriptMetrics  metrics );
 
--- a/src/autofit/autofit.c
+++ b/src/autofit/autofit.c
@@ -1,7 +1,10 @@
-#define FT_MAKE_OPTION_SINGLE_OBJECT
-
-#include <ft2build.h>
+#define FT_MAKE_OPTION_SINGLE_OBJECT
+#include <ft2build.h>
 #include "afangles.c"
 #include "afglobal.c"
 #include "afhints.c"
 #include "aflatin.c"
+#include "afloader.c"
+#include "afmodule.c"
+
+
--- a/src/autohint/ahmodule.c
+++ b/src/autohint/ahmodule.c
@@ -117,7 +117,7 @@
 
 
   FT_CALLBACK_TABLE_DEF
-  const FT_Module_Class  autohint_module_class =
+  const FT_Module_Class  autofit_module_class =
   {
     FT_MODULE_HINTER,
     sizeof ( FT_AutoHinterRec ),
--- a/src/cache/Jamfile
+++ b/src/cache/Jamfile
@@ -14,14 +14,14 @@
 
   if $(FT2_MULTI)
   {
-    _sources = ftmru 
-               ftcmanag 
-               ftccache 
-               ftcglyph 
-               ftcsbits 
+    _sources = ftcmru
+               ftcmanag
+               ftccache
+               ftcglyph
+               ftcsbits
                ftcimage
-               ftcbasic 
-               ftccmap 
+               ftcbasic
+               ftccmap
                ;
   }
   else
--- a/src/cache/descrip.mms
+++ b/src/cache/descrip.mms
@@ -20,7 +20,6 @@
 all : $(OBJS)
         library [--.lib]freetype.olb $(OBJS)
 
-ftcache.obj : ftcache.c ftcmru.c ftcmanag.c ftccache.c ftcglyph.c ftcimage.c \
-              ftcsbits.c ftccmap.c  ftcbasic.c
+ftcache.obj : ftcache.c
 
 # EOF
--- a/src/cache/ftcbasic.c
+++ b/src/cache/ftcbasic.c
@@ -269,9 +269,12 @@
     query.attrs.scaler.pixel   = 1;
     query.attrs.load_flags     = type->flags;
 
+    query.attrs.scaler.x_res   = 0;  /* make compilers happy */
+    query.attrs.scaler.y_res   = 0;
+
     hash = FTC_BASIC_ATTR_HASH( &query.attrs ) + gindex;
-    
-#if 1  /* inlining is about 50% faster! */ 
+
+#if 1  /* inlining is about 50% faster! */
     FTC_GCACHE_LOOKUP_CMP( cache,
                            ftc_basic_family_compare,
                            FTC_GNode_Compare,
@@ -376,11 +379,14 @@
     query.attrs.scaler.pixel   = 1;
     query.attrs.load_flags     = type->flags;
 
+    query.attrs.scaler.x_res   = 0;  /* make compilers happy */
+    query.attrs.scaler.y_res   = 0;
+
     /* beware, the hash must be the same for all glyph ranges! */
     hash = FTC_BASIC_ATTR_HASH( &query.attrs ) +
            gindex / FTC_SBIT_ITEMS_PER_NODE;
 
-#if 1  /* inlining is about 50% faster! */ 
+#if 1  /* inlining is about 50% faster! */
     FTC_GCACHE_LOOKUP_CMP( cache,
                            ftc_basic_family_compare,
                            FTC_SNode_Compare,
@@ -394,7 +400,7 @@
                                gindex,
                                FTC_GQUERY( &query ),
                                (FTC_Node*)&node );
-#endif                               
+#endif
     if ( error )
       goto Exit;
 
--- a/src/cache/ftccmap.c
+++ b/src/cache/ftccmap.c
@@ -240,7 +240,7 @@
                           node, error );
 #else
     error = FTC_Cache_Lookup( cache, hash, &query, (FTC_Node*) &node );
-#endif    
+#endif
     if ( error )
       goto Exit;
 
--- a/src/cache/ftcmanag.c
+++ b/src/cache/ftcmanag.c
@@ -165,22 +165,15 @@
     if ( !manager )
       return FTC_Err_Invalid_Cache_Handle;
 
-    /* we break encapsulation for the sake of speed */
+#ifdef FTC_INLINE
 
-    error = 0;
-    FTC_MRULIST_LOOP( &manager->sizes, node )
-    {
-      FTC_Scaler  scaler0 = &node->scaler;
+    FTC_MRULIST_LOOKUP_CMP( &manager->sizes, scaler, ftc_size_node_compare,
+                            node, error );
 
+#else
+    error = FTC_MruList_Lookup( &manager->sizes, scaler, (FTC_MruNode*)&node );
+#endif
 
-      if ( FTC_SCALER_COMPARE( scaler0, scaler ) )
-        goto Found;
-    }
-    FTC_MRULIST_LOOP_END();
-
-    error = FTC_MruList_New( &manager->sizes, scaler, (FTC_MruNode*)&node );
-
-  Found:
     if ( !error )
       *asize = node->size;
 
@@ -287,18 +280,15 @@
       return FTC_Err_Invalid_Cache_Handle;
 
     /* we break encapsulation for the sake of speed */
+#ifdef FTC_INLINE
 
-    error = 0;
-    FTC_MRULIST_LOOP( &manager->faces, node )
-    {
-      if ( node->face_id == face_id )
-        goto Found;
-    }
-    FTC_MRULIST_LOOP_END();
+    FTC_MRULIST_LOOKUP_CMP( &manager->faces, face_id, ftc_face_node_compare,
+                            node, error );
 
-    error = FTC_MruList_New( &manager->faces, face_id, (FTC_MruNode*)&node );
+#else
+    error = FTC_MruList_Lookup( &manager->faces, face_id, (FTC_MruNode*)&node );
+#endif
 
-  Found:
     if ( !error )
       *aface = node->face;
 
--- a/src/cache/ftcmru.c
+++ b/src/cache/ftcmru.c
@@ -215,10 +215,15 @@
       do
       {
         if ( compare( node, key ) )
+        {
+          if ( node != first )
+            FTC_MruNode_Up( &list->nodes, node );
+
           return node;
+        }
 
         node = node->next;
-  
+
       } while ( node != first);
     }
 
--- a/src/sfnt/Jamfile
+++ b/src/sfnt/Jamfile
@@ -8,7 +8,7 @@
 
   if $(FT2_MULTI)
   {
-    _sources = sfobjs sfdriver ttcmap ttcmap0 ttpost ttload ttsbit ;
+    _sources = sfobjs sfdriver ttcmap0 ttpost ttload ttsbit ;
   }
   else
   {