Update freetype to latest version of ASOP.

This added support of color glyphs.

BUG=290583

Review URL: https://codereview.chromium.org/89753003/
diff --git a/Android.mk b/Android.mk
index 51ae31b..e357397 100644
--- a/Android.mk
+++ b/Android.mk
@@ -37,13 +37,17 @@
 
 LOCAL_C_INCLUDES += \
 	$(LOCAL_PATH)/builds \
-	$(LOCAL_PATH)/include
+	$(LOCAL_PATH)/include \
+	external/libpng \
+	external/zlib
 
 LOCAL_CFLAGS += -W -Wall
 LOCAL_CFLAGS += -fPIC -DPIC
 LOCAL_CFLAGS += "-DDARWIN_NO_CARBON"
 LOCAL_CFLAGS += "-DFT2_BUILD_LIBRARY"
 
+LOCAL_SHARED_LIBRARIES += libpng libz
+
 # the following is for testing only, and should not be used in final builds
 # of the product
 #LOCAL_CFLAGS += "-DTT_CONFIG_OPTION_BYTECODE_INTERPRETER"
@@ -52,5 +56,5 @@
 
 LOCAL_MODULE:= libft2
 
-include $(BUILD_STATIC_LIBRARY)
+include $(BUILD_SHARED_LIBRARY)
 endif
diff --git a/README.chromium b/README.chromium
index b09ca54..7aef628 100644
--- a/README.chromium
+++ b/README.chromium
@@ -1,6 +1,6 @@
 Name: Freetype
 URL: https://android.googlesource.com/platform/external/freetype/
-Version: 8afe960626dbf326354b836fd4d63e05b6974195
+Version: 899c67b6cfcd2010784fbf08c5415af16c526e0c
 License: Custom license "inspired by the BSD, Artistic, and IJG (Independent
          JPEG Group) licenses"
 License File: NOTICE
@@ -22,7 +22,9 @@
 $ git clone https://android.googlesource.com/platform/external/freetype/
 # Use the following command to checkout this version, or omit it to checkout
 # the latest version.
-$ git reset --hard 8afe960626dbf326354b836fd4d63e05b6974195
+$ git reset --hard <version-listed-above>
 
-2. Copy the related files from
+2. Copy all files from
    <android_tree>/external/freetype/
+
+3. Update freetype.gyp to reflect any changes made in Android.mk.
diff --git a/freetype.gyp b/freetype.gyp
index 23463c7..22e22a9 100644
--- a/freetype.gyp
+++ b/freetype.gyp
@@ -11,18 +11,20 @@
           'type': 'static_library',
           'toolsets': ['target'],
           'sources': [
+            # The following files are not sorted alphabetically, but in the
+            # same order as in Android.mk to ease maintenance.
             'src/base/ftbbox.c',
             'src/base/ftbitmap.c',
             'src/base/ftfstype.c',
             'src/base/ftglyph.c',
             'src/base/ftlcdfil.c',
             'src/base/ftstroke.c',
+            'src/base/fttype1.c',
             'src/base/ftxf86.c',
             'src/base/ftbase.c',
             'src/base/ftsystem.c',
             'src/base/ftinit.c',
             'src/base/ftgasp.c',
-            'src/base/fttype1.c',
             'src/raster/raster.c',
             'src/sfnt/sfnt.c',
             'src/smooth/smooth.c',
@@ -32,6 +34,10 @@
             'src/psnames/psnames.c',
             'src/pshinter/pshinter.c',
           ],
+          'dependencies': [
+            '../libpng/libpng.gyp:libpng',
+            '../zlib/zlib.gyp:zlib',
+          ],
           'include_dirs': [
             'build',
             'include',
diff --git a/include/freetype/config/ftconfig.h b/include/freetype/config/ftconfig.h
index 5628569..5dce30e 100644
--- a/include/freetype/config/ftconfig.h
+++ b/include/freetype/config/ftconfig.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    ANSI-specific configuration file (specification only).               */
 /*                                                                         */
-/*  Copyright 1996-2004, 2006-2008, 2010-2011 by                           */
+/*  Copyright 1996-2004, 2006-2008, 2010-2011, 2013 by                     */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -200,6 +200,30 @@
   /*                                                                       */
   typedef unsigned XXX  FT_UInt32;
 
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_Int64                                                           */
+  /*                                                                       */
+  /*    A typedef for a 64bit signed integer type.  The size depends on    */
+  /*    the configuration.  Only defined if there is real 64bit support;   */
+  /*    otherwise, it gets emulated with a structure (if necessary).       */
+  /*                                                                       */
+  typedef signed XXX  FT_Int64;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Type>                                                                */
+  /*    FT_UInt64                                                          */
+  /*                                                                       */
+  /*    A typedef for a 64bit unsigned integer type.  The size depends on  */
+  /*    the configuration.  Only defined if there is real 64bit support;   */
+  /*    otherwise, it gets emulated with a structure (if necessary).       */
+  /*                                                                       */
+  typedef unsigned XXX  FT_UInt64;
+
   /* */
 
 #endif
@@ -239,13 +263,15 @@
 
   /* FT_LONG64 must be defined if a 64-bit type is available */
 #define FT_LONG64
-#define FT_INT64  long
+#define FT_INT64   long
+#define FT_UINT64  unsigned long
 
 #elif defined( _MSC_VER ) && _MSC_VER >= 900  /* Visual C++ (and Intel C++) */
 
   /* this compiler provides the __int64 type */
 #define FT_LONG64
-#define FT_INT64  __int64
+#define FT_INT64   __int64
+#define FT_UINT64  unsigned __int64
 
 #elif defined( __BORLANDC__ )  /* Borland C++ */
 
@@ -254,7 +280,8 @@
 
   /* this compiler provides the __int64 type */
 #define FT_LONG64
-#define FT_INT64  __int64
+#define FT_INT64   __int64
+#define FT_UINT64  unsigned __int64
 
 #elif defined( __WATCOMC__ )   /* Watcom C++ */
 
@@ -263,13 +290,15 @@
 #elif defined( __MWERKS__ )    /* Metrowerks CodeWarrior */
 
 #define FT_LONG64
-#define FT_INT64  long long int
+#define FT_INT64   long long int
+#define FT_UINT64  unsigned long long int
 
 #elif defined( __GNUC__ )
 
   /* GCC provides the `long long' type */
 #define FT_LONG64
-#define FT_INT64  long long int
+#define FT_INT64   long long int
+#define FT_UINT64  unsigned long long int
 
 #endif /* FT_SIZEOF_LONG == (64 / FT_CHAR_BIT) */
 
@@ -293,6 +322,11 @@
 
 #endif /* FT_LONG64 && !FT_CONFIG_OPTION_FORCE_INT64 */
 
+#ifdef FT_LONG64
+  typedef FT_INT64   FT_Int64;
+  typedef FT_UINT64  FT_UInt64;
+#endif
+
 
 #define FT_BEGIN_STMNT  do {
 #define FT_END_STMNT    } while ( 0 )
@@ -355,7 +389,8 @@
       "mov    %0, %1, lsr #16\n\t"      /* %0  = %1 >> 16 */
       "orr    %0, %0, %2, lsl #16\n\t"  /* %0 |= %2 << 16 */
       : "=r"(a), "=&r"(t2), "=&r"(t)
-      : "r"(a), "r"(b) );
+      : "r"(a), "r"(b)
+      : "cc" );
     return a;
   }
 
diff --git a/include/freetype/config/ftheader.h b/include/freetype/config/ftheader.h
index 2a7b8c4..8371a31 100644
--- a/include/freetype/config/ftheader.h
+++ b/include/freetype/config/ftheader.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Build macros of the FreeType 2 library.                              */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010 by */
+/*  Copyright 1996-2008, 2010, 2012, 2013 by                               */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -318,6 +318,45 @@
   /*************************************************************************
    *
    * @macro:
+   *   FT_AUTOHINTER_H
+   *
+   * @description:
+   *   A macro used in #include statements to name the file containing
+   *   structures and macros related to the auto-hinting module.
+   *
+   */
+#define FT_AUTOHINTER_H  <freetype/ftautoh.h>
+
+
+  /*************************************************************************
+   *
+   * @macro:
+   *   FT_CFF_DRIVER_H
+   *
+   * @description:
+   *   A macro used in #include statements to name the file containing
+   *   structures and macros related to the CFF driver module.
+   *
+   */
+#define FT_CFF_DRIVER_H  <freetype/ftcffdrv.h>
+
+
+  /*************************************************************************
+   *
+   * @macro:
+   *   FT_TRUETYPE_DRIVER_H
+   *
+   * @description:
+   *   A macro used in #include statements to name the file containing
+   *   structures and macros related to the TrueType driver module.
+   *
+   */
+#define FT_TRUETYPE_DRIVER_H  <freetype/ftttdrv.h>
+
+
+  /*************************************************************************
+   *
+   * @macro:
    *   FT_TYPE1_TABLES_H
    *
    * @description:
diff --git a/include/freetype/config/ftoption.h b/include/freetype/config/ftoption.h
index c41f089..bc239bf 100644
--- a/include/freetype/config/ftoption.h
+++ b/include/freetype/config/ftoption.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    User-selectable configuration macros (specification only).           */
 /*                                                                         */
-/*  Copyright 1996-2011 by                                                 */
+/*  Copyright 1996-2013 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -216,6 +216,20 @@
 
   /*************************************************************************/
   /*                                                                       */
+  /*  PNG bitmap support.                                                  */
+  /*                                                                       */
+  /*   FreeType now handles loading color bitmap glyphs in the PNG format. */
+  /*   This requires help from the external libpng library.  Uncompressed  */
+  /*   color bitmaps do not need any external libraries and will be        */
+  /*   supported regardless of this configuration.                         */
+  /*                                                                       */
+  /*   Define this macro if you want to enable this `feature'.             */
+  /*                                                                       */
+#define FT_CONFIG_OPTION_USE_PNG
+
+
+  /*************************************************************************/
+  /*                                                                       */
   /* DLL export compilation                                                */
   /*                                                                       */
   /*   When compiling FreeType as a DLL, some systems/compilers need a     */
@@ -560,6 +574,28 @@
 
   /*************************************************************************/
   /*                                                                       */
+  /* Define TT_CONFIG_OPTION_SUBPIXEL_HINTING if you want to compile       */
+  /* EXPERIMENTAL subpixel hinting support into the TrueType driver.  This */
+  /* replaces the native TrueType hinting mechanism when anything but      */
+  /* FT_RENDER_MODE_MONO is requested.                                     */
+  /*                                                                       */
+  /* Enabling this causes the TrueType driver to ignore instructions under */
+  /* certain conditions.  This is done in accordance with the guide here,  */
+  /* with some minor differences:                                          */
+  /*                                                                       */
+  /*  http://www.microsoft.com/typography/cleartype/truetypecleartype.aspx */
+  /*                                                                       */
+  /* By undefining this, you only compile the code necessary to hint       */
+  /* TrueType glyphs with native TT hinting.                               */
+  /*                                                                       */
+  /*   This option requires TT_CONFIG_OPTION_BYTECODE_INTERPRETER to be    */
+  /*   defined.                                                            */
+  /*                                                                       */
+/* #define TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
+
+  /*************************************************************************/
+  /*                                                                       */
   /* If you define TT_CONFIG_OPTION_UNPATENTED_HINTING, a special version  */
   /* of the TrueType bytecode interpreter is used that doesn't implement   */
   /* any of the patented opcodes and algorithms.  The patents related to   */
@@ -669,7 +705,7 @@
 
   /*************************************************************************/
   /*                                                                       */
-  /* T1_MAX_DICT_DEPTH is the maximal depth of nest dictionaries and       */
+  /* T1_MAX_DICT_DEPTH is the maximum depth of nest dictionaries and       */
   /* arrays in the Type 1 stream (see t1load.c).  A minimum of 4 is        */
   /* required.                                                             */
   /*                                                                       */
@@ -716,6 +752,25 @@
   /*************************************************************************/
   /*************************************************************************/
   /****                                                                 ****/
+  /****         C F F   D R I V E R    C O N F I G U R A T I O N        ****/
+  /****                                                                 ****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* CFF_CONFIG_OPTION_OLD_ENGINE controls whether the pre-Adobe CFF       */
+  /* engine gets compiled into FreeType.  If defined, it is possible to    */
+  /* switch between the two engines using the `hinting-engine' property of */
+  /* the cff driver module.                                                */
+  /*                                                                       */
+/* #define CFF_CONFIG_OPTION_OLD_ENGINE */
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /****                                                                 ****/
   /****    A U T O F I T   M O D U L E    C O N F I G U R A T I O N     ****/
   /****                                                                 ****/
   /*************************************************************************/
@@ -752,37 +807,10 @@
 
 
   /*
-   * Define this variable if you want to keep the layout of internal
-   * structures that was used prior to FreeType 2.2.  This also compiles in
-   * a few obsolete functions to avoid linking problems on typical Unix
-   * distributions.
-   *
-   * For embedded systems or building a new distribution from scratch, it
-   * is recommended to disable the macro since it reduces the library's code
-   * size and activates a few memory-saving optimizations as well.
+   *  This macro is obsolete.  Support has been removed in FreeType
+   *  version 2.5.
    */
-#define FT_CONFIG_OPTION_OLD_INTERNALS
-
-
-  /*
-   *  To detect legacy cache-lookup call from a rogue client (<= 2.1.7),
-   *  we restrict the number of charmaps in a font.  The current API of
-   *  FTC_CMapCache_Lookup() takes cmap_index & charcode, but old API
-   *  takes charcode only.  To determine the passed value is for cmap_index
-   *  or charcode, the possible cmap_index is restricted not to exceed
-   *  the minimum possible charcode by a rogue client.  It is also very
-   *  unlikely that a rogue client is interested in Unicode values 0 to 15.
-   *
-   *  NOTE: The original threshold was 4 deduced from popular number of
-   *        cmap subtables in UCS-4 TrueType fonts, but now it is not
-   *        irregular for OpenType fonts to have more than 4 subtables,
-   *        because variation selector subtables are available for Apple
-   *        and Microsoft platforms.
-   */
-
-#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
-#define FT_MAX_CHARMAP_CACHEABLE 15
-#endif
+/* #define FT_CONFIG_OPTION_OLD_INTERNALS */
 
 
   /*
diff --git a/include/freetype/config/ftstdlib.h b/include/freetype/config/ftstdlib.h
index 11d5d0e..b940efc 100644
--- a/include/freetype/config/ftstdlib.h
+++ b/include/freetype/config/ftstdlib.h
@@ -5,7 +5,7 @@
 /*    ANSI-specific library and header configuration file (specification   */
 /*    only).                                                               */
 /*                                                                         */
-/*  Copyright 2002-2007, 2009, 2011 by                                     */
+/*  Copyright 2002-2007, 2009, 2011-2012 by                                */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -159,7 +159,7 @@
                                 /*       on certain platforms           */
 
 #define ft_longjmp     longjmp
-#define ft_setjmp( b ) setjmp( *(jmp_buf*) &(b) )    /* same thing here */
+#define ft_setjmp( b ) setjmp( *(ft_jmp_buf*) &(b) ) /* same thing here */
 
 
   /* the following is only used for debugging purposes, i.e., if */
diff --git a/include/freetype/freetype.h b/include/freetype/freetype.h
index 63c291a..0d5680b 100644
--- a/include/freetype/freetype.h
+++ b/include/freetype/freetype.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType high-level API and common types (specification only).       */
 /*                                                                         */
-/*  Copyright 1996-2012 by                                                 */
+/*  Copyright 1996-2013 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,6 +16,10 @@
 /***************************************************************************/
 
 
+#ifndef __FREETYPE_H__
+#define __FREETYPE_H__
+
+
 #ifndef FT_FREETYPE_H
 #error "`ft2build.h' hasn't been included yet!"
 #error "Please always use macros to include FreeType header files."
@@ -25,14 +29,10 @@
 #endif
 
 
-#ifndef __FREETYPE_H__
-#define __FREETYPE_H__
-
-
 #include <ft2build.h>
 #include FT_CONFIG_CONFIG_H
-#include FT_ERRORS_H
 #include FT_TYPES_H
+#include FT_ERRORS_H
 
 
 FT_BEGIN_HEADER
@@ -237,6 +237,10 @@
   /*    If not disabled with @FT_LOAD_NO_HINTING, the values represent     */
   /*    dimensions of the hinted glyph (in case hinting is applicable).    */
   /*                                                                       */
+  /*    Stroking a glyph with an outside border does not increase          */
+  /*    `horiAdvance' or `vertAdvance'; you have to manually adjust these  */
+  /*    values to account for the added width and height.                  */
+  /*                                                                       */
   typedef struct  FT_Glyph_Metrics_
   {
     FT_Pos  width;
@@ -844,8 +848,8 @@
   /*                           expressed in font units (see                */
   /*                           `units_per_EM').  The box is large enough   */
   /*                           to contain any glyph from the font.  Thus,  */
-  /*                           `bbox.yMax' can be seen as the `maximal     */
-  /*                           ascender', and `bbox.yMin' as the `minimal  */
+  /*                           `bbox.yMax' can be seen as the `maximum     */
+  /*                           ascender', and `bbox.yMin' as the `minimum  */
   /*                           descender'.  Only relevant for scalable     */
   /*                           formats.                                    */
   /*                                                                       */
@@ -871,19 +875,22 @@
   /*                           usually negative.  Only relevant for        */
   /*                           scalable formats.                           */
   /*                                                                       */
-  /*    height              :: The height is the vertical distance         */
+  /*    height              :: This value is the vertical distance         */
   /*                           between two consecutive baselines,          */
   /*                           expressed in font units.  It is always      */
   /*                           positive.  Only relevant for scalable       */
   /*                           formats.                                    */
   /*                                                                       */
-  /*    max_advance_width   :: The maximal advance width, in font units,   */
+  /*                           If you want the global glyph height, use    */
+  /*                           `ascender - descender'.                     */
+  /*                                                                       */
+  /*    max_advance_width   :: The maximum advance width, in font units,   */
   /*                           for all glyphs in this face.  This can be   */
   /*                           used to make word wrapping computations     */
   /*                           faster.  Only relevant for scalable         */
   /*                           formats.                                    */
   /*                                                                       */
-  /*    max_advance_height  :: The maximal advance height, in font units,  */
+  /*    max_advance_height  :: The maximum advance height, in font units,  */
   /*                           for all glyphs in this face.  This is only  */
   /*                           relevant for vertical layouts, and is set   */
   /*                           to `height' for fonts that do not provide   */
@@ -1105,8 +1112,8 @@
    *   FT_HAS_VERTICAL( face )
    *
    * @description:
-   *   A macro that returns true whenever a face object contains vertical
-   *   metrics.
+   *   A macro that returns true whenever a face object contains real
+   *   vertical metrics (and not only synthesized ones).
    *
    */
 #define FT_HAS_VERTICAL( face ) \
@@ -1338,7 +1345,7 @@
   /*    height       :: The height in 26.6 fractional pixels.  See         */
   /*                    @FT_FaceRec for the details.                       */
   /*                                                                       */
-  /*    max_advance  :: The maximal advance width in 26.6 fractional       */
+  /*    max_advance  :: The maximum advance width in 26.6 fractional       */
   /*                    pixels.  See @FT_FaceRec for the details.          */
   /*                                                                       */
   /* <Note>                                                                */
@@ -2227,6 +2234,12 @@
   /*    particular bitmap strike.  Use @FT_Select_Size instead in that     */
   /*    case.                                                              */
   /*                                                                       */
+  /*    The relation between the requested size and the resulting glyph    */
+  /*    size is dependent entirely on how the size is defined in the       */
+  /*    source face.  The font designer chooses the final size of each     */
+  /*    glyph relative to this size.  For more information refer to        */
+  /*    `http://www.freetype.org/freetype2/docs/glyphs/glyphs-2.html'      */
+  /*                                                                       */
   FT_EXPORT( FT_Error )
   FT_Request_Size( FT_Face          face,
                    FT_Size_Request  req );
@@ -2296,6 +2309,11 @@
   /* <Return>                                                              */
   /*    FreeType error code.  0~means success.                             */
   /*                                                                       */
+  /* <Note>                                                                */
+  /*    You should not rely on the resulting glyphs matching, or being     */
+  /*    constrained, to this pixel size.  Refer to @FT_Request_Size to     */
+  /*    understand how requested sizes relate to actual sizes.             */
+  /*                                                                       */
   FT_EXPORT( FT_Error )
   FT_Set_Pixel_Sizes( FT_Face  face,
                       FT_UInt  pixel_width,
@@ -2409,14 +2427,20 @@
    *     behaviour to more specific and useful cases.
    *
    *   FT_LOAD_NO_SCALE ::
-   *     Don't scale the outline glyph loaded, but keep it in font units.
+   *     Don't scale the loaded outline glyph but keep it in font units.
    *
    *     This flag implies @FT_LOAD_NO_HINTING and @FT_LOAD_NO_BITMAP, and
    *     unsets @FT_LOAD_RENDER.
    *
+   *     If the font is `tricky' (see @FT_FACE_FLAG_TRICKY for more), using
+   *     FT_LOAD_NO_SCALE usually yields meaningless outlines because the
+   *     subglyphs must be scaled and positioned with hinting instructions.
+   *     This can be solved by loading the font without FT_LOAD_NO_SCALE and
+   *     setting the character size to `font->units_per_EM'.
+   *
    *   FT_LOAD_NO_HINTING ::
-   *     Disable hinting.  This generally generates `blurrier' bitmap glyph
-   *     when the glyph is rendered in any of the anti-aliased modes.  See
+   *     Disable hinting.  This generally generates `blurrier' bitmap glyphs
+   *     when the glyph are rendered in any of the anti-aliased modes.  See
    *     also the note below.
    *
    *     This flag is implied by @FT_LOAD_NO_SCALE.
@@ -2435,8 +2459,14 @@
    *     @FT_LOAD_NO_SCALE always sets this flag.
    *
    *   FT_LOAD_VERTICAL_LAYOUT ::
-   *     Load the glyph for vertical text layout.  _Don't_ use it as it is
-   *     problematic currently.
+   *     Load the glyph for vertical text layout.  In particular, the
+   *     `advance' value in the @FT_GlyphSlotRec structure is set to the
+   *     `vertAdvance' value of the `metrics' field.
+   *
+   *     In case @FT_HAS_VERTICAL doesn't return true, you shouldn't use
+   *     this flag currently.  Reason is that in this case vertical metrics
+   *     get synthesized, and those values are not always consistent across
+   *     various font formats.
    *
    *   FT_LOAD_FORCE_AUTOHINT ::
    *     Indicates that the auto-hinter is preferred over the font's native
@@ -2493,6 +2523,14 @@
    *   FT_LOAD_NO_AUTOHINT ::
    *     Disable auto-hinter.  See also the note below.
    *
+   *   FT_LOAD_COLOR ::
+   *     This flag is used to request loading of color embedded-bitmap
+   *     images.  The resulting color bitmaps, if available, will have the
+   *     @FT_PIXEL_MODE_BGRA format.  When the flag is not used and color
+   *     bitmaps are found, they will be converted to 256-level gray
+   *     bitmaps transparently.  Those bitmaps will be in the
+   *     @FT_PIXEL_MODE_GRAY format.
+   *
    * @note:
    *   By default, hinting is enabled and the font's native hinter (see
    *   @FT_FACE_FLAG_HINTER) is preferred over the auto-hinter.  You can
@@ -2507,6 +2545,13 @@
    *   Besides deciding which hinter to use, you can also decide which
    *   hinting algorithm to use.  See @FT_LOAD_TARGET_XXX for details.
    *
+   *   Note that the auto-hinter needs a valid Unicode cmap (either a native
+   *   one or synthesized by FreeType) for producing correct results.  If a
+   *   font provides an incorrect mapping (for example, assigning the
+   *   character code U+005A, LATIN CAPITAL LETTER Z, to a glyph depicting a
+   *   mathematical integral sign), the auto-hinter might produce useless
+   *   results.
+   *
    */
 #define FT_LOAD_DEFAULT                      0x0
 #define FT_LOAD_NO_SCALE                     ( 1L << 0 )
@@ -2523,6 +2568,8 @@
 #define FT_LOAD_MONOCHROME                   ( 1L << 12 )
 #define FT_LOAD_LINEAR_DESIGN                ( 1L << 13 )
 #define FT_LOAD_NO_AUTOHINT                  ( 1L << 15 )
+  /* Bits 16..19 are used by `FT_LOAD_TARGET_' */
+#define FT_LOAD_COLOR                        ( 1L << 20 )
 
   /* */
 
@@ -2580,7 +2627,8 @@
    *
    *   If @FT_LOAD_RENDER is also set, the glyph is rendered in the
    *   corresponding mode (i.e., the mode which matches the used algorithm
-   *   best) unless @FT_LOAD_MONOCHROME is set.
+   *   best).  An exeption is FT_LOAD_TARGET_MONO since it implies
+   *   @FT_LOAD_MONOCHROME.
    *
    *   You can use a hinting algorithm that doesn't correspond to the same
    *   rendering mode.  As an example, it is possible to use the `light'
@@ -2922,7 +2970,7 @@
   /*                                                                       */
   /*    glyph_index :: The glyph index.                                    */
   /*                                                                       */
-  /*    buffer_max  :: The maximal number of bytes available in the        */
+  /*    buffer_max  :: The maximum number of bytes available in the        */
   /*                   buffer.                                             */
   /*                                                                       */
   /* <Output>                                                              */
@@ -3081,9 +3129,15 @@
   /* <Note>                                                                */
   /*    If you use FreeType to manipulate the contents of font files       */
   /*    directly, be aware that the glyph index returned by this function  */
-  /*    doesn't always correspond to the internal indices used within      */
-  /*    the file.  This is done to ensure that value~0 always corresponds  */
-  /*    to the `missing glyph'.                                            */
+  /*    doesn't always correspond to the internal indices used within the  */
+  /*    file.  This is done to ensure that value~0 always corresponds to   */
+  /*    the `missing glyph'.  If the first glyph is not named `.notdef',   */
+  /*    then for Type~1 and Type~42 fonts, `.notdef' will be moved into    */
+  /*    the glyph ID~0 position, and whatever was there will be moved to   */
+  /*    the position `.notdef' had.  For Type~1 fonts, if there is no      */
+  /*    `.notdef' glyph at all, then one will be created at index~0 and    */
+  /*    whatever was there will be moved to the last index -- Type~42      */
+  /*    fonts are considered invalid under this condition.                 */
   /*                                                                       */
   FT_EXPORT( FT_UInt )
   FT_Get_Char_Index( FT_Face   face,
@@ -3383,9 +3437,13 @@
   /*    code range for CJK characters.                                     */
   /*                                                                       */
   /*    An IVS is registered and unique; for further details please refer  */
-  /*    to Unicode Technical Report #37, the Ideographic Variation         */
-  /*    Database.  To date (October 2007), the character with the most     */
-  /*    variants is U+908A, having 8~such IVS.                             */
+  /*    to Unicode Technical Standard #37, the Ideographic Variation       */
+  /*    Database:                                                          */
+  /*                                                                       */
+  /*      http://www.unicode.org/reports/tr37/                             */
+  /*                                                                       */
+  /*    To date (November 2012), the character with the most variants is   */
+  /*    U+9089, having 31 such IVS.                                        */
   /*                                                                       */
   /*    Adobe and MS decided to support IVS with a new cmap subtable       */
   /*    (format~14).  It is an odd subtable because it is not a mapping of */
@@ -3614,7 +3672,7 @@
   /*                                                                       */
   /* <Description>                                                         */
   /*    A very simple function used to perform the computation `(a*b)/c'   */
-  /*    with maximal accuracy (it uses a 64-bit intermediate integer       */
+  /*    with maximum accuracy (it uses a 64-bit intermediate integer       */
   /*    whenever necessary).                                               */
   /*                                                                       */
   /*    This function isn't necessarily as fast as some processor specific */
@@ -3649,8 +3707,8 @@
   /*                                                                       */
   /* <Description>                                                         */
   /*    A very simple function used to perform the computation             */
-  /*    `(a*b)/0x10000' with maximal accuracy.  Most of the time this is   */
-  /*    used to multiply a given value by a 16.16 fixed float factor.      */
+  /*    `(a*b)/0x10000' with maximum accuracy.  Most of the time this is   */
+  /*    used to multiply a given value by a 16.16 fixed-point factor.      */
   /*                                                                       */
   /* <Input>                                                               */
   /*    a :: The first multiplier.                                         */
@@ -3694,8 +3752,8 @@
   /*                                                                       */
   /* <Description>                                                         */
   /*    A very simple function used to perform the computation             */
-  /*    `(a*0x10000)/b' with maximal accuracy.  Most of the time, this is  */
-  /*    used to divide a given value by a 16.16 fixed float factor.        */
+  /*    `(a*0x10000)/b' with maximum accuracy.  Most of the time, this is  */
+  /*    used to divide a given value by a 16.16 fixed-point factor.        */
   /*                                                                       */
   /* <Input>                                                               */
   /*    a :: The first multiplier.                                         */
@@ -3834,7 +3892,7 @@
    */
 #define FREETYPE_MAJOR  2
 #define FREETYPE_MINOR  4
-#define FREETYPE_PATCH  9
+#define FREETYPE_PATCH  12
 
 
   /*************************************************************************/
diff --git a/include/freetype/ftadvanc.h b/include/freetype/ftadvanc.h
index b2451be..012b74b 100644
--- a/include/freetype/ftadvanc.h
+++ b/include/freetype/ftadvanc.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Quick computation of advance widths (specification only).            */
 /*                                                                         */
-/*  Copyright 2008 by                                                      */
+/*  Copyright 2008, 2013 by                                                */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -82,8 +82,7 @@
   /*                                                                       */
   /* <Description>                                                         */
   /*    Retrieve the advance value of a given glyph outline in an          */
-  /*    @FT_Face.  By default, the unhinted advance is returned in font    */
-  /*    units.                                                             */
+  /*    @FT_Face.                                                          */
   /*                                                                       */
   /* <Input>                                                               */
   /*    face       :: The source @FT_Face handle.                          */
@@ -94,8 +93,9 @@
   /*                  calling @FT_Load_Glyph, used to determine what kind  */
   /*                  of advances you need.                                */
   /* <Output>                                                              */
-  /*    padvance :: The advance value, in either font units or 16.16       */
-  /*                format.                                                */
+  /*    padvance :: The advance value.  If scaling is performed (based on  */
+  /*                the value of `load_flags'), the advance value is in    */
+  /*                16.16 format.  Otherwise, it is in font units.         */
   /*                                                                       */
   /*                If @FT_LOAD_VERTICAL_LAYOUT is set, this is the        */
   /*                vertical advance corresponding to a vertical layout.   */
@@ -127,8 +127,7 @@
   /*                                                                       */
   /* <Description>                                                         */
   /*    Retrieve the advance values of several glyph outlines in an        */
-  /*    @FT_Face.  By default, the unhinted advances are returned in font  */
-  /*    units.                                                             */
+  /*    @FT_Face.                                                          */
   /*                                                                       */
   /* <Input>                                                               */
   /*    face        :: The source @FT_Face handle.                         */
@@ -141,8 +140,12 @@
   /*                   calling @FT_Load_Glyph.                             */
   /*                                                                       */
   /* <Output>                                                              */
-  /*    padvance :: The advances, in either font units or 16.16 format.    */
-  /*                This array must contain at least `count' elements.     */
+  /*    padvance :: The advance values.  This array, to be provided by the */
+  /*                caller, must contain at least `count' elements.        */
+  /*                                                                       */
+  /*                If scaling is performed (based on the value of         */
+  /*                `load_flags'), the advance values are in 16.16 format. */
+  /*                Otherwise, they are in font units.                     */
   /*                                                                       */
   /*                If @FT_LOAD_VERTICAL_LAYOUT is set, these are the      */
   /*                vertical advances corresponding to a vertical layout.  */
diff --git a/include/freetype/ftautoh.h b/include/freetype/ftautoh.h
new file mode 100644
index 0000000..62ce96d
--- /dev/null
+++ b/include/freetype/ftautoh.h
@@ -0,0 +1,349 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftautoh.h                                                              */
+/*                                                                         */
+/*    FreeType API for controlling the auto-hinter (specification only).   */
+/*                                                                         */
+/*  Copyright 2012 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 __FTAUTOH_H__
+#define __FTAUTOH_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
+
+
+FT_BEGIN_HEADER
+
+
+  /**************************************************************************
+   *
+   * @section:
+   *   auto_hinter
+   *
+   * @title:
+   *   The auto-hinter
+   *
+   * @abstract:
+   *   Controlling the auto-hinting module.
+   *
+   * @description:
+   *   While FreeType's auto-hinter doesn't expose API functions by itself,
+   *   it is possible to control its behaviour with @FT_Property_Set and
+   *   @FT_Property_Get.  The following lists the available properties
+   *   together with the necessary macros and structures.
+   *
+   *   Note that the auto-hinter's module name is `autofitter' for
+   *   historical reasons.
+   *
+   */
+
+
+  /**************************************************************************
+   *
+   * @property:
+   *   glyph-to-script-map
+   *
+   * @description:
+   *   The auto-hinter provides various script modules to hint glyphs.
+   *   Examples of supported scripts are Latin or CJK.  Before a glyph is
+   *   auto-hinted, the Unicode character map of the font gets examined, and
+   *   the script is then determined based on Unicode character ranges, see
+   *   below.
+   *
+   *   OpenType fonts, however, often provide much more glyphs than
+   *   character codes (small caps, superscripts, ligatures, swashes, etc.),
+   *   to be controlled by so-called `features'.  Handling OpenType features
+   *   can be quite complicated and thus needs a separate library on top of
+   *   FreeType.
+   *
+   *   The mapping between glyph indices and scripts (in the auto-hinter
+   *   sense, see the @FT_AUTOHINTER_SCRIPT_XXX values) is stored as an
+   *   array with `num_glyphs' elements, as found in the font's @FT_Face
+   *   structure.  The `glyph-to-script-map' property returns a pointer to
+   *   this array which can be modified as needed.  Note that the
+   *   modification should happen before the first glyph gets processed by
+   *   the auto-hinter so that the global analysis of the font shapes
+   *   actually uses the modified mapping.
+   *
+   *   The following example code demonstrates how to access it (omitting
+   *   the error handling).
+   *
+   *   {
+   *     FT_Library                library;
+   *     FT_Face                   face;
+   *     FT_Prop_GlyphToScriptMap  prop;
+   *
+   *
+   *     FT_Init_FreeType( &library );
+   *     FT_New_Face( library, "foo.ttf", 0, &face );
+   *
+   *     prop.face = face;
+   *
+   *     FT_Property_Get( library, "autofitter",
+   *                               "glyph-to-script-map", &prop );
+   *
+   *     // adjust `prop.map' as needed right here
+   *
+   *     FT_Load_Glyph( face, ..., FT_LOAD_FORCE_AUTOHINT );
+   *   }
+   *
+   */
+
+
+  /**************************************************************************
+   *
+   * @enum:
+   *   FT_AUTOHINTER_SCRIPT_XXX
+   *
+   * @description:
+   *   A list of constants used for the @glyph-to-script-map property to
+   *   specify the script submodule the auto-hinter should use for hinting a
+   *   particular glyph.
+   *
+   * @values:
+   *   FT_AUTOHINTER_SCRIPT_NONE ::
+   *     Don't auto-hint this glyph.
+   *
+   *   FT_AUTOHINTER_SCRIPT_LATIN ::
+   *     Apply the latin auto-hinter.  For the auto-hinter, `latin' is a
+   *     very broad term, including Cyrillic and Greek also since characters
+   *     from those scripts share the same design constraints.
+   *
+   *     By default, characters from the following Unicode ranges are
+   *     assigned to this submodule.
+   *
+   *     {
+   *       U+0020 - U+007F  // Basic Latin (no control characters)
+   *       U+00A0 - U+00FF  // Latin-1 Supplement (no control characters)
+   *       U+0100 - U+017F  // Latin Extended-A
+   *       U+0180 - U+024F  // Latin Extended-B
+   *       U+0250 - U+02AF  // IPA Extensions
+   *       U+02B0 - U+02FF  // Spacing Modifier Letters
+   *       U+0300 - U+036F  // Combining Diacritical Marks
+   *       U+0370 - U+03FF  // Greek and Coptic
+   *       U+0400 - U+04FF  // Cyrillic
+   *       U+0500 - U+052F  // Cyrillic Supplement
+   *       U+1D00 - U+1D7F  // Phonetic Extensions
+   *       U+1D80 - U+1DBF  // Phonetic Extensions Supplement
+   *       U+1DC0 - U+1DFF  // Combining Diacritical Marks Supplement
+   *       U+1E00 - U+1EFF  // Latin Extended Additional
+   *       U+1F00 - U+1FFF  // Greek Extended
+   *       U+2000 - U+206F  // General Punctuation
+   *       U+2070 - U+209F  // Superscripts and Subscripts
+   *       U+20A0 - U+20CF  // Currency Symbols
+   *       U+2150 - U+218F  // Number Forms
+   *       U+2460 - U+24FF  // Enclosed Alphanumerics
+   *       U+2C60 - U+2C7F  // Latin Extended-C
+   *       U+2DE0 - U+2DFF  // Cyrillic Extended-A
+   *       U+2E00 - U+2E7F  // Supplemental Punctuation
+   *       U+A640 - U+A69F  // Cyrillic Extended-B
+   *       U+A720 - U+A7FF  // Latin Extended-D
+   *       U+FB00 - U+FB06  // Alphab. Present. Forms (Latin Ligatures)
+   *      U+1D400 - U+1D7FF // Mathematical Alphanumeric Symbols
+   *      U+1F100 - U+1F1FF // Enclosed Alphanumeric Supplement
+   *     }
+   *
+   *   FT_AUTOHINTER_SCRIPT_CJK ::
+   *     Apply the CJK auto-hinter, covering Chinese, Japanese, Korean, old
+   *     Vietnamese, and some other scripts.
+   *
+   *     By default, characters from the following Unicode ranges are
+   *     assigned to this submodule.
+   *
+   *     {
+   *       U+1100 - U+11FF  // Hangul Jamo
+   *       U+2E80 - U+2EFF  // CJK Radicals Supplement
+   *       U+2F00 - U+2FDF  // Kangxi Radicals
+   *       U+2FF0 - U+2FFF  // Ideographic Description Characters
+   *       U+3000 - U+303F  // CJK Symbols and Punctuation
+   *       U+3040 - U+309F  // Hiragana
+   *       U+30A0 - U+30FF  // Katakana
+   *       U+3100 - U+312F  // Bopomofo
+   *       U+3130 - U+318F  // Hangul Compatibility Jamo
+   *       U+3190 - U+319F  // Kanbun
+   *       U+31A0 - U+31BF  // Bopomofo Extended
+   *       U+31C0 - U+31EF  // CJK Strokes
+   *       U+31F0 - U+31FF  // Katakana Phonetic Extensions
+   *       U+3200 - U+32FF  // Enclosed CJK Letters and Months
+   *       U+3300 - U+33FF  // CJK Compatibility
+   *       U+3400 - U+4DBF  // CJK Unified Ideographs Extension A
+   *       U+4DC0 - U+4DFF  // Yijing Hexagram Symbols
+   *       U+4E00 - U+9FFF  // CJK Unified Ideographs
+   *       U+A960 - U+A97F  // Hangul Jamo Extended-A
+   *       U+AC00 - U+D7AF  // Hangul Syllables
+   *       U+D7B0 - U+D7FF  // Hangul Jamo Extended-B
+   *       U+F900 - U+FAFF  // CJK Compatibility Ideographs
+   *       U+FE10 - U+FE1F  // Vertical forms
+   *       U+FE30 - U+FE4F  // CJK Compatibility Forms
+   *       U+FF00 - U+FFEF  // Halfwidth and Fullwidth Forms
+   *      U+1B000 - U+1B0FF // Kana Supplement
+   *      U+1D300 - U+1D35F // Tai Xuan Hing Symbols
+   *      U+1F200 - U+1F2FF // Enclosed Ideographic Supplement
+   *      U+20000 - U+2A6DF // CJK Unified Ideographs Extension B
+   *      U+2A700 - U+2B73F // CJK Unified Ideographs Extension C
+   *      U+2B740 - U+2B81F // CJK Unified Ideographs Extension D
+   *      U+2F800 - U+2FA1F // CJK Compatibility Ideographs Supplement
+   *     }
+   *
+   *   FT_AUTOHINTER_SCRIPT_INDIC ::
+   *     Apply the indic auto-hinter, covering all major scripts from the
+   *     Indian sub-continent and some other related scripts like Thai, Lao,
+   *     or Tibetan.
+   *
+   *     By default, characters from the following Unicode ranges are
+   *     assigned to this submodule.
+   *
+   *     {
+   *       U+0900 - U+0DFF  // Indic Range
+   *       U+0F00 - U+0FFF  // Tibetan
+   *       U+1900 - U+194F  // Limbu
+   *       U+1B80 - U+1BBF  // Sundanese
+   *       U+1C80 - U+1CDF  // Meetei Mayak
+   *       U+A800 - U+A82F  // Syloti Nagri
+   *      U+11800 - U+118DF // Sharada
+   *     }
+   *
+   *     Note that currently Indic support is rudimentary only, missing blue
+   *     zone support.
+   *
+   */
+#define FT_AUTOHINTER_SCRIPT_NONE   0
+#define FT_AUTOHINTER_SCRIPT_LATIN  1
+#define FT_AUTOHINTER_SCRIPT_CJK    2
+#define FT_AUTOHINTER_SCRIPT_INDIC  3
+
+
+  /**************************************************************************
+   *
+   * @struct:
+   *   FT_Prop_GlyphToScriptMap
+   *
+   * @description:
+   *   The data exchange structure for the @glyph-to-script-map property.
+   *
+   */
+   typedef struct  FT_Prop_GlyphToScriptMap_
+   {
+     FT_Face   face;
+     FT_Byte*  map;
+
+   } FT_Prop_GlyphToScriptMap;
+
+
+  /**************************************************************************
+   *
+   * @property:
+   *   fallback-script
+   *
+   * @description:
+   *   If no auto-hinter script module can be assigned to a glyph, a
+   *   fallback script gets assigned to it (see also the
+   *   @glyph-to-script-map property).  By default, this is
+   *   @FT_AUTOHINTER_SCRIPT_CJK.  Using the `fallback-script' property,
+   *   this fallback value can be changed.
+   *
+   *   {
+   *     FT_Library  library;
+   *     FT_UInt     fallback_script = FT_AUTOHINTER_SCRIPT_NONE;
+   *
+   *
+   *     FT_Init_FreeType( &library );
+   *
+   *     FT_Property_Set( library, "autofitter",
+   *                               "fallback-script", &fallback_script );
+   *   }
+   *
+   * @note:
+   *   This property can be used with @FT_Property_Get also.
+   *
+   *   It's important to use the right timing for changing this value: The
+   *   creation of the glyph-to-script map which eventually uses the
+   *   fallback script value gets triggered either by setting or reading a
+   *   face-specific property like @glyph-to-script-map, or by auto-hinting
+   *   any glyph from that face.  In particular, if you have already created
+   *   an @FT_Face structure but not loaded any glyph (using the
+   *   auto-hinter), a change of the fallback glyph will affect this face.
+   *
+   */
+
+
+  /**************************************************************************
+   *
+   * @property:
+   *   increase-x-height
+   *
+   * @description:
+   *   For ppem values in the range 6~<= ppem <= `increase-x-height', round
+   *   up the font's x~height much more often than normally.  If the value
+   *   is set to~0, which is the default, this feature is switched off.  Use
+   *   this property to improve the legibility of small font sizes if
+   *   necessary.
+   *
+   *   {
+   *     FT_Library               library;
+   *     FT_Face                  face;
+   *     FT_Prop_IncreaseXHeight  prop;
+   *
+   *
+   *     FT_Init_FreeType( &library );
+   *     FT_New_Face( library, "foo.ttf", 0, &face );
+   *     FT_Set_Char_Size( face, 10 * 64, 0, 72, 0 );
+   *
+   *     prop.face  = face;
+   *     prop.limit = 14;
+   *
+   *     FT_Property_Set( library, "autofitter",
+   *                               "increase-x-height", &prop );
+   *   }
+   *
+   * @note:
+   *   This property can be used with @FT_Property_Get also.
+   *
+   *   Set this value right after calling @FT_Set_Char_Size, but before
+   *   loading any glyph (using the auto-hinter).
+   *
+   */
+
+
+  /**************************************************************************
+   *
+   * @struct:
+   *   FT_Prop_IncreaseXHeight
+   *
+   * @description:
+   *   The data exchange structure for the @increase-x-height property.
+   *
+   */
+   typedef struct  FT_Prop_IncreaseXHeight_
+   {
+     FT_Face  face;
+     FT_UInt  limit;
+
+   } FT_Prop_IncreaseXHeight;
+
+
+ /* */
+
+FT_END_HEADER
+
+#endif /* __FTAUTOH_H__ */
+
+
+/* END */
diff --git a/include/freetype/ftbitmap.h b/include/freetype/ftbitmap.h
index 9274236..7dbf5ba 100644
--- a/include/freetype/ftbitmap.h
+++ b/include/freetype/ftbitmap.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType utility functions for bitmaps (specification).              */
 /*                                                                         */
-/*  Copyright 2004, 2005, 2006, 2008 by                                    */
+/*  Copyright 2004-2006, 2008, 2013 by                                     */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -135,9 +135,9 @@
   /*    FT_Bitmap_Convert                                                  */
   /*                                                                       */
   /* <Description>                                                         */
-  /*    Convert a bitmap object with depth 1bpp, 2bpp, 4bpp, or 8bpp to a  */
-  /*    bitmap object with depth 8bpp, making the number of used bytes per */
-  /*    line (a.k.a. the `pitch') a multiple of `alignment'.               */
+  /*    Convert a bitmap object with depth 1bpp, 2bpp, 4bpp, 8bpp or 32bpp */
+  /*    to a bitmap object with depth 8bpp, making the number of used      */
+  /*    bytes line (a.k.a. the `pitch') a multiple of `alignment'.         */
   /*                                                                       */
   /* <Input>                                                               */
   /*    library   :: A handle to a library object.                         */
diff --git a/include/freetype/ftcache.h b/include/freetype/ftcache.h
index 6af5306..4ec9587 100644
--- a/include/freetype/ftcache.h
+++ b/include/freetype/ftcache.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType Cache subsystem (specification).                            */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2010 by */
+/*  Copyright 1996-2008, 2010, 2013 by                                     */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -214,17 +214,6 @@
 
  /* */
 
-#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
-
-  /* these macros are incompatible with LLP64, should not be used */
-
-#define FT_POINTER_TO_ULONG( p )  ( (FT_ULong)(FT_Pointer)(p) )
-
-#define FTC_FACE_ID_HASH( i )                                \
-          ((FT_UInt32)(( FT_POINTER_TO_ULONG( i ) >> 3 ) ^   \
-                       ( FT_POINTER_TO_ULONG( i ) << 7 ) ) )
-
-#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
 
   /*************************************************************************/
   /*************************************************************************/
@@ -381,7 +370,7 @@
   /*    should never try to discard it yourself.                           */
   /*                                                                       */
   /*    The @FT_Face object doesn't necessarily have a current size object */
-  /*    (i.e., face->size can be 0).  If you need a specific `font size',  */
+  /*    (i.e., face->size can be~0).  If you need a specific `font size',  */
   /*    use @FTC_Manager_LookupSize instead.                               */
   /*                                                                       */
   /*    Never change the face's transformation matrix (i.e., never call    */
@@ -705,17 +694,6 @@
             (d1)->width   == (d2)->width   && \
             (d1)->flags   == (d2)->flags   )
 
-#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
-
-  /* this macro is incompatible with LLP64, should not be used */
-
-#define FTC_IMAGE_TYPE_HASH( d )                          \
-          (FT_UFast)( FTC_FACE_ID_HASH( (d)->face_id )  ^ \
-                      ( (d)->width << 8 ) ^ (d)->height ^ \
-                      ( (d)->flags << 4 )               )
-
-#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
-
 
   /*************************************************************************/
   /*                                                                       */
@@ -723,7 +701,7 @@
   /*    FTC_ImageCache                                                     */
   /*                                                                       */
   /* <Description>                                                         */
-  /*    A handle to an glyph image cache object.  They are designed to     */
+  /*    A handle to a glyph image cache object.  They are designed to      */
   /*    hold many distinct glyph images while not exceeding a certain      */
   /*    memory threshold.                                                  */
   /*                                                                       */
@@ -1071,67 +1049,6 @@
 
  /* */
 
-#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
-
-  /*@***********************************************************************/
-  /*                                                                       */
-  /* <Struct>                                                              */
-  /*    FTC_FontRec                                                        */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    A simple structure used to describe a given `font' to the cache    */
-  /*    manager.  Note that a `font' is the combination of a given face    */
-  /*    with a given character size.                                       */
-  /*                                                                       */
-  /* <Fields>                                                              */
-  /*    face_id    :: The ID of the face to use.                           */
-  /*                                                                       */
-  /*    pix_width  :: The character width in integer pixels.               */
-  /*                                                                       */
-  /*    pix_height :: The character height in integer pixels.              */
-  /*                                                                       */
-  typedef struct  FTC_FontRec_
-  {
-    FTC_FaceID  face_id;
-    FT_UShort   pix_width;
-    FT_UShort   pix_height;
-
-  } FTC_FontRec;
-
-
-  /* */
-
-
-#define FTC_FONT_COMPARE( f1, f2 )                  \
-          ( (f1)->face_id    == (f2)->face_id    && \
-            (f1)->pix_width  == (f2)->pix_width  && \
-            (f1)->pix_height == (f2)->pix_height )
-
-  /* this macro is incompatible with LLP64, should not be used */
-#define FTC_FONT_HASH( f )                              \
-          (FT_UInt32)( FTC_FACE_ID_HASH((f)->face_id) ^ \
-                       ((f)->pix_width << 8)          ^ \
-                       ((f)->pix_height)              )
-
-  typedef FTC_FontRec*  FTC_Font;
-
-
-  FT_EXPORT( FT_Error )
-  FTC_Manager_Lookup_Face( FTC_Manager  manager,
-                           FTC_FaceID   face_id,
-                           FT_Face     *aface );
-
-  FT_EXPORT( FT_Error )
-  FTC_Manager_Lookup_Size( FTC_Manager  manager,
-                           FTC_Font     font,
-                           FT_Face     *aface,
-                           FT_Size     *asize );
-
-#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
-
-
- /* */
-
 FT_END_HEADER
 
 #endif /* __FTCACHE_H__ */
diff --git a/include/freetype/ftcffdrv.h b/include/freetype/ftcffdrv.h
new file mode 100644
index 0000000..ccbcbcc
--- /dev/null
+++ b/include/freetype/ftcffdrv.h
@@ -0,0 +1,151 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftcffdrv.h                                                             */
+/*                                                                         */
+/*    FreeType API for controlling the CFF driver (specification only).    */
+/*                                                                         */
+/*  Copyright 2013 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 __FTCFFDRV_H__
+#define __FTCFFDRV_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
+
+
+FT_BEGIN_HEADER
+
+
+  /**************************************************************************
+   *
+   * @section:
+   *   cff_driver
+   *
+   * @title:
+   *   The CFF driver
+   *
+   * @abstract:
+   *   Controlling the CFF driver module.
+   *
+   * @description:
+   *   While FreeType's CFF driver doesn't expose API functions by itself,
+   *   it is possible to control its behaviour with @FT_Property_Set and
+   *   @FT_Property_Get.  The following lists the available properties
+   *   together with the necessary macros and structures.
+   *
+   *   The CFF driver's module name is `cff'.
+   *
+   */
+
+
+  /**************************************************************************
+   *
+   * @property:
+   *   hinting-engine
+   *
+   * @description:
+   *   Thanks to Adobe, which contributed a new hinting (and parsing)
+   *   engine, an application can select between `freetype' and `adobe' if
+   *   compiled with CFF_CONFIG_OPTION_OLD_ENGINE.  If this configuration
+   *   macro isn't defined, `hinting-engine' does nothing.
+   *
+   *   The default engine is `freetype' if CFF_CONFIG_OPTION_OLD_ENGINE is
+   *   defined, and `adobe' otherwise.
+   *
+   *   The following example code demonstrates how to select Adobe's hinting
+   *   engine (omitting the error handling).
+   *
+   *   {
+   *     FT_Library  library;
+   *     FT_Face     face;
+   *     FT_UInt     hinting_engine = FT_CFF_HINTING_ADOBE;
+   *
+   *
+   *     FT_Init_FreeType( &library );
+   *
+   *     FT_Property_Set( library, "cff",
+   *                               "hinting-engine", &hinting_engine );
+   *   }
+   *
+   * @note:
+   *   This property can be used with @FT_Property_Get also.
+   *
+   */
+
+
+  /**************************************************************************
+   *
+   * @enum:
+   *   FT_CFF_HINTING_XXX
+   *
+   * @description:
+   *   A list of constants used for the @hinting-engine property to select
+   *   the hinting engine for CFF fonts.
+   *
+   * @values:
+   *   FT_CFF_HINTING_FREETYPE ::
+   *     Use the old FreeType hinting engine.
+   *
+   *   FT_CFF_HINTING_ADOBE ::
+   *     Use the hinting engine contributed by Adobe.
+   *
+   */
+#define FT_CFF_HINTING_FREETYPE  0
+#define FT_CFF_HINTING_ADOBE     1
+
+
+  /**************************************************************************
+   *
+   * @property:
+   *   no-stem-darkening
+   *
+   * @description:
+   *   By default, the Adobe CFF engine darkens stems at smaller sizes,
+   *   regardless of hinting, to enhance contrast.  Setting this property,
+   *   stem darkening gets switched off.
+   *
+   *   Note that stem darkening is never applied if @FT_LOAD_NO_SCALE is set.
+   *
+   *   {
+   *     FT_Library  library;
+   *     FT_Face     face;
+   *     FT_Bool     no_stem_darkening = TRUE;
+   *
+   *
+   *     FT_Init_FreeType( &library );
+   *
+   *     FT_Property_Set( library, "cff",
+   *                               "no-stem-darkening", &no_stem_darkening );
+   *   }
+   *
+   * @note:
+   *   This property can be used with @FT_Property_Get also.
+   *
+   */
+
+
+ /* */
+
+FT_END_HEADER
+
+
+#endif /* __FTCFFDRV_H__ */
+
+
+/* END */
diff --git a/include/freetype/ftchapters.h b/include/freetype/ftchapters.h
index 6cdf54e..c55670d 100644
--- a/include/freetype/ftchapters.h
+++ b/include/freetype/ftchapters.h
@@ -67,6 +67,22 @@
 /***************************************************************************/
 /*                                                                         */
 /* <Chapter>                                                               */
+/*    module_specific                                                      */
+/*                                                                         */
+/* <Title>                                                                 */
+/*    Controlling FreeType Modules                                         */
+/*                                                                         */
+/* <Sections>                                                              */
+/*    auto_hinter                                                          */
+/*    cff_driver                                                           */
+/*    tt_driver                                                            */
+/*                                                                         */
+/***************************************************************************/
+
+
+/***************************************************************************/
+/*                                                                         */
+/* <Chapter>                                                               */
 /*    cache_subsystem                                                      */
 /*                                                                         */
 /* <Title>                                                                 */
diff --git a/include/freetype/fterrdef.h b/include/freetype/fterrdef.h
index fb4b53b..76c7b9e 100644
--- a/include/freetype/fterrdef.h
+++ b/include/freetype/fterrdef.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType error codes (specification).                                */
 /*                                                                         */
-/*  Copyright 2002, 2004, 2006, 2007, 2010-2011 by                         */
+/*  Copyright 2002, 2004, 2006, 2007, 2010-2013 by                         */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -56,6 +56,8 @@
                 "array allocation size too large" )
   FT_ERRORDEF_( Missing_Module,                              0x0B, \
                 "missing module" )
+  FT_ERRORDEF_( Missing_Property,                            0x0C, \
+                "missing property" )
 
   /* glyph/character errors */
 
@@ -215,6 +217,8 @@
                 "ignore" )
   FT_ERRORDEF_( No_Unicode_Glyph_Name,                       0xA3, \
                 "no Unicode glyph name found" )
+  FT_ERRORDEF_( Glyph_Too_Big,                               0xA4, \
+                "glyph to big for hinting" )
 
   /* BDF errors */
 
diff --git a/include/freetype/fterrors.h b/include/freetype/fterrors.h
index a54699f..0fa3e4d 100644
--- a/include/freetype/fterrors.h
+++ b/include/freetype/fterrors.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType error code handling (specification).                        */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2004, 2007 by                               */
+/*  Copyright 1996-2002, 2004, 2007, 2013 by                               */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -28,9 +28,8 @@
   /*   The configuration macro FT_CONFIG_OPTION_USE_MODULE_ERRORS can be   */
   /*   defined in ftoption.h in order to make the higher byte indicate     */
   /*   the module where the error has happened (this is not compatible     */
-  /*   with standard builds of FreeType 2).  You can then use the macro    */
-  /*   FT_ERROR_BASE macro to extract the generic error code from an       */
-  /*   FT_Error value.                                                     */
+  /*   with standard builds of FreeType 2).  See the file `ftmoderr.h' for */
+  /*   more details.                                                       */
   /*                                                                       */
   /*                                                                       */
   /* II - Error Message strings                                            */
@@ -101,12 +100,6 @@
 
 #undef  FT_NEED_EXTERN_C
 
-#undef  FT_ERR_XCAT
-#undef  FT_ERR_CAT
-
-#define FT_ERR_XCAT( x, y )  x ## y
-#define FT_ERR_CAT( x, y )   FT_ERR_XCAT( x, y )
-
 
   /* FT_ERR_PREFIX is used as a prefix for error identifiers. */
   /* By default, we use `FT_Err_'.                            */
@@ -150,11 +143,11 @@
 
 
   /* this macro is used to define an error */
-#define FT_ERRORDEF_( e, v, s )   \
+#define FT_ERRORDEF_( e, v, s )                                             \
           FT_ERRORDEF( FT_ERR_CAT( FT_ERR_PREFIX, e ), v + FT_ERR_BASE, s )
 
   /* this is only used for <module>_Err_Ok, which must be 0! */
-#define FT_NOERRORDEF_( e, v, s ) \
+#define FT_NOERRORDEF_( e, v, s )                             \
           FT_ERRORDEF( FT_ERR_CAT( FT_ERR_PREFIX, e ), v, s )
 
 
@@ -194,11 +187,9 @@
 #undef FT_NEED_EXTERN_C
 #undef FT_ERR_BASE
 
-  /* FT_KEEP_ERR_PREFIX is needed for ftvalid.h */
-#ifndef FT_KEEP_ERR_PREFIX
+  /* FT_ERR_PREFIX is needed internally */
+#ifndef FT2_BUILD_LIBRARY
 #undef FT_ERR_PREFIX
-#else
-#undef FT_KEEP_ERR_PREFIX
 #endif
 
 #endif /* __FTERRORS_H__ */
diff --git a/include/freetype/ftglyph.h b/include/freetype/ftglyph.h
index 3de69f7..31dc331 100644
--- a/include/freetype/ftglyph.h
+++ b/include/freetype/ftglyph.h
@@ -94,7 +94,7 @@
   /*                                                                       */
   /* <Description>                                                         */
   /*    The root glyph structure contains a given glyph image plus its     */
-  /*    advance width in 16.16 fixed float format.                         */
+  /*    advance width in 16.16 fixed-point format.                         */
   /*                                                                       */
   /* <Fields>                                                              */
   /*    library :: A handle to the FreeType library object.                */
diff --git a/include/freetype/ftimage.h b/include/freetype/ftimage.h
index 04b5e04..3b826b1 100644
--- a/include/freetype/ftimage.h
+++ b/include/freetype/ftimage.h
@@ -5,8 +5,7 @@
 /*    FreeType glyph image formats and default raster interface            */
 /*    (specification).                                                     */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,   */
-/*            2010 by                                                      */
+/*  Copyright 1996-2010, 2013 by                                           */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -54,7 +53,7 @@
   /* <Description>                                                         */
   /*    The type FT_Pos is used to store vectorial coordinates.  Depending */
   /*    on the context, these can represent distances in integer font      */
-  /*    units, or 16.16, or 26.6 fixed float pixel coordinates.            */
+  /*    units, or 16.16, or 26.6 fixed-point pixel coordinates.            */
   /*                                                                       */
   typedef signed long  FT_Pos;
 
@@ -169,6 +168,15 @@
   /*      times taller than the original glyph image.  See also            */
   /*      @FT_RENDER_MODE_LCD_V.                                           */
   /*                                                                       */
+  /*    FT_PIXEL_MODE_BGRA ::                                              */
+  /*      An image with four 8-bit channels per pixel, representing a      */
+  /*      color image (such as emoticons) with alpha channel.  For each    */
+  /*      pixel, the format is BGRA, which means, the blue channel comes   */
+  /*      first in memory.  The color channels are pre-multiplied and in   */
+  /*      the sRGB colorspace.  For example, full red at half-translucent  */
+  /*      opacity will be represented as `00,00,80,80', not `00,00,FF,80'. */
+  /*      See also @FT_LOAD_COLOR.                                         */
+  /*                                                                       */
   typedef enum  FT_Pixel_Mode_
   {
     FT_PIXEL_MODE_NONE = 0,
@@ -178,6 +186,7 @@
     FT_PIXEL_MODE_GRAY4,
     FT_PIXEL_MODE_LCD,
     FT_PIXEL_MODE_LCD_V,
+    FT_PIXEL_MODE_BGRA,
 
     FT_PIXEL_MODE_MAX      /* do not remove */
 
diff --git a/include/freetype/ftlcdfil.h b/include/freetype/ftlcdfil.h
index 0b55ebe..8b253f1 100644
--- a/include/freetype/ftlcdfil.h
+++ b/include/freetype/ftlcdfil.h
@@ -53,6 +53,44 @@
    *   *not* implemented in default builds of the library.  You need to
    *   #define FT_CONFIG_OPTION_SUBPIXEL_RENDERING in your `ftoption.h' file
    *   in order to activate it.
+   *
+   *   FreeType generates alpha coverage maps, which are linear by nature.
+   *   For instance, the value 0x80 in bitmap representation means that
+   *   (within numerical precision) 0x80/0xff fraction of that pixel is
+   *   covered by the glyph's outline.  The blending function for placing
+   *   text over a background is
+   *
+   *   {
+   *     dst = alpha * src + (1 - alpha) * dst    ,
+   *   }
+   *
+   *   which is known as OVER.  However, when calculating the output of the
+   *   OVER operator, the source colors should first be transformed to a
+   *   linear color space, then alpha blended in that space, and transformed
+   *   back to the output color space.
+   *
+   *   When linear light blending is used, the default FIR5 filtering
+   *   weights (as given by FT_LCD_FILTER_DEFAULT) are no longer optimal, as
+   *   they have been designed for black on white rendering while lacking
+   *   gamma correction.  To preserve color neutrality, weights for a FIR5
+   *   filter should be chosen according to two free parameters `a' and `c',
+   *   and the FIR weights should be
+   *
+   *   {
+   *     [a - c, a + c, 2 * a, a + c, a - c]    .
+   *   }
+   *
+   *   This formula generates equal weights for all the color primaries
+   *   across the filter kernel, which makes it colorless.  One suggested
+   *   set of weights is
+   *
+   *   {
+   *     [0x10, 0x50, 0x60, 0x50, 0x10]    ,
+   *   }
+   *
+   *   where `a' has value 0x30 and `b' value 0x20.  The weights in filter
+   *   may have a sum larger than 0x100, which increases coloration slightly
+   *   but also improves contrast.
    */
 
 
diff --git a/include/freetype/ftmodapi.h b/include/freetype/ftmodapi.h
index 8f2e017..8abffb5 100644
--- a/include/freetype/ftmodapi.h
+++ b/include/freetype/ftmodapi.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType modules public interface (specification).                   */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003, 2006, 2008, 2009, 2010 by             */
+/*  Copyright 1996-2003, 2006, 2008-2010, 2012, 2013 by                    */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -42,11 +42,38 @@
   /*    Module Management                                                  */
   /*                                                                       */
   /* <Abstract>                                                            */
-  /*    How to add, upgrade, and remove modules from FreeType.             */
+  /*    How to add, upgrade, remove, and control modules from FreeType.    */
   /*                                                                       */
   /* <Description>                                                         */
   /*    The definitions below are used to manage modules within FreeType.  */
   /*    Modules can be added, upgraded, and removed at runtime.            */
+  /*    Additionally, some module properties can be controlled also.       */
+  /*                                                                       */
+  /*    Here is a list of possible values of the `module_name' field in    */
+  /*    the @FT_Module_Class structure.                                    */
+  /*                                                                       */
+  /*    {                                                                  */
+  /*      autofitter                                                       */
+  /*      bdf                                                              */
+  /*      cff                                                              */
+  /*      gxvalid                                                          */
+  /*      otvalid                                                          */
+  /*      pcf                                                              */
+  /*      pfr                                                              */
+  /*      psaux                                                            */
+  /*      pshinter                                                         */
+  /*      psnames                                                          */
+  /*      raster1, raster5                                                 */
+  /*      sfnt                                                             */
+  /*      smooth, smooth-lcd, smooth-lcdv                                  */
+  /*      truetype                                                         */
+  /*      type1                                                            */
+  /*      type42                                                           */
+  /*      t1cid                                                            */
+  /*      winfonts                                                         */
+  /*    }                                                                  */
+  /*                                                                       */
+  /*    Note that the FreeType Cache sub-system is not a FreeType module.  */
   /*                                                                       */
   /*************************************************************************/
 
@@ -118,7 +145,7 @@
   /*    A function used to query a given module for a specific interface.  */
   /*                                                                       */
   /* <Input>                                                               */
-  /*    module :: The module to finalize.                                  */
+  /*    module :: The module to be searched.                               */
   /*                                                                       */
   /*    name ::   The name of the interface in the module.                 */
   /*                                                                       */
@@ -249,6 +276,137 @@
                     FT_Module   module );
 
 
+  /**********************************************************************
+   *
+   * @function:
+   *    FT_Property_Set
+   *
+   * @description:
+   *    Set a property for a given module.
+   *
+   * @input:
+   *    library ::
+   *       A handle to the library the module is part of.
+   *
+   *    module_name ::
+   *       The module name.
+   *
+   *    property_name ::
+   *       The property name.  Properties are described in the `Synopsis'
+   *       subsection of the module's documentation.
+   *
+   *       Note that only a few modules have properties.
+   *
+   *    value ::
+   *       A generic pointer to a variable or structure which gives the new
+   *       value of the property.  The exact definition of `value' is
+   *       dependent on the property; see the `Synopsis' subsection of the
+   *       module's documentation.
+   *
+   * @return:
+   *   FreeType error code.  0~means success.
+   *
+   * @note:
+   *    If `module_name' isn't a valid module name, or `property_name'
+   *    doesn't specify a valid property, or if `value' doesn't represent a
+   *    valid value for the given property, an error is returned.
+   *
+   *    The following example sets property `bar' (a simple integer) in
+   *    module `foo' to value~1.
+   *
+   *    {
+   *      FT_UInt  bar;
+   *
+   *
+   *      bar = 1;
+   *      FT_Property_Set( library, "foo", "bar", &bar );
+   *    }
+   *
+   *    Note that the FreeType Cache sub-system doesn't recognize module
+   *    property changes.  To avoid glyph lookup confusion within the cache
+   *    you should call @FTC_Manager_Reset to completely flush the cache if
+   *    a module property gets changed after @FTC_Manager_New has been
+   *    called.
+   *
+   *    It is not possible to set properties of the FreeType Cache
+   *    sub-system itself with FT_Property_Set; use @FTC_Property_Set
+   *    instead.
+   *
+   *  @since:
+   *    2.4.11
+   *
+   */
+  FT_EXPORT( FT_Error )
+  FT_Property_Set( FT_Library        library,
+                   const FT_String*  module_name,
+                   const FT_String*  property_name,
+                   const void*       value );
+
+
+  /**********************************************************************
+   *
+   * @function:
+   *    FT_Property_Get
+   *
+   * @description:
+   *    Get a module's property value.
+   *
+   * @input:
+   *    library ::
+   *       A handle to the library the module is part of.
+   *
+   *    module_name ::
+   *       The module name.
+   *
+   *    property_name ::
+   *       The property name.  Properties are described in the `Synopsis'
+   *       subsection of the module's documentation.
+   *
+   * @inout:
+   *    value ::
+   *       A generic pointer to a variable or structure which gives the
+   *       value of the property.  The exact definition of `value' is
+   *       dependent on the property; see the `Synopsis' subsection of the
+   *       module's documentation.
+   *
+   * @return:
+   *   FreeType error code.  0~means success.
+   *
+   * @note:
+   *    If `module_name' isn't a valid module name, or `property_name'
+   *    doesn't specify a valid property, or if `value' doesn't represent a
+   *    valid value for the given property, an error is returned.
+   *
+   *    The following example gets property `baz' (a range) in module `foo'.
+   *
+   *    {
+   *      typedef  range_
+   *      {
+   *        FT_Int32  min;
+   *        FT_Int32  max;
+   *
+   *      } range;
+   *
+   *      range  baz;
+   *
+   *
+   *      FT_Property_Get( library, "foo", "baz", &baz );
+   *    }
+   *
+   *    It is not possible to retrieve properties of the FreeType Cache
+   *    sub-system with FT_Property_Get; use @FTC_Property_Get instead.
+   *
+   *  @since:
+   *    2.4.11
+   *
+   */
+  FT_EXPORT( FT_Error )
+  FT_Property_Get( FT_Library        library,
+                   const FT_String*  module_name,
+                   const FT_String*  property_name,
+                   void*             value );
+
+
   /*************************************************************************/
   /*                                                                       */
   /* <Function>                                                            */
@@ -430,13 +588,13 @@
    *       scale glyph components with bytecode instructions.  It produces
    *       bad output for most other fonts.
    *
-   *    FT_TRUETYPE_ENGINE_TYPE_PATENTED ::
+   *     FT_TRUETYPE_ENGINE_TYPE_PATENTED ::
    *       The library implements a bytecode interpreter that covers
    *       the full instruction set of the TrueType virtual machine (this
    *       was governed by patents until May 2010, hence the name).
    *
    *  @since:
-   *       2.2
+   *     2.2
    *
    */
   typedef enum  FT_TrueTypeEngineType_
diff --git a/include/freetype/ftmoderr.h b/include/freetype/ftmoderr.h
index 1bf3b38..5a27db1 100644
--- a/include/freetype/ftmoderr.h
+++ b/include/freetype/ftmoderr.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType module error offsets (specification).                       */
 /*                                                                         */
-/*  Copyright 2001, 2002, 2003, 2004, 2005, 2010 by                        */
+/*  Copyright 2001-2005, 2010, 2013 by                                     */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -18,17 +18,57 @@
 
   /*************************************************************************/
   /*                                                                       */
-  /* This file is used to define the FreeType module error offsets.        */
+  /* This file is used to define the FreeType module error codes.          */
   /*                                                                       */
-  /* The lower byte gives the error code, the higher byte gives the        */
-  /* module.  The base module has error offset 0.  For example, the error  */
-  /* `FT_Err_Invalid_File_Format' has value 0x003, the error               */
-  /* `TT_Err_Invalid_File_Format' has value 0x1103, the error              */
-  /* `T1_Err_Invalid_File_Format' has value 0x1203, etc.                   */
+  /* If the macro FT_CONFIG_OPTION_USE_MODULE_ERRORS in `ftoption.h' is    */
+  /* set, the lower byte of an error value identifies the error code as    */
+  /* usual.  In addition, the higher byte identifies the module.  For      */
+  /* example, the error `FT_Err_Invalid_File_Format' has value 0x0003, the */
+  /* error `TT_Err_Invalid_File_Format' has value 0x1303, the error        */
+  /* `T1_Err_Invalid_File_Format' has value 0x1403, etc.                   */
   /*                                                                       */
-  /* Undefine the macro FT_CONFIG_OPTION_USE_MODULE_ERRORS in ftoption.h   */
-  /* to make the higher byte always zero (disabling the module error       */
-  /* mechanism).                                                           */
+  /* Note that `FT_Err_Ok', `TT_Err_Ok', etc. are always equal to zero,    */
+  /* including the high byte.                                              */
+  /*                                                                       */
+  /* If FT_CONFIG_OPTION_USE_MODULE_ERRORS isn't set, the higher byte of   */
+  /* an error value is set to zero.                                        */
+  /*                                                                       */
+  /* To hide the various `XXX_Err_' prefixes in the source code, FreeType  */
+  /* provides some macros in `fttypes.h'.                                  */
+  /*                                                                       */
+  /*   FT_ERR( err )                                                       */
+  /*     Add current error module prefix (as defined with the              */
+  /*     `FT_ERR_PREFIX' macro) to `err'.  For example, in the BDF module  */
+  /*     the line                                                          */
+  /*                                                                       */
+  /*       error = FT_ERR( Invalid_Outline );                              */
+  /*                                                                       */
+  /*     expands to                                                        */
+  /*                                                                       */
+  /*       error = BDF_Err_Invalid_Outline;                                */
+  /*                                                                       */
+  /*     For simplicity, you can always use `FT_Err_Ok' directly instead   */
+  /*     of `FT_ERR( Ok )'.                                                */
+  /*                                                                       */
+  /*   FT_ERR_EQ( errcode, err )                                           */
+  /*   FT_ERR_NEQ( errcode, err )                                          */
+  /*     Compare error code `errcode' with the error `err' for equality    */
+  /*     and inequality, respectively.  Example:                           */
+  /*                                                                       */
+  /*       if ( FT_ERR_EQ( error, Invalid_Outline ) )                      */
+  /*         ...                                                           */
+  /*                                                                       */
+  /*     Using this macro you don't have to think about error prefixes.    */
+  /*     Of course, if module errors are not active, the above example is  */
+  /*     the same as                                                       */
+  /*                                                                       */
+  /*       if ( error == FT_Err_Invalid_Outline )                          */
+  /*         ...                                                           */
+  /*                                                                       */
+  /*   FT_ERROR_BASE( errcode )                                            */
+  /*   FT_ERROR_MODULE( errcode )                                          */
+  /*     Get base error and module error code, respectively.               */
+  /*                                                                       */
   /*                                                                       */
   /* It can also be used to create a module error message table easily     */
   /* with something like                                                   */
@@ -48,9 +88,6 @@
   /*     #include FT_MODULE_ERRORS_H                                       */
   /*   }                                                                   */
   /*                                                                       */
-  /* To use such a table, all errors must be ANDed with 0xFF00 to remove   */
-  /* the error code.                                                       */
-  /*                                                                       */
   /*************************************************************************/
 
 
@@ -124,6 +161,7 @@
   FT_MODERRDEF( Type1,    0x1300, "Type 1 module" )
   FT_MODERRDEF( Type42,   0x1400, "Type 42 module" )
   FT_MODERRDEF( Winfonts, 0x1500, "Windows FON/FNT module" )
+  FT_MODERRDEF( GXvalid,  0x1600, "GX validation module" )
 
 
 #ifdef FT_MODERR_END_LIST
diff --git a/include/freetype/ftoutln.h b/include/freetype/ftoutln.h
index 1cf3c3f..fd69f28 100644
--- a/include/freetype/ftoutln.h
+++ b/include/freetype/ftoutln.h
@@ -5,7 +5,7 @@
 /*    Support for the FT_Outline type used to store glyph shapes of        */
 /*    most scalable font formats (specification).                          */
 /*                                                                         */
-/*  Copyright 1996-2003, 2005-2011 by                                      */
+/*  Copyright 1996-2003, 2005-2012 by                                      */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -59,6 +59,7 @@
   /*    FT_Outline_Translate                                               */
   /*    FT_Outline_Transform                                               */
   /*    FT_Outline_Embolden                                                */
+  /*    FT_Outline_EmboldenXY                                              */
   /*    FT_Outline_Reverse                                                 */
   /*    FT_Outline_Check                                                   */
   /*                                                                       */
@@ -124,9 +125,11 @@
   /*                   outline will *not* necessarily be *freed*, when     */
   /*                   destroying the library, by @FT_Done_FreeType.       */
   /*                                                                       */
-  /*    numPoints   :: The maximal number of points within the outline.    */
+  /*    numPoints   :: The maximum number of points within the outline.    */
+  /*                   Must be smaller than or equal to 0xFFFF (65535).    */
   /*                                                                       */
-  /*    numContours :: The maximal number of contours within the outline.  */
+  /*    numContours :: The maximum number of contours within the outline.  */
+  /*                   This value must be in the range 0 to `numPoints'.   */
   /*                                                                       */
   /* <Output>                                                              */
   /*    anoutline   :: A handle to the new outline.                        */
@@ -353,6 +356,23 @@
   /*************************************************************************/
   /*                                                                       */
   /* <Function>                                                            */
+  /*    FT_Outline_EmboldenXY                                              */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Embolden an outline.  The new outline will be `xstrength' pixels   */
+  /*    wider and `ystrength' pixels higher.  Otherwise, it is similar to  */
+  /*    @FT_Outline_Embolden, which uses the same strength in both         */
+  /*    directions.                                                        */
+  /*                                                                       */
+  FT_EXPORT( FT_Error )
+  FT_Outline_EmboldenXY( FT_Outline*  outline,
+                         FT_Pos       xstrength,
+                         FT_Pos       ystrength );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
   /*    FT_Outline_Reverse                                                 */
   /*                                                                       */
   /* <Description>                                                         */
diff --git a/include/freetype/ftstroke.h b/include/freetype/ftstroke.h
index 49ae2bc..a498e4a 100644
--- a/include/freetype/ftstroke.h
+++ b/include/freetype/ftstroke.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType path stroker (specification).                               */
 /*                                                                         */
-/*  Copyright 2002-2006, 2008, 2009, 2011 by                               */
+/*  Copyright 2002-2006, 2008, 2009, 2011-2012 by                          */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -271,7 +271,7 @@
    *   miter_limit ::
    *     The miter limit for the FT_STROKER_LINEJOIN_MITER_FIXED and
    *     FT_STROKER_LINEJOIN_MITER_VARIABLE line join styles,
-   *     expressed as 16.16 fixed point value.
+   *     expressed as 16.16 fixed-point value.
    *
    * @note:
    *   The radius is expressed in the same units as the outline
@@ -682,6 +682,11 @@
    *
    * @note:
    *   The source glyph is untouched in case of error.
+   *
+   *   Adding stroke may yield a significantly wider and taller glyph
+   *   depending on how large of a radius was used to stroke the glyph.  You
+   *   may need to manually adjust horizontal and vertical advance amounts
+   *   to account for this added size.
    */
   FT_EXPORT( FT_Error )
   FT_Glyph_Stroke( FT_Glyph    *pglyph,
@@ -719,6 +724,11 @@
    *
    * @note:
    *   The source glyph is untouched in case of error.
+   *
+   *   Adding stroke may yield a significantly wider and taller glyph
+   *   depending on how large of a radius was used to stroke the glyph.  You
+   *   may need to manually adjust horizontal and vertical advance amounts
+   *   to account for this added size.
    */
   FT_EXPORT( FT_Error )
   FT_Glyph_StrokeBorder( FT_Glyph    *pglyph,
diff --git a/include/freetype/ftsynth.h b/include/freetype/ftsynth.h
index a068b79..2074503 100644
--- a/include/freetype/ftsynth.h
+++ b/include/freetype/ftsynth.h
@@ -5,7 +5,7 @@
 /*    FreeType synthesizing code for emboldening and slanting              */
 /*    (specification).                                                     */
 /*                                                                         */
-/*  Copyright 2000-2001, 2003, 2006, 2008 by                               */
+/*  Copyright 2000-2001, 2003, 2006, 2008, 2012 by                         */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -61,8 +61,9 @@
   /* taste).  This function is actually a convenience function, providing  */
   /* a wrapper for @FT_Outline_Embolden and @FT_Bitmap_Embolden.           */
   /*                                                                       */
-  /* For emboldened outlines the metrics are estimates only; if you need   */
-  /* precise values you should call @FT_Outline_Get_CBox.                  */
+  /* For emboldened outlines the height, width, and advance metrics are    */
+  /* increased by the strength of the emboldening.  You can also call      */
+  /* @FT_Outline_Get_CBox to get precise values.                           */
   FT_EXPORT( void )
   FT_GlyphSlot_Embolden( FT_GlyphSlot  slot );
 
diff --git a/include/freetype/fttrigon.h b/include/freetype/fttrigon.h
index 6b77d2e..65143cb 100644
--- a/include/freetype/fttrigon.h
+++ b/include/freetype/fttrigon.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType trigonometric functions (specification).                    */
 /*                                                                         */
-/*  Copyright 2001, 2003, 2005, 2007 by                                    */
+/*  Copyright 2001, 2003, 2005, 2007, 2013 by                              */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -46,7 +46,7 @@
    *
    * @description:
    *   This type is used to model angle values in FreeType.  Note that the
-   *   angle is a 16.16 fixed float value expressed in degrees.
+   *   angle is a 16.16 fixed-point value expressed in degrees.
    *
    */
   typedef FT_Fixed  FT_Angle;
@@ -106,7 +106,7 @@
    *   FT_Sin
    *
    * @description:
-   *   Return the sinus of a given angle in fixed point format.
+   *   Return the sinus of a given angle in fixed-point format.
    *
    * @input:
    *   angle ::
@@ -130,7 +130,7 @@
    *   FT_Cos
    *
    * @description:
-   *   Return the cosinus of a given angle in fixed point format.
+   *   Return the cosinus of a given angle in fixed-point format.
    *
    * @input:
    *   angle ::
@@ -154,7 +154,7 @@
    *   FT_Tan
    *
    * @description:
-   *   Return the tangent of a given angle in fixed point format.
+   *   Return the tangent of a given angle in fixed-point format.
    *
    * @input:
    *   angle ::
diff --git a/include/freetype/ftttdrv.h b/include/freetype/ftttdrv.h
new file mode 100644
index 0000000..d5d3f1c
--- /dev/null
+++ b/include/freetype/ftttdrv.h
@@ -0,0 +1,150 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftttdrv.h                                                              */
+/*                                                                         */
+/*    FreeType API for controlling the TrueType driver                     */
+/*    (specification only).                                                */
+/*                                                                         */
+/*  Copyright 2013 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 __FTTTDRV_H__
+#define __FTTTDRV_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
+
+
+FT_BEGIN_HEADER
+
+
+  /**************************************************************************
+   *
+   * @section:
+   *   tt_driver
+   *
+   * @title:
+   *   The TrueType driver
+   *
+   * @abstract:
+   *   Controlling the TrueType driver module.
+   *
+   * @description:
+   *   While FreeType's TrueType driver doesn't expose API functions by
+   *   itself, it is possible to control its behaviour with @FT_Property_Set
+   *   and @FT_Property_Get.  The following lists the available properties
+   *   together with the necessary macros and structures.
+   *
+   *   The TrueType driver's module name is `truetype'.
+   *
+   */
+
+
+  /**************************************************************************
+   *
+   * @property:
+   *   interpreter-version
+   *
+   * @description:
+   *   Currently, two versions are available which represent the bytecode
+   *   interpreter with and without subpixel hinting support,
+   *   respectively.  The default is subpixel support if
+   *   TT_CONFIG_OPTION_SUBPIXEL_HINTING is defined, and no subpixel
+   *   support otherwise (since it isn't available then).
+   *
+   *   If subpixel hinting is on, many TrueType bytecode instructions
+   *   behave differently compared to B/W or grayscale rendering.  The
+   *   main idea is to render at a much increased horizontal resolution,
+   *   then sampling down the created output to subpixel precision.
+   *   However, many older fonts are not suited to this and must be
+   *   specially taken care of by applying (hardcoded) font-specific
+   *   tweaks.
+   *
+   *   Details on subpixel hinting and some of the necessary tweaks can be
+   *   found in Greg Hitchcock's whitepaper at
+   *   `http://www.microsoft.com/typography/cleartype/truetypecleartype.aspx'.
+   *
+   *   The following example code demonstrates how to activate subpixel
+   *   hinting (omitting the error handling).
+   *
+   *   {
+   *     FT_Library  library;
+   *     FT_Face     face;
+   *     FT_UInt     interpreter_version = TT_INTERPRETER_VERSION_38;
+   *
+   *
+   *     FT_Init_FreeType( &library );
+   *
+   *     FT_Property_Set( library, "truetype",
+   *                               "interpreter-version",
+   *                               &interpreter_version );
+   *   }
+   *
+   * @note:
+   *   This property can be used with @FT_Property_Get also.
+   *
+   */
+
+
+  /**************************************************************************
+   *
+   * @enum:
+   *   TT_INTERPRETER_VERSION_XXX
+   *
+   * @description:
+   *   A list of constants used for the @interpreter-version property to
+   *   select the hinting engine for Truetype fonts.
+   *
+   *   The numeric value in the constant names represents the version
+   *   number as returned by the `GETINFO' bytecode instruction.
+   *
+   * @values:
+   *   TT_INTERPRETER_VERSION_35 ::
+   *     Version~35 corresponds to MS rasterizer v.1.7 as used e.g. in
+   *     Windows~98; only grayscale and B/W rasterizing is supported.
+   *
+   *   TT_INTERPRETER_VERSION_38 ::
+   *     Version~38 corresponds to MS rasterizer v.1.9; it is roughly
+   *     equivalent to the hinting provided by DirectWrite ClearType (as
+   *     can be found, for example, in the Internet Explorer~9 running on
+   *     Windows~7).
+   *
+   * @note:
+   *   This property controls the behaviour of the bytecode interpreter
+   *   and thus how outlines get hinted.  It does *not* control how glyph
+   *   get rasterized!  In particular, it does not control subpixel color
+   *   filtering.
+   *
+   *   If FreeType has not been compiled with configuration option
+   *   FT_CONFIG_OPTION_SUBPIXEL_HINTING, selecting version~38 causes an
+   *   `FT_Err_Unimplemented_Feature' error.
+   *
+   */
+#define TT_INTERPRETER_VERSION_35  35
+#define TT_INTERPRETER_VERSION_38  38
+
+
+ /* */
+
+FT_END_HEADER
+
+
+#endif /* __FTTTDRV_H__ */
+
+
+/* END */
diff --git a/include/freetype/fttypes.h b/include/freetype/fttypes.h
index 3255527..027e59c 100644
--- a/include/freetype/fttypes.h
+++ b/include/freetype/fttypes.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType simple types definitions (specification only).              */
 /*                                                                         */
-/*  Copyright 1996-2002, 2004, 2006-2009, 2012 by                          */
+/*  Copyright 1996-2002, 2004, 2006-2009, 2012, 2013 by                    */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -255,7 +255,7 @@
   /*    FT_F2Dot14                                                         */
   /*                                                                       */
   /* <Description>                                                         */
-  /*    A signed 2.14 fixed float type used for unit vectors.              */
+  /*    A signed 2.14 fixed-point type used for unit vectors.              */
   /*                                                                       */
   typedef signed short  FT_F2Dot14;
 
@@ -266,7 +266,7 @@
   /*    FT_F26Dot6                                                         */
   /*                                                                       */
   /* <Description>                                                         */
-  /*    A signed 26.6 fixed float type used for vectorial pixel            */
+  /*    A signed 26.6 fixed-point type used for vectorial pixel            */
   /*    coordinates.                                                       */
   /*                                                                       */
   typedef signed long  FT_F26Dot6;
@@ -278,7 +278,7 @@
   /*    FT_Fixed                                                           */
   /*                                                                       */
   /* <Description>                                                         */
-  /*    This type is used to store 16.16 fixed float values, like scaling  */
+  /*    This type is used to store 16.16 fixed-point values, like scaling  */
   /*    values or matrix coefficients.                                     */
   /*                                                                       */
   typedef signed long  FT_Fixed;
@@ -362,7 +362,7 @@
   /*                                                                       */
   /* <Description>                                                         */
   /*    A simple structure used to store a 2x2 matrix.  Coefficients are   */
-  /*    in 16.16 fixed float format.  The computation performed is:        */
+  /*    in 16.16 fixed-point format.  The computation performed is:        */
   /*                                                                       */
   /*       {                                                               */
   /*          x' = x*xx + y*xy                                             */
@@ -571,14 +571,24 @@
   /* */
 
 #define FT_IS_EMPTY( list )  ( (list).head == 0 )
+#define FT_BOOL( x )  ( (FT_Bool)( x ) )
 
-  /* return base error code (without module-specific prefix) */
+  /* concatenate C tokens */
+#define FT_ERR_XCAT( x, y )  x ## y
+#define FT_ERR_CAT( x, y )   FT_ERR_XCAT( x, y )
+
+  /* see `ftmoderr.h' for descriptions of the following macros */
+
+#define FT_ERR( e )  FT_ERR_CAT( FT_ERR_PREFIX, e )
+
 #define FT_ERROR_BASE( x )    ( (x) & 0xFF )
-
-  /* return module error code */
 #define FT_ERROR_MODULE( x )  ( (x) & 0xFF00U )
 
-#define FT_BOOL( x )  ( (FT_Bool)( x ) )
+#define FT_ERR_EQ( x, e )                                        \
+          ( FT_ERROR_BASE( x ) == FT_ERROR_BASE( FT_ERR( e ) ) )
+#define FT_ERR_NEQ( x, e )                                       \
+          ( FT_ERROR_BASE( x ) != FT_ERROR_BASE( FT_ERR( e ) ) )
+
 
 FT_END_HEADER
 
diff --git a/include/freetype/internal/autohint.h b/include/freetype/internal/autohint.h
index 231bdd4..545de93 100644
--- a/include/freetype/internal/autohint.h
+++ b/include/freetype/internal/autohint.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    High-level `autohint' module-specific interface (specification).     */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2007 by                                     */
+/*  Copyright 1996-2002, 2007, 2009, 2012 by                               */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -86,20 +86,20 @@
   /*    FT_AutoHinter_GlobalGetFunc                                        */
   /*                                                                       */
   /* <Description>                                                         */
-  /*    Retrieves the global hints computed for a given face object the    */
+  /*    Retrieve the global hints computed for a given face object.  The   */
   /*    resulting data is dissociated from the face and will survive a     */
   /*    call to FT_Done_Face().  It must be discarded through the API      */
   /*    FT_AutoHinter_GlobalDoneFunc().                                    */
   /*                                                                       */
   /* <Input>                                                               */
-  /*    hinter        :: A handle to the source auto-hinter.               */
+  /*    hinter       :: A handle to the source auto-hinter.                */
   /*                                                                       */
-  /*    face          :: A handle to the source face object.               */
+  /*    face         :: A handle to the source face object.                */
   /*                                                                       */
   /* <Output>                                                              */
-  /*    global_hints  :: A typeless pointer to the global hints.           */
+  /*    global_hints :: A typeless pointer to the global hints.            */
   /*                                                                       */
-  /*    global_len    :: The size in bytes of the global hints.            */
+  /*    global_len   :: The size in bytes of the global hints.             */
   /*                                                                       */
   typedef void
   (*FT_AutoHinter_GlobalGetFunc)( FT_AutoHinter  hinter,
@@ -114,7 +114,7 @@
   /*    FT_AutoHinter_GlobalDoneFunc                                       */
   /*                                                                       */
   /* <Description>                                                         */
-  /*    Discards the global hints retrieved through                        */
+  /*    Discard the global hints retrieved through                         */
   /*    FT_AutoHinter_GlobalGetFunc().  This is the only way these hints   */
   /*    are freed from memory.                                             */
   /*                                                                       */
@@ -168,8 +168,8 @@
   /*    This function is capable of loading composite glyphs by hinting    */
   /*    each sub-glyph independently (which improves quality).             */
   /*                                                                       */
-  /*    It will call the font driver with FT_Load_Glyph(), with            */
-  /*    FT_LOAD_NO_SCALE set.                                              */
+  /*    It will call the font driver with @FT_Load_Glyph, with             */
+  /*    @FT_LOAD_NO_SCALE set.                                             */
   /*                                                                       */
   typedef FT_Error
   (*FT_AutoHinter_GlyphLoadFunc)( FT_AutoHinter  hinter,
@@ -182,43 +182,56 @@
   /*************************************************************************/
   /*                                                                       */
   /* <Struct>                                                              */
-  /*    FT_AutoHinter_ServiceRec                                           */
+  /*    FT_AutoHinter_InterfaceRec                                         */
   /*                                                                       */
   /* <Description>                                                         */
   /*    The auto-hinter module's interface.                                */
   /*                                                                       */
-  typedef struct  FT_AutoHinter_ServiceRec_
+  typedef struct  FT_AutoHinter_InterfaceRec_
   {
     FT_AutoHinter_GlobalResetFunc  reset_face;
     FT_AutoHinter_GlobalGetFunc    get_global_hints;
     FT_AutoHinter_GlobalDoneFunc   done_global_hints;
     FT_AutoHinter_GlyphLoadFunc    load_glyph;
 
-  } FT_AutoHinter_ServiceRec, *FT_AutoHinter_Service;
+  } FT_AutoHinter_InterfaceRec, *FT_AutoHinter_Interface;
+
 
 #ifndef FT_CONFIG_OPTION_PIC
 
-#define FT_DEFINE_AUTOHINTER_SERVICE(class_, reset_face_, get_global_hints_, \
-                                     done_global_hints_, load_glyph_)        \
-  FT_CALLBACK_TABLE_DEF                                                      \
-  const FT_AutoHinter_ServiceRec class_ =                                    \
-  {                                                                          \
-    reset_face_, get_global_hints_, done_global_hints_, load_glyph_          \
+#define FT_DEFINE_AUTOHINTER_INTERFACE(       \
+          class_,                             \
+          reset_face_,                        \
+          get_global_hints_,                  \
+          done_global_hints_,                 \
+          load_glyph_ )                       \
+  FT_CALLBACK_TABLE_DEF                       \
+  const FT_AutoHinter_InterfaceRec  class_ =  \
+  {                                           \
+    reset_face_,                              \
+    get_global_hints_,                        \
+    done_global_hints_,                       \
+    load_glyph_                               \
   };
 
 #else /* FT_CONFIG_OPTION_PIC */
 
-#define FT_DEFINE_AUTOHINTER_SERVICE(class_, reset_face_, get_global_hints_, \
-                                     done_global_hints_, load_glyph_)        \
-  void                                                                       \
-  FT_Init_Class_##class_( FT_Library library,                                \
-                          FT_AutoHinter_ServiceRec* clazz)                   \
-  {                                                                          \
-    FT_UNUSED(library);                                                      \
-    clazz->reset_face = reset_face_;                                         \
-    clazz->get_global_hints = get_global_hints_;                             \
-    clazz->done_global_hints = done_global_hints_;                           \
-    clazz->load_glyph = load_glyph_;                                         \
+#define FT_DEFINE_AUTOHINTER_INTERFACE(                            \
+          class_,                                                  \
+          reset_face_,                                             \
+          get_global_hints_,                                       \
+          done_global_hints_,                                      \
+          load_glyph_ )                                            \
+  void                                                             \
+  FT_Init_Class_ ## class_( FT_Library                   library,  \
+                            FT_AutoHinter_InterfaceRec*  clazz )   \
+  {                                                                \
+    FT_UNUSED( library );                                          \
+                                                                   \
+    clazz->reset_face        = reset_face_;                        \
+    clazz->get_global_hints  = get_global_hints_;                  \
+    clazz->done_global_hints = done_global_hints_;                 \
+    clazz->load_glyph        = load_glyph_;                        \
   }
 
 #endif /* FT_CONFIG_OPTION_PIC */
diff --git a/include/freetype/internal/ftcalc.h b/include/freetype/internal/ftcalc.h
index f8b4324..faac3a3 100644
--- a/include/freetype/internal/ftcalc.h
+++ b/include/freetype/internal/ftcalc.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Arithmetic computations (specification).                             */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2008, 2009 by       */
+/*  Copyright 1996-2006, 2008, 2009, 2012-2013 by                          */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -33,7 +33,7 @@
   /*    FT_FixedSqrt                                                       */
   /*                                                                       */
   /* <Description>                                                         */
-  /*    Computes the square root of a 16.16 fixed point value.             */
+  /*    Computes the square root of a 16.16 fixed-point value.             */
   /*                                                                       */
   /* <Input>                                                               */
   /*    x :: The value to compute the root for.                            */
@@ -48,29 +48,6 @@
   FT_SqrtFixed( FT_Int32  x );
 
 
-#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    FT_Sqrt32                                                          */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Computes the square root of an Int32 integer (which will be        */
-  /*    handled as an unsigned long value).                                */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    x :: The value to compute the root for.                            */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    The result of `sqrt(x)'.                                           */
-  /*                                                                       */
-  FT_EXPORT( FT_Int32 )
-  FT_Sqrt32( FT_Int32  x );
-
-#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
-
-
   /*************************************************************************/
   /*                                                                       */
   /* FT_MulDiv() and FT_MulFix() are declared in freetype.h.               */
@@ -78,8 +55,6 @@
   /*************************************************************************/
 
 
-#ifdef TT_USE_BYTECODE_INTERPRETER
-
   /*************************************************************************/
   /*                                                                       */
   /* <Function>                                                            */
@@ -87,7 +62,7 @@
   /*                                                                       */
   /* <Description>                                                         */
   /*    A very simple function used to perform the computation `(a*b)/c'   */
-  /*    (without rounding) with maximal accuracy (it uses a 64-bit         */
+  /*    (without rounding) with maximum accuracy (it uses a 64-bit         */
   /*    intermediate integer whenever necessary).                          */
   /*                                                                       */
   /*    This function isn't necessarily as fast as some processor specific */
@@ -108,8 +83,6 @@
                       FT_Long  b,
                       FT_Long  c );
 
-#endif /* TT_USE_BYTECODE_INTERPRETER */
-
 
   /*
    *  A variant of FT_Matrix_Multiply which scales its result afterwards.
@@ -129,7 +102,6 @@
    *  A variant of FT_Vector_Transform.  See comments for
    *  FT_Matrix_Multiply_Scaled.
    */
-
   FT_BASE( void )
   FT_Vector_Transform_Scaled( FT_Vector*        vector,
                               const FT_Matrix*  matrix,
@@ -160,6 +132,22 @@
                      FT_Pos  out_y );
 
 
+  /*
+   *  Return the most significant bit index.
+   */
+  FT_BASE( FT_Int )
+  FT_MSB( FT_UInt32  z );
+
+
+  /*
+   *  Return sqrt(x*x+y*y), which is the same as `FT_Vector_Length' but uses
+   *  two fixed-point arguments instead.
+   */
+  FT_BASE( FT_Fixed )
+  FT_Hypot( FT_Fixed  x,
+            FT_Fixed  y );
+
+
 #define INT_TO_F26DOT6( x )    ( (FT_Long)(x) << 6  )
 #define INT_TO_F2DOT14( x )    ( (FT_Long)(x) << 14 )
 #define INT_TO_FIXED( x )      ( (FT_Long)(x) << 16 )
diff --git a/include/freetype/internal/ftdebug.h b/include/freetype/internal/ftdebug.h
index 7baae35..1ee120f 100644
--- a/include/freetype/internal/ftdebug.h
+++ b/include/freetype/internal/ftdebug.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Debugging and logging component (specification).                     */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2004, 2006, 2007, 2008, 2009 by             */
+/*  Copyright 1996-2002, 2004, 2006-2009, 2013 by                          */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -185,7 +185,8 @@
 
   /*************************************************************************/
   /*                                                                       */
-  /* Define the FT_ASSERT macro.                                           */
+  /* Define the FT_ASSERT and FT_THROW macros.  The call to `FT_Throw'     */
+  /* makes it possible to easily set a breakpoint at this function.        */
   /*                                                                       */
   /*************************************************************************/
 
@@ -199,10 +200,18 @@
                         __LINE__, __FILE__ );                       \
           } while ( 0 )
 
+#define FT_THROW( e )                                   \
+          ( FT_Throw( FT_ERR_CAT( FT_ERR_PREFIX, e ),   \
+                      __LINE__,                         \
+                      __FILE__ )                      | \
+            FT_ERR_CAT( FT_ERR_PREFIX, e )            )
+
 #else /* !FT_DEBUG_LEVEL_ERROR */
 
 #define FT_ASSERT( condition )  do { } while ( 0 )
 
+#define FT_THROW( e )  FT_ERR_CAT( FT_ERR_PREFIX, e )
+
 #endif /* !FT_DEBUG_LEVEL_ERROR */
 
 
@@ -226,6 +235,12 @@
   FT_Panic( const char*  fmt,
             ... );
 
+  /* report file name and line number of an error */
+  FT_BASE( int )
+  FT_Throw( FT_Error     error,
+            int          line,
+            const char*  file );
+
 #endif /* FT_DEBUG_LEVEL_ERROR */
 
 
@@ -233,15 +248,6 @@
   ft_debug_init( void );
 
 
-#if defined( _MSC_VER )      /* Visual C++ (and Intel C++) */
-
-  /* We disable the warning `conditional expression is constant' here */
-  /* in order to compile cleanly with the maximum level of warnings.  */
-#pragma warning( disable : 4127 )
-
-#endif /* _MSC_VER */
-
-
 FT_END_HEADER
 
 #endif /* __FTDEBUG_H__ */
diff --git a/include/freetype/internal/ftdriver.h b/include/freetype/internal/ftdriver.h
index 6f6b206..940218e 100644
--- a/include/freetype/internal/ftdriver.h
+++ b/include/freetype/internal/ftdriver.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType font driver interface (specification).                      */
 /*                                                                         */
-/*  Copyright 1996-2003, 2006, 2008, 2011 by                               */
+/*  Copyright 1996-2003, 2006, 2008, 2011-2013 by                          */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -60,22 +60,6 @@
   (*FT_Size_SelectFunc)( FT_Size   size,
                          FT_ULong  size_index );
 
-#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
-
-  typedef FT_Error
-  (*FT_Size_ResetPointsFunc)( FT_Size     size,
-                              FT_F26Dot6  char_width,
-                              FT_F26Dot6  char_height,
-                              FT_UInt     horz_resolution,
-                              FT_UInt     vert_resolution );
-
-  typedef FT_Error
-  (*FT_Size_ResetPixelsFunc)( FT_Size  size,
-                              FT_UInt  pixel_width,
-                              FT_UInt  pixel_height );
-
-#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
-
   typedef FT_Error
   (*FT_Slot_LoadFunc)( FT_GlyphSlot  slot,
                        FT_Size       size,
@@ -181,72 +165,42 @@
   /*                                                                       */
   typedef struct  FT_Driver_ClassRec_
   {
-    FT_Module_Class           root;
+    FT_Module_Class          root;
 
-    FT_Long                   face_object_size;
-    FT_Long                   size_object_size;
-    FT_Long                   slot_object_size;
+    FT_Long                  face_object_size;
+    FT_Long                  size_object_size;
+    FT_Long                  slot_object_size;
 
-    FT_Face_InitFunc          init_face;
-    FT_Face_DoneFunc          done_face;
+    FT_Face_InitFunc         init_face;
+    FT_Face_DoneFunc         done_face;
 
-    FT_Size_InitFunc          init_size;
-    FT_Size_DoneFunc          done_size;
+    FT_Size_InitFunc         init_size;
+    FT_Size_DoneFunc         done_size;
 
-    FT_Slot_InitFunc          init_slot;
-    FT_Slot_DoneFunc          done_slot;
+    FT_Slot_InitFunc         init_slot;
+    FT_Slot_DoneFunc         done_slot;
 
-#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+    FT_Slot_LoadFunc         load_glyph;
 
-    FT_Size_ResetPointsFunc   set_char_sizes;
-    FT_Size_ResetPixelsFunc   set_pixel_sizes;
-
-#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
-
-    FT_Slot_LoadFunc          load_glyph;
-
-    FT_Face_GetKerningFunc    get_kerning;
-    FT_Face_AttachFunc        attach_file;
-    FT_Face_GetAdvancesFunc   get_advances;
+    FT_Face_GetKerningFunc   get_kerning;
+    FT_Face_AttachFunc       attach_file;
+    FT_Face_GetAdvancesFunc  get_advances;
 
     /* since version 2.2 */
-    FT_Size_RequestFunc       request_size;
-    FT_Size_SelectFunc        select_size;
+    FT_Size_RequestFunc      request_size;
+    FT_Size_SelectFunc       select_size;
 
   } FT_Driver_ClassRec, *FT_Driver_Class;
 
 
-  /*
-   *  The following functions are used as stubs for `set_char_sizes' and
-   *  `set_pixel_sizes'; the code uses `request_size' and `select_size'
-   *  functions instead.
-   *
-   *  Implementation is in `src/base/ftobjs.c'.
-   */
-#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
-
-  FT_BASE( FT_Error )
-  ft_stub_set_char_sizes( FT_Size     size,
-                          FT_F26Dot6  width,
-                          FT_F26Dot6  height,
-                          FT_UInt     horz_res,
-                          FT_UInt     vert_res );
-
-  FT_BASE( FT_Error )
-  ft_stub_set_pixel_sizes( FT_Size  size,
-                           FT_UInt  width,
-                           FT_UInt  height );
-
-#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
-
   /*************************************************************************/
   /*                                                                       */
   /* <Macro>                                                               */
   /*    FT_DECLARE_DRIVER                                                  */
   /*                                                                       */
   /* <Description>                                                         */
-  /*    Used to create a forward declaration of a                          */
-  /*    FT_Driver_ClassRec stract instance.                                */
+  /*    Used to create a forward declaration of an FT_Driver_ClassRec      */
+  /*    struct instance.                                                   */
   /*                                                                       */
   /* <Macro>                                                               */
   /*    FT_DEFINE_DRIVER                                                   */
@@ -254,160 +208,194 @@
   /* <Description>                                                         */
   /*    Used to initialize an instance of FT_Driver_ClassRec struct.       */
   /*                                                                       */
-  /*    When FT_CONFIG_OPTION_PIC is defined a Create funtion will need    */
-  /*    to called with a pointer where the allocated stracture is returned.*/
-  /*    And when it is no longer needed a Destroy function needs           */
-  /*    to be called to release that allocation.                           */
-  /*    fcinit.c (ft_create_default_module_classes) already contains       */
-  /*    a mechanism to call these functions for the default modules        */
-  /*    described in ftmodule.h                                            */
+  /*    When FT_CONFIG_OPTION_PIC is defined a `create' function has to be */
+  /*    called with a pointer where the allocated structure is returned.   */
+  /*    And when it is no longer needed a `destroy' function needs to be   */
+  /*    called to release that allocation.                                 */
   /*                                                                       */
-  /*    Notice that the created Create and Destroy functions call          */
-  /*    pic_init and pic_free function to allow you to manually allocate   */
-  /*    and initialize any additional global data, like module specific    */
+  /*    `fcinit.c' (ft_create_default_module_classes) already contains a   */
+  /*    mechanism to call these functions for the default modules          */
+  /*    described in `ftmodule.h'.                                         */
+  /*                                                                       */
+  /*    Notice that the created `create' and `destroy' functions call      */
+  /*    `pic_init' and `pic_free' to allow you to manually allocate and    */
+  /*    initialize any additional global data, like a module specific      */
   /*    interface, and put them in the global pic container defined in     */
-  /*    ftpic.h. if you don't need them just implement the functions as    */
-  /*    empty to resolve the link error.  Also the pic_init and pic_free   */
-  /*    functions should be declared in pic.h, to be referred by driver    */
-  /*    definition calling FT_DEFINE_DRIVER() in following.                */
+  /*    `ftpic.h'.  If you don't need them just implement the functions as */
+  /*    empty to resolve the link error.  Also the `pic_init' and          */
+  /*    `pic_free' functions should be declared in `pic.h', to be referred */
+  /*    by driver definition calling `FT_DEFINE_DRIVER' in following.      */
   /*                                                                       */
   /*    When FT_CONFIG_OPTION_PIC is not defined the struct will be        */
-  /*    allocated in the global scope (or the scope where the macro        */
-  /*    is used).                                                          */
+  /*    allocated in the global scope (or the scope where the macro is     */
+  /*    used).                                                             */
   /*                                                                       */
 #ifndef FT_CONFIG_OPTION_PIC
 
-#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
-#define FT_DEFINE_DRIVERS_OLD_INTERNALS(a_,b_) \
-  a_, b_,
-#else
-  #define FT_DEFINE_DRIVERS_OLD_INTERNALS(a_,b_)
-#endif
-
-#define FT_DECLARE_DRIVER(class_)    \
+#define FT_DECLARE_DRIVER( class_ )  \
   FT_CALLBACK_TABLE                  \
   const FT_Driver_ClassRec  class_;
 
-#define FT_DEFINE_DRIVER(class_,                                             \
-                         flags_, size_, name_, version_, requires_,          \
-                         interface_, init_, done_, get_interface_,           \
-                         face_object_size_, size_object_size_,               \
-                         slot_object_size_, init_face_, done_face_,          \
-                         init_size_, done_size_, init_slot_, done_slot_,     \
-                         old_set_char_sizes_, old_set_pixel_sizes_,          \
-                         load_glyph_, get_kerning_, attach_file_,            \
-                         get_advances_, request_size_, select_size_ )        \
-  FT_CALLBACK_TABLE_DEF                                                      \
-  const FT_Driver_ClassRec class_ =                                          \
-  {                                                                          \
-    FT_DEFINE_ROOT_MODULE(flags_,size_,name_,version_,requires_,interface_,  \
-                          init_,done_,get_interface_)                        \
-                                                                             \
-    face_object_size_,                                                       \
-    size_object_size_,                                                       \
-    slot_object_size_,                                                       \
-                                                                             \
-    init_face_,                                                              \
-    done_face_,                                                              \
-                                                                             \
-    init_size_,                                                              \
-    done_size_,                                                              \
-                                                                             \
-    init_slot_,                                                              \
-    done_slot_,                                                              \
-                                                                             \
-    FT_DEFINE_DRIVERS_OLD_INTERNALS(old_set_char_sizes_, old_set_pixel_sizes_) \
-                                                                             \
-    load_glyph_,                                                             \
-                                                                             \
-    get_kerning_,                                                            \
-    attach_file_,                                                            \
-    get_advances_,                                                           \
-                                                                             \
-    request_size_,                                                           \
-    select_size_                                                             \
+#define FT_DEFINE_DRIVER(                    \
+          class_,                            \
+          flags_,                            \
+          size_,                             \
+          name_,                             \
+          version_,                          \
+          requires_,                         \
+          interface_,                        \
+          init_,                             \
+          done_,                             \
+          get_interface_,                    \
+          face_object_size_,                 \
+          size_object_size_,                 \
+          slot_object_size_,                 \
+          init_face_,                        \
+          done_face_,                        \
+          init_size_,                        \
+          done_size_,                        \
+          init_slot_,                        \
+          done_slot_,                        \
+          load_glyph_,                       \
+          get_kerning_,                      \
+          attach_file_,                      \
+          get_advances_,                     \
+          request_size_,                     \
+          select_size_ )                     \
+  FT_CALLBACK_TABLE_DEF                      \
+  const FT_Driver_ClassRec  class_ =         \
+  {                                          \
+    FT_DEFINE_ROOT_MODULE( flags_,           \
+                           size_,            \
+                           name_,            \
+                           version_,         \
+                           requires_,        \
+                           interface_,       \
+                           init_,            \
+                           done_,            \
+                           get_interface_ )  \
+                                             \
+    face_object_size_,                       \
+    size_object_size_,                       \
+    slot_object_size_,                       \
+                                             \
+    init_face_,                              \
+    done_face_,                              \
+                                             \
+    init_size_,                              \
+    done_size_,                              \
+                                             \
+    init_slot_,                              \
+    done_slot_,                              \
+                                             \
+    load_glyph_,                             \
+                                             \
+    get_kerning_,                            \
+    attach_file_,                            \
+    get_advances_,                           \
+                                             \
+    request_size_,                           \
+    select_size_                             \
   };
 
 #else /* FT_CONFIG_OPTION_PIC */
 
-#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
-#define FT_DEFINE_DRIVERS_OLD_INTERNALS(a_,b_) \
-  clazz->set_char_sizes = a_; \
-  clazz->set_pixel_sizes = b_;
-#else
-  #define FT_DEFINE_DRIVERS_OLD_INTERNALS(a_,b_)
-#endif
+#define FT_DECLARE_DRIVER( class_ )  FT_DECLARE_MODULE( class_ )
 
-#define FT_DECLARE_DRIVER(class_)    FT_DECLARE_MODULE(class_)
-
-#define FT_DEFINE_DRIVER(class_,                                             \
-                         flags_, size_, name_, version_, requires_,          \
-                         interface_, init_, done_, get_interface_,           \
-                         face_object_size_, size_object_size_,               \
-                         slot_object_size_, init_face_, done_face_,          \
-                         init_size_, done_size_, init_slot_, done_slot_,     \
-                         old_set_char_sizes_, old_set_pixel_sizes_,          \
-                         load_glyph_, get_kerning_, attach_file_,            \
-                         get_advances_, request_size_, select_size_ )        \
-                                                                             \
-  void                                                                       \
-  FT_Destroy_Class_##class_( FT_Library        library,                      \
-                             FT_Module_Class*  clazz )                       \
-  {                                                                          \
-    FT_Memory       memory = library->memory;                                \
-    FT_Driver_Class dclazz = (FT_Driver_Class)clazz;                         \
-    class_##_pic_free( library );                                            \
-    if ( dclazz )                                                            \
-      FT_FREE( dclazz );                                                     \
-  }                                                                          \
-                                                                             \
-  FT_Error                                                                   \
-  FT_Create_Class_##class_( FT_Library        library,                       \
-                            FT_Module_Class**  output_class )                \
-  {                                                                          \
-    FT_Driver_Class  clazz;                                                  \
-    FT_Error         error;                                                  \
-    FT_Memory        memory = library->memory;                               \
-                                                                             \
-    if ( FT_ALLOC( clazz, sizeof(*clazz) ) )                                 \
-      return error;                                                          \
-                                                                             \
-    error = class_##_pic_init( library );                                    \
-    if(error)                                                                \
-    {                                                                        \
-      FT_FREE( clazz );                                                      \
-      return error;                                                          \
-    }                                                                        \
-                                                                             \
-    FT_DEFINE_ROOT_MODULE(flags_,size_,name_,version_,requires_,interface_,  \
-                          init_,done_,get_interface_)                        \
-                                                                             \
-    clazz->face_object_size    = face_object_size_;                          \
-    clazz->size_object_size    = size_object_size_;                          \
-    clazz->slot_object_size    = slot_object_size_;                          \
-                                                                             \
-    clazz->init_face           = init_face_;                                 \
-    clazz->done_face           = done_face_;                                 \
-                                                                             \
-    clazz->init_size           = init_size_;                                 \
-    clazz->done_size           = done_size_;                                 \
-                                                                             \
-    clazz->init_slot           = init_slot_;                                 \
-    clazz->done_slot           = done_slot_;                                 \
-                                                                             \
-    FT_DEFINE_DRIVERS_OLD_INTERNALS(old_set_char_sizes_, old_set_pixel_sizes_) \
-                                                                             \
-    clazz->load_glyph          = load_glyph_;                                \
-                                                                             \
-    clazz->get_kerning         = get_kerning_;                               \
-    clazz->attach_file         = attach_file_;                               \
-    clazz->get_advances        = get_advances_;                              \
-                                                                             \
-    clazz->request_size        = request_size_;                              \
-    clazz->select_size         = select_size_;                               \
-                                                                             \
-    *output_class = (FT_Module_Class*)clazz;                                 \
-    return FT_Err_Ok;                                                        \
+#define FT_DEFINE_DRIVER(                                        \
+          class_,                                                \
+          flags_,                                                \
+          size_,                                                 \
+          name_,                                                 \
+          version_,                                              \
+          requires_,                                             \
+          interface_,                                            \
+          init_,                                                 \
+          done_,                                                 \
+          get_interface_,                                        \
+          face_object_size_,                                     \
+          size_object_size_,                                     \
+          slot_object_size_,                                     \
+          init_face_,                                            \
+          done_face_,                                            \
+          init_size_,                                            \
+          done_size_,                                            \
+          init_slot_,                                            \
+          done_slot_,                                            \
+          load_glyph_,                                           \
+          get_kerning_,                                          \
+          attach_file_,                                          \
+          get_advances_,                                         \
+          request_size_,                                         \
+          select_size_ )                                         \
+  void                                                           \
+  FT_Destroy_Class_ ## class_( FT_Library        library,        \
+                               FT_Module_Class*  clazz )         \
+  {                                                              \
+    FT_Memory        memory = library->memory;                   \
+    FT_Driver_Class  dclazz = (FT_Driver_Class)clazz;            \
+                                                                 \
+                                                                 \
+    class_ ## _pic_free( library );                              \
+    if ( dclazz )                                                \
+      FT_FREE( dclazz );                                         \
+  }                                                              \
+                                                                 \
+                                                                 \
+  FT_Error                                                       \
+  FT_Create_Class_ ## class_( FT_Library         library,        \
+                              FT_Module_Class**  output_class )  \
+  {                                                              \
+    FT_Driver_Class  clazz  = NULL;                              \
+    FT_Error         error;                                      \
+    FT_Memory        memory = library->memory;                   \
+                                                                 \
+                                                                 \
+    if ( FT_ALLOC( clazz, sizeof ( *clazz ) ) )                  \
+      return error;                                              \
+                                                                 \
+    error = class_ ## _pic_init( library );                      \
+    if ( error )                                                 \
+    {                                                            \
+      FT_FREE( clazz );                                          \
+      return error;                                              \
+    }                                                            \
+                                                                 \
+    FT_DEFINE_ROOT_MODULE( flags_,                               \
+                           size_,                                \
+                           name_,                                \
+                           version_,                             \
+                           requires_,                            \
+                           interface_,                           \
+                           init_,                                \
+                           done_,                                \
+                           get_interface_ )                      \
+                                                                 \
+    clazz->face_object_size = face_object_size_;                 \
+    clazz->size_object_size = size_object_size_;                 \
+    clazz->slot_object_size = slot_object_size_;                 \
+                                                                 \
+    clazz->init_face        = init_face_;                        \
+    clazz->done_face        = done_face_;                        \
+                                                                 \
+    clazz->init_size        = init_size_;                        \
+    clazz->done_size        = done_size_;                        \
+                                                                 \
+    clazz->init_slot        = init_slot_;                        \
+    clazz->done_slot        = done_slot_;                        \
+                                                                 \
+    clazz->load_glyph       = load_glyph_;                       \
+                                                                 \
+    clazz->get_kerning      = get_kerning_;                      \
+    clazz->attach_file      = attach_file_;                      \
+    clazz->get_advances     = get_advances_;                     \
+                                                                 \
+    clazz->request_size     = request_size_;                     \
+    clazz->select_size      = select_size_;                      \
+                                                                 \
+    *output_class = (FT_Module_Class*)clazz;                     \
+                                                                 \
+    return FT_Err_Ok;                                            \
   }
 
 
diff --git a/include/freetype/internal/ftmemory.h b/include/freetype/internal/ftmemory.h
index 026aa63..3d51aee 100644
--- a/include/freetype/internal/ftmemory.h
+++ b/include/freetype/internal/ftmemory.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType memory management macros (specification).               */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2004, 2005, 2006, 2007, 2010 by             */
+/*  Copyright 1996-2002, 2004-2007, 2010, 2013 by                          */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg                       */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -141,8 +141,10 @@
                const void*  P );
 
 
-#define FT_MEM_ALLOC( ptr, size )                                         \
-          FT_ASSIGNP_INNER( ptr, ft_mem_alloc( memory, (size), &error ) )
+#define FT_MEM_ALLOC( ptr, size )                               \
+          FT_ASSIGNP_INNER( ptr, ft_mem_alloc( memory,          \
+                                               (FT_Long)(size), \
+                                               &error ) )
 
 #define FT_MEM_FREE( ptr )                \
           FT_BEGIN_STMNT                  \
@@ -154,45 +156,60 @@
           FT_MEM_ALLOC( ptr, sizeof ( *(ptr) ) )
 
 #define FT_MEM_REALLOC( ptr, cursz, newsz )                        \
-          FT_ASSIGNP_INNER( ptr, ft_mem_realloc( memory, 1,        \
-                                                 (cursz), (newsz), \
-                                                 (ptr), &error ) )
+          FT_ASSIGNP_INNER( ptr, ft_mem_realloc( memory,           \
+                                                 1,                \
+                                                 (FT_Long)(cursz), \
+                                                 (FT_Long)(newsz), \
+                                                 (ptr),            \
+                                                 &error ) )
 
-#define FT_MEM_QALLOC( ptr, size )                                         \
-          FT_ASSIGNP_INNER( ptr, ft_mem_qalloc( memory, (size), &error ) )
+#define FT_MEM_QALLOC( ptr, size )                               \
+          FT_ASSIGNP_INNER( ptr, ft_mem_qalloc( memory,          \
+                                                (FT_Long)(size), \
+                                                &error ) )
 
 #define FT_MEM_QNEW( ptr )                        \
           FT_MEM_QALLOC( ptr, sizeof ( *(ptr) ) )
 
-#define FT_MEM_QREALLOC( ptr, cursz, newsz )                         \
-          FT_ASSIGNP_INNER( ptr, ft_mem_qrealloc( memory, 1,        \
-                                                  (cursz), (newsz), \
-                                                  (ptr), &error ) )
+#define FT_MEM_QREALLOC( ptr, cursz, newsz )                        \
+          FT_ASSIGNP_INNER( ptr, ft_mem_qrealloc( memory,           \
+                                                  1,                \
+                                                  (FT_Long)(cursz), \
+                                                  (FT_Long)(newsz), \
+                                                  (ptr),            \
+                                                  &error ) )
 
-#define FT_MEM_QRENEW_ARRAY( ptr, cursz, newsz )                             \
-          FT_ASSIGNP_INNER( ptr, ft_mem_qrealloc( memory, sizeof ( *(ptr) ), \
-                                                  (cursz), (newsz),          \
-                                                  (ptr), &error ) )
+#define FT_MEM_ALLOC_MULT( ptr, count, item_size )                     \
+          FT_ASSIGNP_INNER( ptr, ft_mem_realloc( memory,               \
+                                                 (FT_Long)(item_size), \
+                                                 0,                    \
+                                                 (FT_Long)(count),     \
+                                                 NULL,                 \
+                                                 &error ) )
 
-#define FT_MEM_ALLOC_MULT( ptr, count, item_size )                    \
-          FT_ASSIGNP_INNER( ptr, ft_mem_realloc( memory, (item_size), \
-                                                 0, (count),          \
-                                                 NULL, &error ) )
+#define FT_MEM_REALLOC_MULT( ptr, oldcnt, newcnt, itmsz )           \
+          FT_ASSIGNP_INNER( ptr, ft_mem_realloc( memory,            \
+                                                 (FT_Long)(itmsz),  \
+                                                 (FT_Long)(oldcnt), \
+                                                 (FT_Long)(newcnt), \
+                                                 (ptr),             \
+                                                 &error ) )
 
-#define FT_MEM_REALLOC_MULT( ptr, oldcnt, newcnt, itmsz )            \
-          FT_ASSIGNP_INNER( ptr, ft_mem_realloc( memory, (itmsz),    \
-                                                 (oldcnt), (newcnt), \
-                                                 (ptr), &error ) )
+#define FT_MEM_QALLOC_MULT( ptr, count, item_size )                     \
+          FT_ASSIGNP_INNER( ptr, ft_mem_qrealloc( memory,               \
+                                                  (FT_Long)(item_size), \
+                                                  0,                    \
+                                                  (FT_Long)(count),     \
+                                                  NULL,                 \
+                                                  &error ) )
 
-#define FT_MEM_QALLOC_MULT( ptr, count, item_size )                    \
-          FT_ASSIGNP_INNER( ptr, ft_mem_qrealloc( memory, (item_size), \
-                                                  0, (count),          \
-                                                  NULL, &error ) )
-
-#define FT_MEM_QREALLOC_MULT( ptr, oldcnt, newcnt, itmsz)             \
-          FT_ASSIGNP_INNER( ptr, ft_mem_qrealloc( memory, (itmsz),    \
-                                                  (oldcnt), (newcnt), \
-                                                  (ptr), &error ) )
+#define FT_MEM_QREALLOC_MULT( ptr, oldcnt, newcnt, itmsz)            \
+          FT_ASSIGNP_INNER( ptr, ft_mem_qrealloc( memory,            \
+                                                  (FT_Long)(itmsz),  \
+                                                  (FT_Long)(oldcnt), \
+                                                  (FT_Long)(newcnt), \
+                                                  (ptr),             \
+                                                  &error ) )
 
 
 #define FT_MEM_SET_ERROR( cond )  ( (cond), error != 0 )
@@ -236,26 +253,37 @@
   /* _typed_ in order to automatically compute array element sizes.        */
   /*                                                                       */
 
-#define FT_MEM_NEW_ARRAY( ptr, count )                                      \
-          FT_ASSIGNP_INNER( ptr, ft_mem_realloc( memory, sizeof ( *(ptr) ), \
-                                                 0, (count),                \
-                                                 NULL, &error ) )
+#define FT_MEM_NEW_ARRAY( ptr, count )                              \
+          FT_ASSIGNP_INNER( ptr, ft_mem_realloc( memory,            \
+                                                 sizeof ( *(ptr) ), \
+                                                 0,                 \
+                                                 (FT_Long)(count),  \
+                                                 NULL,              \
+                                                 &error ) )
 
-#define FT_MEM_RENEW_ARRAY( ptr, cursz, newsz )                             \
-          FT_ASSIGNP_INNER( ptr, ft_mem_realloc( memory, sizeof ( *(ptr) ), \
-                                                 (cursz), (newsz),          \
-                                                 (ptr), &error ) )
+#define FT_MEM_RENEW_ARRAY( ptr, cursz, newsz )                     \
+          FT_ASSIGNP_INNER( ptr, ft_mem_realloc( memory,            \
+                                                 sizeof ( *(ptr) ), \
+                                                 (FT_Long)(cursz),  \
+                                                 (FT_Long)(newsz),  \
+                                                 (ptr),             \
+                                                 &error ) )
 
-#define FT_MEM_QNEW_ARRAY( ptr, count )                                      \
-          FT_ASSIGNP_INNER( ptr, ft_mem_qrealloc( memory, sizeof ( *(ptr) ), \
-                                                  0, (count),                \
-                                                  NULL, &error ) )
+#define FT_MEM_QNEW_ARRAY( ptr, count )                              \
+          FT_ASSIGNP_INNER( ptr, ft_mem_qrealloc( memory,            \
+                                                  sizeof ( *(ptr) ), \
+                                                  0,                 \
+                                                  (FT_Long)(count),  \
+                                                  NULL,              \
+                                                  &error ) )
 
-#define FT_MEM_QRENEW_ARRAY( ptr, cursz, newsz )                             \
-          FT_ASSIGNP_INNER( ptr, ft_mem_qrealloc( memory, sizeof ( *(ptr) ), \
-                                                  (cursz), (newsz),          \
-                                                  (ptr), &error ) )
-
+#define FT_MEM_QRENEW_ARRAY( ptr, cursz, newsz )                     \
+          FT_ASSIGNP_INNER( ptr, ft_mem_qrealloc( memory,            \
+                                                  sizeof ( *(ptr) ), \
+                                                  (FT_Long)(cursz),  \
+                                                  (FT_Long)(newsz),  \
+                                                  (ptr),             \
+                                                  &error ) )
 
 #define FT_ALLOC( ptr, size )                           \
           FT_MEM_SET_ERROR( FT_MEM_ALLOC( ptr, size ) )
@@ -303,37 +331,6 @@
           FT_MEM_SET_ERROR( FT_MEM_RENEW_ARRAY( ptr, curcnt, newcnt ) )
 
 
-#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
-
-  FT_BASE( FT_Error )
-  FT_Alloc( FT_Memory  memory,
-            FT_Long    size,
-            void*     *P );
-
-  FT_BASE( FT_Error )
-  FT_QAlloc( FT_Memory  memory,
-             FT_Long    size,
-             void*     *p );
-
-  FT_BASE( FT_Error )
-  FT_Realloc( FT_Memory  memory,
-              FT_Long    current,
-              FT_Long    size,
-              void*     *P );
-
-  FT_BASE( FT_Error )
-  FT_QRealloc( FT_Memory  memory,
-               FT_Long    current,
-               FT_Long    size,
-               void*     *p );
-
-  FT_BASE( void )
-  FT_Free( FT_Memory  memory,
-           void*     *P );
-
-#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
-
-
   FT_BASE( FT_Pointer )
   ft_mem_strdup( FT_Memory    memory,
                  const char*  str,
@@ -345,6 +342,7 @@
               FT_ULong     size,
               FT_Error    *p_error );
 
+
 #define FT_MEM_STRDUP( dst, str )                                            \
           (dst) = (char*)ft_mem_strdup( memory, (const char*)(str), &error )
 
diff --git a/include/freetype/internal/ftobjs.h b/include/freetype/internal/ftobjs.h
index fc18275..8a309b8 100644
--- a/include/freetype/internal/ftobjs.h
+++ b/include/freetype/internal/ftobjs.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType private base classes (specification).                   */
 /*                                                                         */
-/*  Copyright 1996-2006, 2008, 2010, 2012 by                               */
+/*  Copyright 1996-2006, 2008, 2010, 2012-2013 by                          */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -206,46 +206,79 @@
 
   } FT_CMap_ClassRec;
 
+
 #ifndef FT_CONFIG_OPTION_PIC
 
-#define FT_DECLARE_CMAP_CLASS(class_) \
-    FT_CALLBACK_TABLE const FT_CMap_ClassRec class_;
+#define FT_DECLARE_CMAP_CLASS( class_ )              \
+  FT_CALLBACK_TABLE const  FT_CMap_ClassRec class_;
 
-#define FT_DEFINE_CMAP_CLASS(class_, size_, init_, done_, char_index_,       \
-        char_next_, char_var_index_, char_var_default_, variant_list_,       \
-        charvariant_list_, variantchar_list_)                                \
-  FT_CALLBACK_TABLE_DEF                                                      \
-  const FT_CMap_ClassRec class_ =                                            \
-  {                                                                          \
-    size_, init_, done_, char_index_, char_next_, char_var_index_,           \
-    char_var_default_, variant_list_, charvariant_list_, variantchar_list_   \
+#define FT_DEFINE_CMAP_CLASS(       \
+          class_,                   \
+          size_,                    \
+          init_,                    \
+          done_,                    \
+          char_index_,              \
+          char_next_,               \
+          char_var_index_,          \
+          char_var_default_,        \
+          variant_list_,            \
+          charvariant_list_,        \
+          variantchar_list_ )       \
+  FT_CALLBACK_TABLE_DEF             \
+  const FT_CMap_ClassRec  class_ =  \
+  {                                 \
+    size_,                          \
+    init_,                          \
+    done_,                          \
+    char_index_,                    \
+    char_next_,                     \
+    char_var_index_,                \
+    char_var_default_,              \
+    variant_list_,                  \
+    charvariant_list_,              \
+    variantchar_list_               \
   };
+
 #else /* FT_CONFIG_OPTION_PIC */
 
-#define FT_DECLARE_CMAP_CLASS(class_) \
-    void FT_Init_Class_##class_( FT_Library library, FT_CMap_ClassRec*  clazz);
+#define FT_DECLARE_CMAP_CLASS( class_ )                  \
+  void                                                   \
+  FT_Init_Class_ ## class_( FT_Library         library,  \
+                            FT_CMap_ClassRec*  clazz );
 
-#define FT_DEFINE_CMAP_CLASS(class_, size_, init_, done_, char_index_,       \
-        char_next_, char_var_index_, char_var_default_, variant_list_,       \
-        charvariant_list_, variantchar_list_)                                \
-  void                                                                       \
-  FT_Init_Class_##class_( FT_Library library,                                \
-                          FT_CMap_ClassRec*  clazz)                          \
-  {                                                                          \
-    FT_UNUSED(library);                                                      \
-    clazz->size = size_;                                                     \
-    clazz->init = init_;                                                     \
-    clazz->done = done_;                                                     \
-    clazz->char_index = char_index_;                                         \
-    clazz->char_next = char_next_;                                           \
-    clazz->char_var_index = char_var_index_;                                 \
-    clazz->char_var_default = char_var_default_;                             \
-    clazz->variant_list = variant_list_;                                     \
-    clazz->charvariant_list = charvariant_list_;                             \
-    clazz->variantchar_list = variantchar_list_;                             \
+#define FT_DEFINE_CMAP_CLASS(                            \
+          class_,                                        \
+          size_,                                         \
+          init_,                                         \
+          done_,                                         \
+          char_index_,                                   \
+          char_next_,                                    \
+          char_var_index_,                               \
+          char_var_default_,                             \
+          variant_list_,                                 \
+          charvariant_list_,                             \
+          variantchar_list_ )                            \
+  void                                                   \
+  FT_Init_Class_ ## class_( FT_Library         library,  \
+                            FT_CMap_ClassRec*  clazz )   \
+  {                                                      \
+    FT_UNUSED( library );                                \
+                                                         \
+    clazz->size             = size_;                     \
+    clazz->init             = init_;                     \
+    clazz->done             = done_;                     \
+    clazz->char_index       = char_index_;               \
+    clazz->char_next        = char_next_;                \
+    clazz->char_var_index   = char_var_index_;           \
+    clazz->char_var_default = char_var_default_;         \
+    clazz->variant_list     = variant_list_;             \
+    clazz->charvariant_list = charvariant_list_;         \
+    clazz->variantchar_list = variantchar_list_;         \
   }
+
 #endif /* FT_CONFIG_OPTION_PIC */
 
+
   /* create a new charmap and add it to charmap->face */
   FT_BASE( FT_Error )
   FT_CMap_New( FT_CMap_Class  clazz,
@@ -270,13 +303,13 @@
   /*                                                                       */
   /* <Fields>                                                              */
   /*    max_points ::                                                      */
-  /*      The maximal number of points used to store the vectorial outline */
+  /*      The maximum number of points used to store the vectorial outline */
   /*      of any glyph in this face.  If this value cannot be known in     */
   /*      advance, or if the face isn't scalable, this should be set to 0. */
   /*      Only relevant for scalable formats.                              */
   /*                                                                       */
   /*    max_contours ::                                                    */
-  /*      The maximal number of contours used to store the vectorial       */
+  /*      The maximum number of contours used to store the vectorial       */
   /*      outline of any glyph in this face.  If this value cannot be      */
   /*      known in advance, or if the face isn't scalable, this should be  */
   /*      set to 0.  Only relevant for scalable formats.                   */
@@ -319,10 +352,6 @@
   /*                                                                       */
   typedef struct  FT_Face_InternalRec_
   {
-#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
-    FT_UShort           reserved1;
-    FT_Short            reserved2;
-#endif
     FT_Matrix           transform_matrix;
     FT_Vector           transform_delta;
     FT_Int              transform_flags;
@@ -411,6 +440,7 @@
 
   /*************************************************************************/
   /*************************************************************************/
+  /*************************************************************************/
   /****                                                                 ****/
   /****                                                                 ****/
   /****                         M O D U L E S                           ****/
@@ -503,7 +533,7 @@
   ft_module_get_service( FT_Module    module,
                          const char*  service_id );
 
- /* */
+  /* */
 
 
   /*************************************************************************/
@@ -511,7 +541,7 @@
   /*************************************************************************/
   /****                                                                 ****/
   /****                                                                 ****/
-  /****               FACE, SIZE & GLYPH SLOT OBJECTS                   ****/
+  /****   F A C E,   S I Z E   &   G L Y P H   S L O T   O B J E C T S  ****/
   /****                                                                 ****/
   /****                                                                 ****/
   /*************************************************************************/
@@ -926,12 +956,13 @@
   FT_EXPORT_VAR( FT_Raster_Funcs )  ft_default_raster;
 #endif
 
+
   /*************************************************************************/
   /*************************************************************************/
   /*************************************************************************/
   /****                                                                 ****/
   /****                                                                 ****/
-  /****              PIC-Support Macros for ftimage.h                   ****/
+  /****                      P I C   S U P P O R T                      ****/
   /****                                                                 ****/
   /****                                                                 ****/
   /*************************************************************************/
@@ -939,6 +970,9 @@
   /*************************************************************************/
 
 
+  /* PIC support macros for ftimage.h */
+
+
   /*************************************************************************/
   /*                                                                       */
   /* <Macro>                                                               */
@@ -947,38 +981,57 @@
   /* <Description>                                                         */
   /*    Used to initialize an instance of FT_Outline_Funcs struct.         */
   /*    When FT_CONFIG_OPTION_PIC is defined an init funtion will need to  */
-  /*    called with a pre-allocated stracture to be filled.                */
+  /*    be called with a pre-allocated structure to be filled.             */
   /*    When FT_CONFIG_OPTION_PIC is not defined the struct will be        */
   /*    allocated in the global scope (or the scope where the macro        */
   /*    is used).                                                          */
   /*                                                                       */
 #ifndef FT_CONFIG_OPTION_PIC
 
-#define FT_DEFINE_OUTLINE_FUNCS(class_, move_to_, line_to_, conic_to_,       \
-                                cubic_to_, shift_, delta_)                   \
-  static const FT_Outline_Funcs class_ =                                     \
-  {                                                                          \
-    move_to_, line_to_, conic_to_, cubic_to_, shift_, delta_                 \
+#define FT_DEFINE_OUTLINE_FUNCS(           \
+          class_,                          \
+          move_to_,                        \
+          line_to_,                        \
+          conic_to_,                       \
+          cubic_to_,                       \
+          shift_,                          \
+          delta_ )                         \
+  static const  FT_Outline_Funcs class_ =  \
+  {                                        \
+    move_to_,                              \
+    line_to_,                              \
+    conic_to_,                             \
+    cubic_to_,                             \
+    shift_,                                \
+    delta_                                 \
   };
 
 #else /* FT_CONFIG_OPTION_PIC */
 
-#define FT_DEFINE_OUTLINE_FUNCS(class_, move_to_, line_to_, conic_to_,       \
-                                cubic_to_, shift_, delta_)                   \
-  static FT_Error                                                            \
-  Init_Class_##class_( FT_Outline_Funcs*  clazz )                            \
-  {                                                                          \
-    clazz->move_to = move_to_;                                               \
-    clazz->line_to = line_to_;                                               \
-    clazz->conic_to = conic_to_;                                             \
-    clazz->cubic_to = cubic_to_;                                             \
-    clazz->shift = shift_;                                                   \
-    clazz->delta = delta_;                                                   \
-    return FT_Err_Ok;                                                        \
+#define FT_DEFINE_OUTLINE_FUNCS(                     \
+          class_,                                    \
+          move_to_,                                  \
+          line_to_,                                  \
+          conic_to_,                                 \
+          cubic_to_,                                 \
+          shift_,                                    \
+          delta_ )                                   \
+  static FT_Error                                    \
+  Init_Class_ ## class_( FT_Outline_Funcs*  clazz )  \
+  {                                                  \
+    clazz->move_to  = move_to_;                      \
+    clazz->line_to  = line_to_;                      \
+    clazz->conic_to = conic_to_;                     \
+    clazz->cubic_to = cubic_to_;                     \
+    clazz->shift    = shift_;                        \
+    clazz->delta    = delta_;                        \
+                                                     \
+    return FT_Err_Ok;                                \
   }
 
 #endif /* FT_CONFIG_OPTION_PIC */
 
+
   /*************************************************************************/
   /*                                                                       */
   /* <Macro>                                                               */
@@ -987,51 +1040,56 @@
   /* <Description>                                                         */
   /*    Used to initialize an instance of FT_Raster_Funcs struct.          */
   /*    When FT_CONFIG_OPTION_PIC is defined an init funtion will need to  */
-  /*    called with a pre-allocated stracture to be filled.                */
+  /*    be called with a pre-allocated structure to be filled.             */
   /*    When FT_CONFIG_OPTION_PIC is not defined the struct will be        */
   /*    allocated in the global scope (or the scope where the macro        */
   /*    is used).                                                          */
   /*                                                                       */
 #ifndef FT_CONFIG_OPTION_PIC
 
-#define FT_DEFINE_RASTER_FUNCS(class_, glyph_format_, raster_new_,           \
-                               raster_reset_, raster_set_mode_,              \
-                               raster_render_, raster_done_)                 \
-  const FT_Raster_Funcs class_ =                                      \
-  {                                                                          \
-    glyph_format_, raster_new_, raster_reset_,                               \
-    raster_set_mode_, raster_render_, raster_done_                           \
+#define FT_DEFINE_RASTER_FUNCS(    \
+          class_,                  \
+          glyph_format_,           \
+          raster_new_,             \
+          raster_reset_,           \
+          raster_set_mode_,        \
+          raster_render_,          \
+          raster_done_ )           \
+  const FT_Raster_Funcs  class_ =  \
+  {                                \
+    glyph_format_,                 \
+    raster_new_,                   \
+    raster_reset_,                 \
+    raster_set_mode_,              \
+    raster_render_,                \
+    raster_done_                   \
   };
 
 #else /* FT_CONFIG_OPTION_PIC */
 
-#define FT_DEFINE_RASTER_FUNCS(class_, glyph_format_, raster_new_,           \
-    raster_reset_, raster_set_mode_, raster_render_, raster_done_)           \
-  void                                                                       \
-  FT_Init_Class_##class_( FT_Raster_Funcs*  clazz )                          \
-  {                                                                          \
-    clazz->glyph_format = glyph_format_;                                     \
-    clazz->raster_new = raster_new_;                                         \
-    clazz->raster_reset = raster_reset_;                                     \
-    clazz->raster_set_mode = raster_set_mode_;                               \
-    clazz->raster_render = raster_render_;                                   \
-    clazz->raster_done = raster_done_;                                       \
+#define FT_DEFINE_RASTER_FUNCS(                        \
+          class_,                                      \
+          glyph_format_,                               \
+          raster_new_,                                 \
+          raster_reset_,                               \
+          raster_set_mode_,                            \
+          raster_render_,                              \
+          raster_done_ )                               \
+  void                                                 \
+  FT_Init_Class_ ## class_( FT_Raster_Funcs*  clazz )  \
+  {                                                    \
+    clazz->glyph_format    = glyph_format_;            \
+    clazz->raster_new      = raster_new_;              \
+    clazz->raster_reset    = raster_reset_;            \
+    clazz->raster_set_mode = raster_set_mode_;         \
+    clazz->raster_render   = raster_render_;           \
+    clazz->raster_done     = raster_done_;             \
   }
 
 #endif /* FT_CONFIG_OPTION_PIC */
 
-  /*************************************************************************/
-  /*************************************************************************/
-  /*************************************************************************/
-  /****                                                                 ****/
-  /****                                                                 ****/
-  /****              PIC-Support Macros for ftrender.h                  ****/
-  /****                                                                 ****/
-  /****                                                                 ****/
-  /*************************************************************************/
-  /*************************************************************************/
-  /*************************************************************************/
 
+  /* PIC support macros for ftrender.h */
 
 
   /*************************************************************************/
@@ -1042,40 +1100,64 @@
   /* <Description>                                                         */
   /*    Used to initialize an instance of FT_Glyph_Class struct.           */
   /*    When FT_CONFIG_OPTION_PIC is defined an init funtion will need to  */
-  /*    called with a pre-allocated stracture to be filled.                */
+  /*    be called with a pre-allocated stcture to be filled.               */
   /*    When FT_CONFIG_OPTION_PIC is not defined the struct will be        */
   /*    allocated in the global scope (or the scope where the macro        */
   /*    is used).                                                          */
   /*                                                                       */
 #ifndef FT_CONFIG_OPTION_PIC
 
-#define FT_DEFINE_GLYPH(class_, size_, format_, init_, done_, copy_,         \
-                        transform_, bbox_, prepare_)                         \
-  FT_CALLBACK_TABLE_DEF                                                      \
-  const FT_Glyph_Class class_ =                                              \
-  {                                                                          \
-    size_, format_, init_, done_, copy_, transform_, bbox_, prepare_         \
+#define FT_DEFINE_GLYPH(          \
+          class_,                 \
+          size_,                  \
+          format_,                \
+          init_,                  \
+          done_,                  \
+          copy_,                  \
+          transform_,             \
+          bbox_,                  \
+          prepare_ )              \
+  FT_CALLBACK_TABLE_DEF           \
+  const FT_Glyph_Class  class_ =  \
+  {                               \
+    size_,                        \
+    format_,                      \
+    init_,                        \
+    done_,                        \
+    copy_,                        \
+    transform_,                   \
+    bbox_,                        \
+    prepare_                      \
   };
 
 #else /* FT_CONFIG_OPTION_PIC */
 
-#define FT_DEFINE_GLYPH(class_, size_, format_, init_, done_, copy_,         \
-                        transform_, bbox_, prepare_)                         \
-  void                                                                       \
-  FT_Init_Class_##class_( FT_Glyph_Class*  clazz )                           \
-  {                                                                          \
-    clazz->glyph_size = size_;                                               \
-    clazz->glyph_format = format_;                                           \
-    clazz->glyph_init = init_;                                               \
-    clazz->glyph_done = done_;                                               \
-    clazz->glyph_copy = copy_;                                               \
-    clazz->glyph_transform = transform_;                                     \
-    clazz->glyph_bbox = bbox_;                                               \
-    clazz->glyph_prepare = prepare_;                                         \
+#define FT_DEFINE_GLYPH(                              \
+          class_,                                     \
+          size_,                                      \
+          format_,                                    \
+          init_,                                      \
+          done_,                                      \
+          copy_,                                      \
+          transform_,                                 \
+          bbox_,                                      \
+          prepare_ )                                  \
+  void                                                \
+  FT_Init_Class_ ## class_( FT_Glyph_Class*  clazz )  \
+  {                                                   \
+    clazz->glyph_size      = size_;                   \
+    clazz->glyph_format    = format_;                 \
+    clazz->glyph_init      = init_;                   \
+    clazz->glyph_done      = done_;                   \
+    clazz->glyph_copy      = copy_;                   \
+    clazz->glyph_transform = transform_;              \
+    clazz->glyph_bbox      = bbox_;                   \
+    clazz->glyph_prepare   = prepare_;                \
   }
 
 #endif /* FT_CONFIG_OPTION_PIC */
 
+
   /*************************************************************************/
   /*                                                                       */
   /* <Macro>                                                               */
@@ -1083,7 +1165,7 @@
   /*                                                                       */
   /* <Description>                                                         */
   /*    Used to create a forward declaration of a                          */
-  /*    FT_Renderer_Class stract instance.                                 */
+  /*    FT_Renderer_Class struct instance.                                 */
   /*                                                                       */
   /* <Macro>                                                               */
   /*    FT_DEFINE_RENDERER                                                 */
@@ -1091,22 +1173,23 @@
   /* <Description>                                                         */
   /*    Used to initialize an instance of FT_Renderer_Class struct.        */
   /*                                                                       */
-  /*    When FT_CONFIG_OPTION_PIC is defined a Create funtion will need    */
-  /*    to called with a pointer where the allocated stracture is returned.*/
-  /*    And when it is no longer needed a Destroy function needs           */
-  /*    to be called to release that allocation.                           */
-  /*    fcinit.c (ft_create_default_module_classes) already contains       */
+  /*    When FT_CONFIG_OPTION_PIC is defined a `create' funtion will need  */
+  /*    to be called with a pointer where the allocated structure is       */
+  /*    returned.  And when it is no longer needed a `destroy' function    */
+  /*    needs to be called to release that allocation.                     */
+  /*    `fcinit.c' (ft_create_default_module_classes) already contains     */
   /*    a mechanism to call these functions for the default modules        */
-  /*    described in ftmodule.h                                            */
+  /*    described in `ftmodule.h'.                                         */
   /*                                                                       */
-  /*    Notice that the created Create and Destroy functions call          */
-  /*    pic_init and pic_free function to allow you to manually allocate   */
-  /*    and initialize any additional global data, like module specific    */
+  /*    Notice that the created `create' and `destroy' functions call      */
+  /*    `pic_init' and `pic_free' to allow you to manually allocate and    */
+  /*    initialize any additional global data, like a module specific      */
   /*    interface, and put them in the global pic container defined in     */
-  /*    ftpic.h. if you don't need them just implement the functions as    */
-  /*    empty to resolve the link error.  Also the pic_init and pic_free   */
-  /*    functions should be declared in pic.h, to be referred by renderer  */
-  /*    definition calling FT_DEFINE_RENDERER() in following.              */
+  /*    `ftpic.h'.  If you don't need them just implement the functions as */
+  /*    empty to resolve the link error.  Also the `pic_init' and          */
+  /*    `pic_free' functions should be declared in `pic.h', to be referred */
+  /*    by the renderer definition calling `FT_DEFINE_RENDERER' in the     */
+  /*    following.                                                         */
   /*                                                                       */
   /*    When FT_CONFIG_OPTION_PIC is not defined the struct will be        */
   /*    allocated in the global scope (or the scope where the macro        */
@@ -1114,99 +1197,130 @@
   /*                                                                       */
 #ifndef FT_CONFIG_OPTION_PIC
 
-#define FT_DECLARE_RENDERER(class_)                                          \
-    FT_EXPORT_VAR( const FT_Renderer_Class ) class_;
+#define FT_DECLARE_RENDERER( class_ )               \
+  FT_EXPORT_VAR( const FT_Renderer_Class ) class_;
 
-#define FT_DEFINE_RENDERER(class_,                                           \
-                           flags_, size_, name_, version_, requires_,        \
-                           interface_, init_, done_, get_interface_,         \
-                           glyph_format_, render_glyph_, transform_glyph_,   \
-                           get_glyph_cbox_, set_mode_, raster_class_ )       \
-  FT_CALLBACK_TABLE_DEF                                                      \
-  const FT_Renderer_Class  class_ =                                          \
-  {                                                                          \
-    FT_DEFINE_ROOT_MODULE(flags_,size_,name_,version_,requires_,             \
-                          interface_,init_,done_,get_interface_)             \
-    glyph_format_,                                                           \
-                                                                             \
-    render_glyph_,                                                           \
-    transform_glyph_,                                                        \
-    get_glyph_cbox_,                                                         \
-    set_mode_,                                                               \
-                                                                             \
-    raster_class_                                                            \
+#define FT_DEFINE_RENDERER(                  \
+          class_,                            \
+          flags_,                            \
+          size_,                             \
+          name_,                             \
+          version_,                          \
+          requires_,                         \
+          interface_,                        \
+          init_,                             \
+          done_,                             \
+          get_interface_,                    \
+          glyph_format_,                     \
+          render_glyph_,                     \
+          transform_glyph_,                  \
+          get_glyph_cbox_,                   \
+          set_mode_,                         \
+          raster_class_ )                    \
+  FT_CALLBACK_TABLE_DEF                      \
+  const FT_Renderer_Class  class_ =          \
+  {                                          \
+    FT_DEFINE_ROOT_MODULE( flags_,           \
+                           size_,            \
+                           name_,            \
+                           version_,         \
+                           requires_,        \
+                           interface_,       \
+                           init_,            \
+                           done_,            \
+                           get_interface_ )  \
+    glyph_format_,                           \
+                                             \
+    render_glyph_,                           \
+    transform_glyph_,                        \
+    get_glyph_cbox_,                         \
+    set_mode_,                               \
+                                             \
+    raster_class_                            \
   };
 
 #else /* FT_CONFIG_OPTION_PIC */
 
-#define FT_DECLARE_RENDERER(class_)  FT_DECLARE_MODULE(class_)
+#define FT_DECLARE_RENDERER( class_ )  FT_DECLARE_MODULE( class_ )
 
-#define FT_DEFINE_RENDERER(class_, \
-                           flags_, size_, name_, version_, requires_,        \
-                           interface_, init_, done_, get_interface_,         \
-                           glyph_format_, render_glyph_, transform_glyph_,   \
-                           get_glyph_cbox_, set_mode_, raster_class_ )       \
-                                                                             \
-  void                                                                       \
-  FT_Destroy_Class_##class_( FT_Library        library,                      \
-                        FT_Module_Class*  clazz )                            \
-  {                                                                          \
-    FT_Renderer_Class* rclazz = (FT_Renderer_Class*)clazz;                   \
-    FT_Memory         memory = library->memory;                              \
-    class_##_pic_free( library );                                            \
-    if ( rclazz )                                                            \
-      FT_FREE( rclazz );                                                     \
-  }                                                                          \
-                                                                             \
-  FT_Error                                                                   \
-  FT_Create_Class_##class_( FT_Library         library,                      \
-                            FT_Module_Class**  output_class )                \
-  {                                                                          \
-    FT_Renderer_Class*  clazz;                                               \
-    FT_Error            error;                                               \
-    FT_Memory           memory = library->memory;                            \
-                                                                             \
-    if ( FT_ALLOC( clazz, sizeof(*clazz) ) )                                 \
-      return error;                                                          \
-                                                                             \
-    error = class_##_pic_init( library );                                    \
-    if(error)                                                                \
-    {                                                                        \
-      FT_FREE( clazz );                                                      \
-      return error;                                                          \
-    }                                                                        \
-                                                                             \
-    FT_DEFINE_ROOT_MODULE(flags_,size_,name_,version_,requires_,             \
-                          interface_,init_,done_,get_interface_)             \
-                                                                             \
-    clazz->glyph_format       = glyph_format_;                               \
-                                                                             \
-    clazz->render_glyph       = render_glyph_;                               \
-    clazz->transform_glyph    = transform_glyph_;                            \
-    clazz->get_glyph_cbox     = get_glyph_cbox_;                             \
-    clazz->set_mode           = set_mode_;                                   \
-                                                                             \
-    clazz->raster_class       = raster_class_;                               \
-                                                                             \
-    *output_class = (FT_Module_Class*)clazz;                                 \
-    return FT_Err_Ok;                                                        \
+#define FT_DEFINE_RENDERER(                                      \
+          class_,                                                \
+          flags_,                                                \
+          size_,                                                 \
+          name_,                                                 \
+          version_,                                              \
+          requires_,                                             \
+          interface_,                                            \
+          init_,                                                 \
+          done_,                                                 \
+          get_interface_,                                        \
+          glyph_format_,                                         \
+          render_glyph_,                                         \
+          transform_glyph_,                                      \
+          get_glyph_cbox_,                                       \
+          set_mode_,                                             \
+          raster_class_ )                                        \
+  void                                                           \
+  FT_Destroy_Class_ ## class_( FT_Library        library,        \
+                               FT_Module_Class*  clazz )         \
+  {                                                              \
+    FT_Renderer_Class*  rclazz = (FT_Renderer_Class*)clazz;      \
+    FT_Memory           memory = library->memory;                \
+                                                                 \
+                                                                 \
+    class_ ## _pic_free( library );                              \
+    if ( rclazz )                                                \
+      FT_FREE( rclazz );                                         \
+  }                                                              \
+                                                                 \
+                                                                 \
+  FT_Error                                                       \
+  FT_Create_Class_ ## class_( FT_Library         library,        \
+                              FT_Module_Class**  output_class )  \
+  {                                                              \
+    FT_Renderer_Class*  clazz = NULL;                            \
+    FT_Error            error;                                   \
+    FT_Memory           memory = library->memory;                \
+                                                                 \
+                                                                 \
+    if ( FT_ALLOC( clazz, sizeof ( *clazz ) ) )                  \
+      return error;                                              \
+                                                                 \
+    error = class_ ## _pic_init( library );                      \
+    if ( error )                                                 \
+    {                                                            \
+      FT_FREE( clazz );                                          \
+      return error;                                              \
+    }                                                            \
+                                                                 \
+    FT_DEFINE_ROOT_MODULE( flags_,                               \
+                           size_,                                \
+                           name_,                                \
+                           version_,                             \
+                           requires_,                            \
+                           interface_,                           \
+                           init_,                                \
+                           done_,                                \
+                           get_interface_ )                      \
+                                                                 \
+    clazz->glyph_format    = glyph_format_;                      \
+                                                                 \
+    clazz->render_glyph    = render_glyph_;                      \
+    clazz->transform_glyph = transform_glyph_;                   \
+    clazz->get_glyph_cbox  = get_glyph_cbox_;                    \
+    clazz->set_mode        = set_mode_;                          \
+                                                                 \
+    clazz->raster_class    = raster_class_;                      \
+                                                                 \
+    *output_class = (FT_Module_Class*)clazz;                     \
+                                                                 \
+    return FT_Err_Ok;                                            \
   }
 
-
-
 #endif /* FT_CONFIG_OPTION_PIC */
 
-  /*************************************************************************/
-  /*************************************************************************/
-  /*************************************************************************/
-  /****                                                                 ****/
-  /****                                                                 ****/
-  /****              PIC-Support Macros for ftmodapi.h                  ****/
-  /****                                                                 ****/
-  /****                                                                 ****/
-  /*************************************************************************/
-  /*************************************************************************/
-  /*************************************************************************/
+
+  /* PIC support macros for ftmodapi.h **/
 
 
 #ifdef FT_CONFIG_OPTION_PIC
@@ -1247,6 +1361,7 @@
 
 #endif
 
+
   /*************************************************************************/
   /*                                                                       */
   /* <Macro>                                                               */
@@ -1254,30 +1369,31 @@
   /*                                                                       */
   /* <Description>                                                         */
   /*    Used to create a forward declaration of a                          */
-  /*    FT_Module_Class stract instance.                                   */
+  /*    FT_Module_Class struct instance.                                   */
   /*                                                                       */
   /* <Macro>                                                               */
   /*    FT_DEFINE_MODULE                                                   */
   /*                                                                       */
   /* <Description>                                                         */
-  /*    Used to initialize an instance of FT_Module_Class struct.          */
+  /*    Used to initialize an instance of an FT_Module_Class struct.       */
   /*                                                                       */
-  /*    When FT_CONFIG_OPTION_PIC is defined a Create funtion will need    */
-  /*    to called with a pointer where the allocated stracture is returned.*/
-  /*    And when it is no longer needed a Destroy function needs           */
-  /*    to be called to release that allocation.                           */
-  /*    fcinit.c (ft_create_default_module_classes) already contains       */
+  /*    When FT_CONFIG_OPTION_PIC is defined a `create' funtion needs to   */
+  /*    be called with a pointer where the allocated structure is          */
+  /*    returned.  And when it is no longer needed a `destroy' function    */
+  /*    needs to be called to release that allocation.                     */
+  /*    `fcinit.c' (ft_create_default_module_classes) already contains     */
   /*    a mechanism to call these functions for the default modules        */
-  /*    described in ftmodule.h                                            */
+  /*    described in `ftmodule.h'.                                         */
   /*                                                                       */
-  /*    Notice that the created Create and Destroy functions call          */
-  /*    pic_init and pic_free function to allow you to manually allocate   */
-  /*    and initialize any additional global data, like module specific    */
+  /*    Notice that the created `create' and `destroy' functions call      */
+  /*    `pic_init' and `pic_free' to allow you to manually allocate and    */
+  /*    initialize any additional global data, like a module specific      */
   /*    interface, and put them in the global pic container defined in     */
-  /*    ftpic.h. if you don't need them just implement the functions as    */
-  /*    empty to resolve the link error.  Also the pic_init and pic_free   */
-  /*    functions should be declared in pic.h, to be referred by module    */
-  /*    definition calling FT_DEFINE_MODULE() in following.                */
+  /*    `ftpic.h'.  If you don't need them just implement the functions as */
+  /*    empty to resolve the link error.  Also the `pic_init' and          */
+  /*    `pic_free' functions should be declared in `pic.h', to be referred */
+  /*    by the module definition calling `FT_DEFINE_MODULE' in the         */
+  /*    following.                                                         */
   /*                                                                       */
   /*    When FT_CONFIG_OPTION_PIC is not defined the struct will be        */
   /*    allocated in the global scope (or the scope where the macro        */
@@ -1287,119 +1403,159 @@
   /*    FT_DEFINE_ROOT_MODULE                                              */
   /*                                                                       */
   /* <Description>                                                         */
-  /*    Used to initialize an instance of FT_Module_Class struct inside    */
-  /*    another stract that contains it or in a function that initializes  */
-  /*    that containing stract                                             */
+  /*    Used to initialize an instance of an FT_Module_Class struct inside */
+  /*    another struct that contains it or in a function that initializes  */
+  /*    that containing struct.                                            */
   /*                                                                       */
 #ifndef FT_CONFIG_OPTION_PIC
 
-#define FT_DECLARE_MODULE(class_)                                            \
-  FT_CALLBACK_TABLE                                                          \
-  const FT_Module_Class  class_;                                             \
+#define FT_DECLARE_MODULE( class_ )  \
+  FT_CALLBACK_TABLE                  \
+  const FT_Module_Class  class_;
 
-#define FT_DEFINE_ROOT_MODULE(flags_, size_, name_, version_, requires_,     \
-                              interface_, init_, done_, get_interface_)      \
-  {                                                                          \
-    flags_,                                                                  \
-    size_,                                                                   \
-                                                                             \
-    name_,                                                                   \
-    version_,                                                                \
-    requires_,                                                               \
-                                                                             \
-    interface_,                                                              \
-                                                                             \
-    init_,                                                                   \
-    done_,                                                                   \
-    get_interface_,                                                          \
+#define FT_DEFINE_ROOT_MODULE(  \
+          flags_,               \
+          size_,                \
+          name_,                \
+          version_,             \
+          requires_,            \
+          interface_,           \
+          init_,                \
+          done_,                \
+          get_interface_ )      \
+  {                             \
+    flags_,                     \
+    size_,                      \
+                                \
+    name_,                      \
+    version_,                   \
+    requires_,                  \
+                                \
+    interface_,                 \
+                                \
+    init_,                      \
+    done_,                      \
+    get_interface_,             \
   },
 
-#define FT_DEFINE_MODULE(class_, flags_, size_, name_, version_, requires_,  \
-                         interface_, init_, done_, get_interface_)           \
-  FT_CALLBACK_TABLE_DEF                                                      \
-  const FT_Module_Class class_ =                                             \
-  {                                                                          \
-    flags_,                                                                  \
-    size_,                                                                   \
-                                                                             \
-    name_,                                                                   \
-    version_,                                                                \
-    requires_,                                                               \
-                                                                             \
-    interface_,                                                              \
-                                                                             \
-    init_,                                                                   \
-    done_,                                                                   \
-    get_interface_,                                                          \
+#define FT_DEFINE_MODULE(         \
+          class_,                 \
+          flags_,                 \
+          size_,                  \
+          name_,                  \
+          version_,               \
+          requires_,              \
+          interface_,             \
+          init_,                  \
+          done_,                  \
+          get_interface_ )        \
+  FT_CALLBACK_TABLE_DEF           \
+  const FT_Module_Class class_ =  \
+  {                               \
+    flags_,                       \
+    size_,                        \
+                                  \
+    name_,                        \
+    version_,                     \
+    requires_,                    \
+                                  \
+    interface_,                   \
+                                  \
+    init_,                        \
+    done_,                        \
+    get_interface_,               \
   };
 
 
 #else /* FT_CONFIG_OPTION_PIC */
 
-#define FT_DECLARE_MODULE(class_)                                            \
-  FT_Error FT_Create_Class_##class_( FT_Library library,                     \
-                                     FT_Module_Class** output_class );       \
-  void     FT_Destroy_Class_##class_( FT_Library library,                    \
-                                      FT_Module_Class*  clazz );
+#define FT_DECLARE_MODULE( class_ )                               \
+  FT_Error                                                        \
+  FT_Create_Class_ ## class_( FT_Library         library,         \
+                              FT_Module_Class**  output_class );  \
+  void                                                            \
+  FT_Destroy_Class_ ## class_( FT_Library        library,         \
+                               FT_Module_Class*  clazz );
 
-#define FT_DEFINE_ROOT_MODULE(flags_, size_, name_, version_, requires_,     \
-                              interface_, init_, done_, get_interface_)      \
-    clazz->root.module_flags       = flags_;                                 \
-    clazz->root.module_size        = size_;                                  \
-    clazz->root.module_name        = name_;                                  \
-    clazz->root.module_version     = version_;                               \
-    clazz->root.module_requires    = requires_;                              \
-                                                                             \
-    clazz->root.module_interface   = interface_;                             \
-                                                                             \
-    clazz->root.module_init        = init_;                                  \
-    clazz->root.module_done        = done_;                                  \
-    clazz->root.get_interface      = get_interface_;
+#define FT_DEFINE_ROOT_MODULE(                      \
+          flags_,                                   \
+          size_,                                    \
+          name_,                                    \
+          version_,                                 \
+          requires_,                                \
+          interface_,                               \
+          init_,                                    \
+          done_,                                    \
+          get_interface_ )                          \
+    clazz->root.module_flags     = flags_;          \
+    clazz->root.module_size      = size_;           \
+    clazz->root.module_name      = name_;           \
+    clazz->root.module_version   = version_;        \
+    clazz->root.module_requires  = requires_;       \
+                                                    \
+    clazz->root.module_interface = interface_;      \
+                                                    \
+    clazz->root.module_init      = init_;           \
+    clazz->root.module_done      = done_;           \
+    clazz->root.get_interface    = get_interface_;
 
-#define FT_DEFINE_MODULE(class_, flags_, size_, name_, version_, requires_,  \
-                         interface_, init_, done_, get_interface_)           \
-                                                                             \
-  void                                                                       \
-  FT_Destroy_Class_##class_( FT_Library library,                             \
-                             FT_Module_Class*  clazz )                       \
-  {                                                                          \
-    FT_Memory memory = library->memory;                                      \
-    class_##_pic_free( library );                                            \
-    if ( clazz )                                                             \
-      FT_FREE( clazz );                                                      \
-  }                                                                          \
-                                                                             \
-  FT_Error                                                                   \
-  FT_Create_Class_##class_( FT_Library library,                              \
-                            FT_Module_Class**  output_class )                \
-  {                                                                          \
-    FT_Memory memory = library->memory;                                      \
-    FT_Module_Class*  clazz;                                                 \
-    FT_Error          error;                                                 \
-                                                                             \
-    if ( FT_ALLOC( clazz, sizeof(*clazz) ) )                                 \
-      return error;                                                          \
-    error = class_##_pic_init( library );                                    \
-    if(error)                                                                \
-    {                                                                        \
-      FT_FREE( clazz );                                                      \
-      return error;                                                          \
-    }                                                                        \
-                                                                             \
-    clazz->module_flags       = flags_;                                      \
-    clazz->module_size        = size_;                                       \
-    clazz->module_name        = name_;                                       \
-    clazz->module_version     = version_;                                    \
-    clazz->module_requires    = requires_;                                   \
-                                                                             \
-    clazz->module_interface   = interface_;                                  \
-                                                                             \
-    clazz->module_init        = init_;                                       \
-    clazz->module_done        = done_;                                       \
-    clazz->get_interface      = get_interface_;                              \
-                                                                             \
-    *output_class = clazz;                                                   \
-    return FT_Err_Ok;                                                        \
+#define FT_DEFINE_MODULE(                                        \
+          class_,                                                \
+          flags_,                                                \
+          size_,                                                 \
+          name_,                                                 \
+          version_,                                              \
+          requires_,                                             \
+          interface_,                                            \
+          init_,                                                 \
+          done_,                                                 \
+          get_interface_ )                                       \
+  void                                                           \
+  FT_Destroy_Class_ ## class_( FT_Library        library,        \
+                               FT_Module_Class*  clazz )         \
+  {                                                              \
+    FT_Memory memory = library->memory;                          \
+                                                                 \
+                                                                 \
+    class_ ## _pic_free( library );                              \
+    if ( clazz )                                                 \
+      FT_FREE( clazz );                                          \
+  }                                                              \
+                                                                 \
+                                                                 \
+  FT_Error                                                       \
+  FT_Create_Class_ ## class_( FT_Library         library,        \
+                              FT_Module_Class**  output_class )  \
+  {                                                              \
+    FT_Memory         memory = library->memory;                  \
+    FT_Module_Class*  clazz  = NULL;                             \
+    FT_Error          error;                                     \
+                                                                 \
+                                                                 \
+    if ( FT_ALLOC( clazz, sizeof ( *clazz ) ) )                  \
+      return error;                                              \
+    error = class_ ## _pic_init( library );                      \
+    if ( error )                                                 \
+    {                                                            \
+      FT_FREE( clazz );                                          \
+      return error;                                              \
+    }                                                            \
+                                                                 \
+    clazz->module_flags     = flags_;                            \
+    clazz->module_size      = size_;                             \
+    clazz->module_name      = name_;                             \
+    clazz->module_version   = version_;                          \
+    clazz->module_requires  = requires_;                         \
+                                                                 \
+    clazz->module_interface = interface_;                        \
+                                                                 \
+    clazz->module_init      = init_;                             \
+    clazz->module_done      = done_;                             \
+    clazz->get_interface    = get_interface_;                    \
+                                                                 \
+    *output_class = clazz;                                       \
+                                                                 \
+    return FT_Err_Ok;                                            \
   }
 
 #endif /* FT_CONFIG_OPTION_PIC */
diff --git a/include/freetype/internal/ftpic.h b/include/freetype/internal/ftpic.h
index 5b674e6..485ce7a 100644
--- a/include/freetype/internal/ftpic.h
+++ b/include/freetype/internal/ftpic.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType position independent code services (declaration).       */
 /*                                                                         */
-/*  Copyright 2009 by                                                      */
+/*  Copyright 2009, 2012 by                                                */
 /*  Oran Agra and Mickey Gabel.                                            */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -31,29 +31,33 @@
 
 #ifdef FT_CONFIG_OPTION_PIC
 
-  typedef struct FT_PIC_Container_
+  typedef struct  FT_PIC_Container_
   {
     /* pic containers for base */
-    void* base;
+    void*  base;
+
     /* pic containers for modules */
-    void* autofit;
-    void* cff;
-    void* pshinter;
-    void* psnames;
-    void* raster;
-    void* sfnt;
-    void* smooth;
-    void* truetype;
+    void*  autofit;
+    void*  cff;
+    void*  pshinter;
+    void*  psnames;
+    void*  raster;
+    void*  sfnt;
+    void*  smooth;
+    void*  truetype;
+
   } FT_PIC_Container;
 
-  /* Initialize the various function tables, structs, etc. stored in the container. */
+
+  /* Initialize the various function tables, structs, etc. */
+  /* stored in the container.                              */
   FT_BASE( FT_Error )
-  ft_pic_container_init( FT_Library library );
+  ft_pic_container_init( FT_Library  library );
 
 
   /* Destroy the contents of the container. */
   FT_BASE( void )
-  ft_pic_container_destroy( FT_Library library );
+  ft_pic_container_destroy( FT_Library  library );
 
 #endif /* FT_CONFIG_OPTION_PIC */
 
diff --git a/include/freetype/internal/ftrfork.h b/include/freetype/internal/ftrfork.h
index 77e1020..6307f2d 100644
--- a/include/freetype/internal/ftrfork.h
+++ b/include/freetype/internal/ftrfork.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Embedded resource forks accessor (specification).                    */
 /*                                                                         */
-/*  Copyright 2004, 2006, 2007 by                                          */
+/*  Copyright 2004, 2006, 2007, 2012 by                                    */
 /*  Masatake YAMATO and Redhat K.K.                                        */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -80,26 +80,37 @@
   } ft_raccess_guess_rec;
 
 #ifndef FT_CONFIG_OPTION_PIC
+
   /* this array is a storage in non-PIC mode, so ; is needed in END */
-#define CONST_FT_RFORK_RULE_ARRAY_BEGIN( name, type ) \
-        const type name[] = {
-#define CONST_FT_RFORK_RULE_ARRAY_ENTRY( func_suffix, type_suffix ) \
-        { raccess_guess_##func_suffix, FT_RFork_Rule_##type_suffix },
-#define CONST_FT_RFORK_RULE_ARRAY_END };
+#define CONST_FT_RFORK_RULE_ARRAY_BEGIN( name, type )  \
+          const type name[] = {
+#define CONST_FT_RFORK_RULE_ARRAY_ENTRY( func_suffix, type_suffix )  \
+          { raccess_guess_ ## func_suffix,                           \
+            FT_RFork_Rule_ ## type_suffix },
+#define CONST_FT_RFORK_RULE_ARRAY_END  };
+
 #else /* FT_CONFIG_OPTION_PIC */
+
   /* this array is a function in PIC mode, so no ; is needed in END */
-#define CONST_FT_RFORK_RULE_ARRAY_BEGIN( name, type ) \
-        void FT_Init_##name ( type* storage ) {       \
-          type *local = storage;                      \
-          int i = 0;
-#define CONST_FT_RFORK_RULE_ARRAY_ENTRY( func_suffix, type_suffix ) \
-        local[i].func = raccess_guess_##func_suffix;                \
-        local[i].type = FT_RFork_Rule_##type_suffix;                \
-        i++;
-#define CONST_FT_RFORK_RULE_ARRAY_END }
+#define CONST_FT_RFORK_RULE_ARRAY_BEGIN( name, type )  \
+          void                                         \
+          FT_Init_ ## name( type*  storage )           \
+          {                                            \
+            type*  local = storage;                    \
+                                                       \
+                                                       \
+            int  i = 0;
+#define CONST_FT_RFORK_RULE_ARRAY_ENTRY( func_suffix, type_suffix )  \
+          local[i].func = raccess_guess_ ## func_suffix;             \
+          local[i].type = FT_RFork_Rule_ ## type_suffix;             \
+          i++;
+#define CONST_FT_RFORK_RULE_ARRAY_END  }
+
 #endif /* FT_CONFIG_OPTION_PIC */
+
 #endif /* FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK */
 
+
   /*************************************************************************/
   /*                                                                       */
   /* <Function>                                                            */
diff --git a/include/freetype/internal/ftserv.h b/include/freetype/internal/ftserv.h
index 4f481db..4ac988b 100644
--- a/include/freetype/internal/ftserv.h
+++ b/include/freetype/internal/ftserv.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType services (specification only).                          */
 /*                                                                         */
-/*  Copyright 2003-2007, 2009, 2012 by                                     */
+/*  Copyright 2003-2007, 2009, 2012, 2013 by                               */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -34,12 +34,12 @@
 
 FT_BEGIN_HEADER
 
-#if defined( _MSC_VER )      /* Visual C++ (and Intel C++) */
-
-  /* we disable the warning `conditional expression is constant' here */
-  /* in order to compile cleanly with the maximum level of warnings   */
+#if defined( _MSC_VER )      /* Visual C++ (and Intel C++)  */
+  /* We disable the warning `conditional expression is      */
+  /* constant' in order to compile cleanly with the maximum */
+  /* level of warnings.                                     */
+#pragma warning( push )
 #pragma warning( disable : 4127 )
-
 #endif /* _MSC_VER */
 
   /*
@@ -92,6 +92,7 @@
 
 #endif /* !C++ */
 
+
   /*
    * @macro:
    *   FT_FACE_FIND_GLOBAL_SERVICE
@@ -167,7 +168,13 @@
   /*************************************************************************/
   /*                                                                       */
   /* <Macro>                                                               */
-  /*    FT_DEFINE_SERVICEDESCREC1 .. FT_DEFINE_SERVICEDESCREC6             */
+  /*    FT_DEFINE_SERVICEDESCREC1                                          */
+  /*    FT_DEFINE_SERVICEDESCREC2                                          */
+  /*    FT_DEFINE_SERVICEDESCREC3                                          */
+  /*    FT_DEFINE_SERVICEDESCREC4                                          */
+  /*    FT_DEFINE_SERVICEDESCREC5                                          */
+  /*    FT_DEFINE_SERVICEDESCREC6                                          */
+  /*    FT_DEFINE_SERVICEDESCREC7                                          */
   /*                                                                       */
   /* <Description>                                                         */
   /*    Used to initialize an array of FT_ServiceDescRec structures.       */
@@ -264,6 +271,26 @@
     { NULL, NULL }                                                          \
   };
 
+#define FT_DEFINE_SERVICEDESCREC7( class_,                                  \
+                                   serv_id_1, serv_data_1,                  \
+                                   serv_id_2, serv_data_2,                  \
+                                   serv_id_3, serv_data_3,                  \
+                                   serv_id_4, serv_data_4,                  \
+                                   serv_id_5, serv_data_5,                  \
+                                   serv_id_6, serv_data_6,                  \
+                                   serv_id_7, serv_data_7 )                 \
+  static const FT_ServiceDescRec  class_[] =                                \
+  {                                                                         \
+    { serv_id_1, serv_data_1 },                                             \
+    { serv_id_2, serv_data_2 },                                             \
+    { serv_id_3, serv_data_3 },                                             \
+    { serv_id_4, serv_data_4 },                                             \
+    { serv_id_5, serv_data_5 },                                             \
+    { serv_id_6, serv_data_6 },                                             \
+    { serv_id_7, serv_data_7 },                                             \
+    { NULL, NULL }                                                          \
+  };
+
 #else /* FT_CONFIG_OPTION_PIC */
 
 #define FT_DEFINE_SERVICEDESCREC1( class_,                                  \
@@ -283,7 +310,7 @@
   FT_Create_Class_ ## class_( FT_Library           library,                 \
                               FT_ServiceDescRec**  output_class )           \
   {                                                                         \
-    FT_ServiceDescRec*  clazz;                                              \
+    FT_ServiceDescRec*  clazz  = NULL;                                      \
     FT_Error            error;                                              \
     FT_Memory           memory = library->memory;                           \
                                                                             \
@@ -319,7 +346,7 @@
   FT_Create_Class_ ## class_( FT_Library           library,                 \
                               FT_ServiceDescRec**  output_class )           \
   {                                                                         \
-    FT_ServiceDescRec*  clazz;                                              \
+    FT_ServiceDescRec*  clazz  = NULL;                                      \
     FT_Error            error;                                              \
     FT_Memory           memory = library->memory;                           \
                                                                             \
@@ -358,7 +385,7 @@
   FT_Create_Class_ ## class_( FT_Library           library,                 \
                               FT_ServiceDescRec**  output_class )           \
   {                                                                         \
-    FT_ServiceDescRec*  clazz;                                              \
+    FT_ServiceDescRec*  clazz  = NULL;                                      \
     FT_Error            error;                                              \
     FT_Memory           memory = library->memory;                           \
                                                                             \
@@ -400,7 +427,7 @@
   FT_Create_Class_ ## class_( FT_Library           library,                 \
                               FT_ServiceDescRec**  output_class )           \
   {                                                                         \
-    FT_ServiceDescRec*  clazz;                                              \
+    FT_ServiceDescRec*  clazz  = NULL;                                      \
     FT_Error            error;                                              \
     FT_Memory           memory = library->memory;                           \
                                                                             \
@@ -445,7 +472,7 @@
   FT_Create_Class_ ## class_( FT_Library           library,                 \
                               FT_ServiceDescRec**  output_class )           \
   {                                                                         \
-    FT_ServiceDescRec*  clazz;                                              \
+    FT_ServiceDescRec*  clazz  = NULL;                                      \
     FT_Error            error;                                              \
     FT_Memory           memory = library->memory;                           \
                                                                             \
@@ -493,7 +520,7 @@
   FT_Create_Class_ ## class_( FT_Library           library,                 \
                               FT_ServiceDescRec**  output_class)            \
   {                                                                         \
-    FT_ServiceDescRec*  clazz;                                              \
+    FT_ServiceDescRec*  clazz  = NULL;                                      \
     FT_Error            error;                                              \
     FT_Memory           memory = library->memory;                           \
                                                                             \
@@ -521,6 +548,59 @@
     return FT_Err_Ok;                                                       \
   }
 
+#define FT_DEFINE_SERVICEDESCREC7( class_,                                  \
+                                   serv_id_1, serv_data_1,                  \
+                                   serv_id_2, serv_data_2,                  \
+                                   serv_id_3, serv_data_3,                  \
+                                   serv_id_4, serv_data_4,                  \
+                                   serv_id_5, serv_data_5,                  \
+                                   serv_id_6, serv_data_6,                  \
+                                   serv_id_7, serv_data_7 )                 \
+  void                                                                      \
+  FT_Destroy_Class_ ## class_( FT_Library          library,                 \
+                               FT_ServiceDescRec*  clazz )                  \
+  {                                                                         \
+    FT_Memory  memory = library->memory;                                    \
+                                                                            \
+                                                                            \
+    if ( clazz )                                                            \
+      FT_FREE( clazz );                                                     \
+  }                                                                         \
+                                                                            \
+  FT_Error                                                                  \
+  FT_Create_Class_ ## class_( FT_Library           library,                 \
+                              FT_ServiceDescRec**  output_class)            \
+  {                                                                         \
+    FT_ServiceDescRec*  clazz  = NULL;                                      \
+    FT_Error            error;                                              \
+    FT_Memory           memory = library->memory;                           \
+                                                                            \
+                                                                            \
+    if ( FT_ALLOC( clazz, sizeof ( *clazz ) * 8 ) )                         \
+      return error;                                                         \
+                                                                            \
+    clazz[0].serv_id   = serv_id_1;                                         \
+    clazz[0].serv_data = serv_data_1;                                       \
+    clazz[1].serv_id   = serv_id_2;                                         \
+    clazz[1].serv_data = serv_data_2;                                       \
+    clazz[2].serv_id   = serv_id_3;                                         \
+    clazz[2].serv_data = serv_data_3;                                       \
+    clazz[3].serv_id   = serv_id_4;                                         \
+    clazz[3].serv_data = serv_data_4;                                       \
+    clazz[4].serv_id   = serv_id_5;                                         \
+    clazz[4].serv_data = serv_data_5;                                       \
+    clazz[5].serv_id   = serv_id_6;                                         \
+    clazz[5].serv_data = serv_data_6;                                       \
+    clazz[6].serv_id   = serv_id_7;                                         \
+    clazz[6].serv_data = serv_data_7;                                       \
+    clazz[7].serv_id   = NULL;                                              \
+    clazz[7].serv_data = NULL;                                              \
+                                                                            \
+    *output_class = clazz;                                                  \
+                                                                            \
+    return FT_Err_Ok;                                                       \
+  }
+
 #endif /* FT_CONFIG_OPTION_PIC */
 
 
@@ -573,7 +653,9 @@
   /*
    *  A magic number used within the services cache.
    */
-#define FT_SERVICE_UNAVAILABLE  ((FT_Pointer)-2)  /* magic number */
+
+  /* ensure that value `1' has the same width as a pointer */
+#define FT_SERVICE_UNAVAILABLE  ((FT_Pointer)~(FT_PtrDist)1)
 
 
   /*
@@ -671,6 +753,7 @@
 #define FT_SERVICE_POSTSCRIPT_CMAPS_H   <freetype/internal/services/svpscmap.h>
 #define FT_SERVICE_POSTSCRIPT_INFO_H    <freetype/internal/services/svpsinfo.h>
 #define FT_SERVICE_POSTSCRIPT_NAME_H    <freetype/internal/services/svpostnm.h>
+#define FT_SERVICE_PROPERTIES_H         <freetype/internal/services/svprop.h>
 #define FT_SERVICE_SFNT_H               <freetype/internal/services/svsfnt.h>
 #define FT_SERVICE_TRUETYPE_ENGINE_H    <freetype/internal/services/svtteng.h>
 #define FT_SERVICE_TT_CMAP_H            <freetype/internal/services/svttcmap.h>
@@ -680,6 +763,10 @@
 
  /* */
 
+#if defined( _MSC_VER )
+#pragma warning( pop )
+#endif
+
 FT_END_HEADER
 
 #endif /* __FTSERV_H__ */
diff --git a/include/freetype/internal/ftstream.h b/include/freetype/internal/ftstream.h
index 8b18500..2661858 100644
--- a/include/freetype/internal/ftstream.h
+++ b/include/freetype/internal/ftstream.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Stream handling (specification).                                     */
 /*                                                                         */
-/*  Copyright 1996-2002, 2004-2006, 2011 by                                */
+/*  Copyright 1996-2002, 2004-2006, 2011, 2013 by                          */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -154,67 +154,60 @@
   /*                                                                       */
 
 #define FT_BYTE_( p, i )  ( ((const FT_Byte*)(p))[(i)] )
-#define FT_INT8_( p, i )  ( ((const FT_Char*)(p))[(i)] )
 
 #define FT_INT16( x )   ( (FT_Int16)(x)  )
 #define FT_UINT16( x )  ( (FT_UInt16)(x) )
 #define FT_INT32( x )   ( (FT_Int32)(x)  )
 #define FT_UINT32( x )  ( (FT_UInt32)(x) )
 
-#define FT_BYTE_I16( p, i, s )  ( FT_INT16(  FT_BYTE_( p, i ) ) << (s) )
+
 #define FT_BYTE_U16( p, i, s )  ( FT_UINT16( FT_BYTE_( p, i ) ) << (s) )
-#define FT_BYTE_I32( p, i, s )  ( FT_INT32(  FT_BYTE_( p, i ) ) << (s) )
 #define FT_BYTE_U32( p, i, s )  ( FT_UINT32( FT_BYTE_( p, i ) ) << (s) )
 
-#define FT_INT8_I16( p, i, s )  ( FT_INT16(  FT_INT8_( p, i ) ) << (s) )
-#define FT_INT8_U16( p, i, s )  ( FT_UINT16( FT_INT8_( p, i ) ) << (s) )
-#define FT_INT8_I32( p, i, s )  ( FT_INT32(  FT_INT8_( p, i ) ) << (s) )
-#define FT_INT8_U32( p, i, s )  ( FT_UINT32( FT_INT8_( p, i ) ) << (s) )
 
-
-#define FT_PEEK_SHORT( p )  FT_INT16( FT_INT8_I16( p, 0, 8) | \
-                                      FT_BYTE_I16( p, 1, 0) )
+#define FT_PEEK_SHORT( p )  FT_INT16( FT_BYTE_U16( p, 0, 8) | \
+                                      FT_BYTE_U16( p, 1, 0) )
 
 #define FT_PEEK_USHORT( p )  FT_UINT16( FT_BYTE_U16( p, 0, 8 ) | \
                                         FT_BYTE_U16( p, 1, 0 ) )
 
-#define FT_PEEK_LONG( p )  FT_INT32( FT_INT8_I32( p, 0, 24 ) | \
-                                     FT_BYTE_I32( p, 1, 16 ) | \
-                                     FT_BYTE_I32( p, 2,  8 ) | \
-                                     FT_BYTE_I32( p, 3,  0 ) )
+#define FT_PEEK_LONG( p )  FT_INT32( FT_BYTE_U32( p, 0, 24 ) | \
+                                     FT_BYTE_U32( p, 1, 16 ) | \
+                                     FT_BYTE_U32( p, 2,  8 ) | \
+                                     FT_BYTE_U32( p, 3,  0 ) )
 
 #define FT_PEEK_ULONG( p )  FT_UINT32( FT_BYTE_U32( p, 0, 24 ) | \
                                        FT_BYTE_U32( p, 1, 16 ) | \
                                        FT_BYTE_U32( p, 2,  8 ) | \
                                        FT_BYTE_U32( p, 3,  0 ) )
 
-#define FT_PEEK_OFF3( p )  FT_INT32( FT_INT8_I32( p, 0, 16 ) | \
-                                     FT_BYTE_I32( p, 1,  8 ) | \
-                                     FT_BYTE_I32( p, 2,  0 ) )
+#define FT_PEEK_OFF3( p )  FT_INT32( FT_BYTE_U32( p, 0, 16 ) | \
+                                     FT_BYTE_U32( p, 1,  8 ) | \
+                                     FT_BYTE_U32( p, 2,  0 ) )
 
 #define FT_PEEK_UOFF3( p )  FT_UINT32( FT_BYTE_U32( p, 0, 16 ) | \
                                        FT_BYTE_U32( p, 1,  8 ) | \
                                        FT_BYTE_U32( p, 2,  0 ) )
 
-#define FT_PEEK_SHORT_LE( p )  FT_INT16( FT_INT8_I16( p, 1, 8 ) | \
-                                         FT_BYTE_I16( p, 0, 0 ) )
+#define FT_PEEK_SHORT_LE( p )  FT_INT16( FT_BYTE_U16( p, 1, 8 ) | \
+                                         FT_BYTE_U16( p, 0, 0 ) )
 
 #define FT_PEEK_USHORT_LE( p )  FT_UINT16( FT_BYTE_U16( p, 1, 8 ) |  \
                                            FT_BYTE_U16( p, 0, 0 ) )
 
-#define FT_PEEK_LONG_LE( p )  FT_INT32( FT_INT8_I32( p, 3, 24 ) | \
-                                        FT_BYTE_I32( p, 2, 16 ) | \
-                                        FT_BYTE_I32( p, 1,  8 ) | \
-                                        FT_BYTE_I32( p, 0,  0 ) )
+#define FT_PEEK_LONG_LE( p )  FT_INT32( FT_BYTE_U32( p, 3, 24 ) | \
+                                        FT_BYTE_U32( p, 2, 16 ) | \
+                                        FT_BYTE_U32( p, 1,  8 ) | \
+                                        FT_BYTE_U32( p, 0,  0 ) )
 
 #define FT_PEEK_ULONG_LE( p )  FT_UINT32( FT_BYTE_U32( p, 3, 24 ) | \
                                           FT_BYTE_U32( p, 2, 16 ) | \
                                           FT_BYTE_U32( p, 1,  8 ) | \
                                           FT_BYTE_U32( p, 0,  0 ) )
 
-#define FT_PEEK_OFF3_LE( p )  FT_INT32( FT_INT8_I32( p, 2, 16 ) | \
-                                        FT_BYTE_I32( p, 1,  8 ) | \
-                                        FT_BYTE_I32( p, 0,  0 ) )
+#define FT_PEEK_OFF3_LE( p )  FT_INT32( FT_BYTE_U32( p, 2, 16 ) | \
+                                        FT_BYTE_U32( p, 1,  8 ) | \
+                                        FT_BYTE_U32( p, 0,  0 ) )
 
 #define FT_PEEK_UOFF3_LE( p )  FT_UINT32( FT_BYTE_U32( p, 2, 16 ) | \
                                           FT_BYTE_U32( p, 1,  8 ) | \
@@ -493,37 +486,41 @@
 #define FT_STREAM_POS()           \
           FT_Stream_Pos( stream )
 
-#define FT_STREAM_SEEK( position )                           \
-          FT_SET_ERROR( FT_Stream_Seek( stream, position ) )
+#define FT_STREAM_SEEK( position )                               \
+          FT_SET_ERROR( FT_Stream_Seek( stream,                  \
+                                        (FT_ULong)(position) ) )
 
-#define FT_STREAM_SKIP( distance )                           \
-          FT_SET_ERROR( FT_Stream_Skip( stream, distance ) )
+#define FT_STREAM_SKIP( distance )                              \
+          FT_SET_ERROR( FT_Stream_Skip( stream,                 \
+                                        (FT_Long)(distance) ) )
 
-#define FT_STREAM_READ( buffer, count )                   \
-          FT_SET_ERROR( FT_Stream_Read( stream,           \
-                                        (FT_Byte*)buffer, \
-                                        count ) )
+#define FT_STREAM_READ( buffer, count )                       \
+          FT_SET_ERROR( FT_Stream_Read( stream,               \
+                                        (FT_Byte*)(buffer),   \
+                                        (FT_ULong)(count) ) )
 
-#define FT_STREAM_READ_AT( position, buffer, count )         \
-          FT_SET_ERROR( FT_Stream_ReadAt( stream,            \
-                                           position,         \
-                                           (FT_Byte*)buffer, \
-                                           count ) )
+#define FT_STREAM_READ_AT( position, buffer, count )            \
+          FT_SET_ERROR( FT_Stream_ReadAt( stream,               \
+                                          (FT_ULong)(position), \
+                                          (FT_Byte*)buffer,     \
+                                          (FT_ULong)(count) ) )
 
 #define FT_STREAM_READ_FIELDS( fields, object )                          \
           FT_SET_ERROR( FT_Stream_ReadFields( stream, fields, object ) )
 
 
-#define FT_FRAME_ENTER( size )                                       \
-          FT_SET_ERROR(                                              \
-            FT_DEBUG_INNER( FT_Stream_EnterFrame( stream, size ) ) )
+#define FT_FRAME_ENTER( size )                                           \
+          FT_SET_ERROR(                                                  \
+            FT_DEBUG_INNER( FT_Stream_EnterFrame( stream,                \
+                                                  (FT_ULong)(size) ) ) )
 
-#define FT_FRAME_EXIT()                 \
+#define FT_FRAME_EXIT()                                   \
           FT_DEBUG_INNER( FT_Stream_ExitFrame( stream ) )
 
 #define FT_FRAME_EXTRACT( size, bytes )                                       \
           FT_SET_ERROR(                                                       \
-            FT_DEBUG_INNER( FT_Stream_ExtractFrame( stream, size,             \
+            FT_DEBUG_INNER( FT_Stream_ExtractFrame( stream,                   \
+                                                    (FT_ULong)(size),         \
                                                     (FT_Byte**)&(bytes) ) ) )
 
 #define FT_FRAME_RELEASE( bytes )                                         \
diff --git a/include/freetype/internal/fttrace.h b/include/freetype/internal/fttrace.h
index fbefdbd..a9d98b6 100644
--- a/include/freetype/internal/fttrace.h
+++ b/include/freetype/internal/fttrace.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Tracing handling (specification only).                               */
 /*                                                                         */
-/*  Copyright 2002, 2004-2007, 2009, 2011 by                               */
+/*  Copyright 2002, 2004-2007, 2009, 2011-2013 by                          */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -38,6 +38,7 @@
 FT_TRACE_DEF( mm )        /* MM interface            (ftmm.c)     */
 FT_TRACE_DEF( raccess )   /* resource fork accessor  (ftrfork.c)  */
 FT_TRACE_DEF( synth )     /* bold/slant synthesizer  (ftsynth.c)  */
+FT_TRACE_DEF( bitmap )    /* bitmap checksum         (ftobjs.c)   */
 
   /* Cache sub-system */
 FT_TRACE_DEF( cache )     /* cache sub-system        (ftcache.c, etc.) */
@@ -73,6 +74,7 @@
   /* PostScript helper module `psaux' */
 FT_TRACE_DEF( t1decode )
 FT_TRACE_DEF( psobjs )
+FT_TRACE_DEF( psconv )
 
   /* PostScript hinting module `pshinter' */
 FT_TRACE_DEF( pshrec )
@@ -86,6 +88,10 @@
 FT_TRACE_DEF( cffobjs )
 FT_TRACE_DEF( cffparse )
 
+FT_TRACE_DEF( cf2blues )
+FT_TRACE_DEF( cf2hints )
+FT_TRACE_DEF( cf2interp )
+
   /* Type 42 driver component */
 FT_TRACE_DEF( t42 )
 
@@ -136,6 +142,8 @@
 FT_TRACE_DEF( gxvlcar )
 
   /* autofit components */
+FT_TRACE_DEF( afmodule )
+FT_TRACE_DEF( afhints )
 FT_TRACE_DEF( afcjk )
 FT_TRACE_DEF( aflatin )
 FT_TRACE_DEF( aflatin2 )
diff --git a/include/freetype/internal/ftvalid.h b/include/freetype/internal/ftvalid.h
index 00cd85e..12ad036 100644
--- a/include/freetype/internal/ftvalid.h
+++ b/include/freetype/internal/ftvalid.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType validation support (specification).                         */
 /*                                                                         */
-/*  Copyright 2004 by                                                      */
+/*  Copyright 2004, 2013 by                                                */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -76,6 +76,14 @@
   } FT_ValidationLevel;
 
 
+#if defined( _MSC_VER )      /* Visual C++ (and Intel C++) */
+  /* We disable the warning `structure was padded due to   */
+  /* __declspec(align())' in order to compile cleanly with */
+  /* the maximum level of warnings.                        */
+#pragma warning( push )
+#pragma warning( disable : 4324 )
+#endif /* _MSC_VER */
+
   /* validator structure */
   typedef struct  FT_ValidatorRec_
   {
@@ -88,8 +96,11 @@
 
   } FT_ValidatorRec;
 
+#if defined( _MSC_VER )
+#pragma warning( pop )
+#endif
 
-#define FT_VALIDATOR( x )  ((FT_Validator)( x ))
+#define FT_VALIDATOR( x )  ( (FT_Validator)( x ) )
 
 
   FT_BASE( void )
diff --git a/include/freetype/internal/psaux.h b/include/freetype/internal/psaux.h
index a96e0df..e903114 100644
--- a/include/freetype/internal/psaux.h
+++ b/include/freetype/internal/psaux.h
@@ -5,7 +5,7 @@
 /*    Auxiliary functions and data structures related to PostScript fonts  */
 /*    (specification).                                                     */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003, 2004, 2006, 2008, 2009 by             */
+/*  Copyright 1996-2004, 2006, 2008, 2009, 2012 by                         */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -101,6 +101,9 @@
   /*    capacity  :: The current size of the heap block.  Increments by    */
   /*                 1kByte chunks.                                        */
   /*                                                                       */
+  /*    init      :: Set to 0xDEADBEEF if `elements' and `lengths' have    */
+  /*                 been allocated.                                       */
+  /*                                                                       */
   /*    max_elems :: The maximum number of elements in table.              */
   /*                                                                       */
   /*    num_elems :: The current number of elements in table.              */
@@ -183,6 +186,7 @@
     T1_FIELD_TYPE_STRING,
     T1_FIELD_TYPE_KEY,
     T1_FIELD_TYPE_BBOX,
+    T1_FIELD_TYPE_MM_BBOX,
     T1_FIELD_TYPE_INTEGER_ARRAY,
     T1_FIELD_TYPE_FIXED_ARRAY,
     T1_FIELD_TYPE_CALLBACK,
@@ -225,7 +229,7 @@
     T1_Field_ParseFunc  reader;
     FT_UInt             offset;       /* offset of field in object      */
     FT_Byte             size;         /* size of field in bytes         */
-    FT_UInt             array_max;    /* maximal number of elements for */
+    FT_UInt             array_max;    /* maximum number of elements for */
                                       /* array                          */
     FT_UInt             count_offset; /* offset of element count for    */
                                       /* arrays; must not be zero if in */
@@ -531,7 +535,7 @@
   /*                                                                       */
   /*    max_points   :: maximum points in builder outline                  */
   /*                                                                       */
-  /*    max_contours :: Maximal number of contours in builder outline.     */
+  /*    max_contours :: Maximum number of contours in builder outline.     */
   /*                                                                       */
   /*    pos_x        :: The horizontal translation (if composite glyph).   */
   /*                                                                       */
diff --git a/include/freetype/internal/pshints.h b/include/freetype/internal/pshints.h
index 5b7b698..3fb18dc 100644
--- a/include/freetype/internal/pshints.h
+++ b/include/freetype/internal/pshints.h
@@ -6,7 +6,7 @@
 /*    recorders (specification only).  These are used to support native    */
 /*    T1/T2 hints in the `type1', `cid', and `cff' font drivers.           */
 /*                                                                         */
-/*  Copyright 2001, 2002, 2003, 2005, 2006, 2007, 2009 by                  */
+/*  Copyright 2001-2003, 2005-2007, 2009, 2012 by                          */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -679,27 +679,37 @@
 
   typedef PSHinter_Interface*  PSHinter_Service;
 
+
 #ifndef FT_CONFIG_OPTION_PIC
 
-#define FT_DEFINE_PSHINTER_INTERFACE(class_, get_globals_funcs_,             \
-                                     get_t1_funcs_, get_t2_funcs_)           \
-  static const PSHinter_Interface class_ =                                   \
-  {                                                                          \
-    get_globals_funcs_, get_t1_funcs_, get_t2_funcs_                         \
+#define FT_DEFINE_PSHINTER_INTERFACE(        \
+          class_,                            \
+          get_globals_funcs_,                \
+          get_t1_funcs_,                     \
+          get_t2_funcs_ )                    \
+  static const PSHinter_Interface  class_ =  \
+  {                                          \
+    get_globals_funcs_,                      \
+    get_t1_funcs_,                           \
+    get_t2_funcs_                            \
   };
 
 #else /* FT_CONFIG_OPTION_PIC */
 
-#define FT_DEFINE_PSHINTER_INTERFACE(class_, get_globals_funcs_,             \
-                                     get_t1_funcs_, get_t2_funcs_)           \
-  void                                                                       \
-  FT_Init_Class_##class_( FT_Library library,                                \
-                          PSHinter_Interface*  clazz)                        \
-  {                                                                          \
-    FT_UNUSED(library);                                                      \
-    clazz->get_globals_funcs = get_globals_funcs_;                           \
-    clazz->get_t1_funcs = get_t1_funcs_;                                     \
-    clazz->get_t2_funcs = get_t2_funcs_;                                     \
+#define FT_DEFINE_PSHINTER_INTERFACE(                      \
+          class_,                                          \
+          get_globals_funcs_,                              \
+          get_t1_funcs_,                                   \
+          get_t2_funcs_ )                                  \
+  void                                                     \
+  FT_Init_Class_ ## class_( FT_Library           library,  \
+                            PSHinter_Interface*  clazz )   \
+  {                                                        \
+    FT_UNUSED( library );                                  \
+                                                           \
+    clazz->get_globals_funcs = get_globals_funcs_;         \
+    clazz->get_t1_funcs      = get_t1_funcs_;              \
+    clazz->get_t2_funcs      = get_t2_funcs_;              \
   }
 
 #endif /* FT_CONFIG_OPTION_PIC */
diff --git a/include/freetype/internal/services/svprop.h b/include/freetype/internal/services/svprop.h
new file mode 100644
index 0000000..22da0bb
--- /dev/null
+++ b/include/freetype/internal/services/svprop.h
@@ -0,0 +1,81 @@
+/***************************************************************************/
+/*                                                                         */
+/*  svprop.h                                                               */
+/*                                                                         */
+/*    The FreeType property service (specification).                       */
+/*                                                                         */
+/*  Copyright 2012 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 __SVPROP_H__
+#define __SVPROP_H__
+
+
+FT_BEGIN_HEADER
+
+
+#define FT_SERVICE_ID_PROPERTIES  "properties"
+
+
+  typedef FT_Error
+  (*FT_Properties_SetFunc)( FT_Module    module,
+                            const char*  property_name,
+                            const void*  value );
+
+  typedef FT_Error
+  (*FT_Properties_GetFunc)( FT_Module    module,
+                            const char*  property_name,
+                            void*        value );
+
+
+  FT_DEFINE_SERVICE( Properties )
+  {
+    FT_Properties_SetFunc  set_property;
+    FT_Properties_GetFunc  get_property;
+  };
+
+
+#ifndef FT_CONFIG_OPTION_PIC
+
+#define FT_DEFINE_SERVICE_PROPERTIESREC( class_,          \
+                                         set_property_,   \
+                                         get_property_ )  \
+  static const FT_Service_PropertiesRec  class_ =         \
+  {                                                       \
+    set_property_,                                        \
+    get_property_                                         \
+  };
+
+#else /* FT_CONFIG_OPTION_PIC */
+
+#define FT_DEFINE_SERVICE_PROPERTIESREC( class_,                \
+                                         set_property_,         \
+                                         get_property_ )        \
+  void                                                          \
+  FT_Init_Class_ ## class_( FT_Service_PropertiesRec*  clazz )  \
+  {                                                             \
+    clazz->set_property = set_property_;                        \
+    clazz->get_property = get_property_;                        \
+  }
+
+#endif /* FT_CONFIG_OPTION_PIC */
+
+  /* */
+
+
+FT_END_HEADER
+
+
+#endif /* __SVPROP_H__ */
+
+
+/* END */
diff --git a/include/freetype/internal/sfnt.h b/include/freetype/internal/sfnt.h
index 905ca8c..6b5e41f 100644
--- a/include/freetype/internal/sfnt.h
+++ b/include/freetype/internal/sfnt.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    High-level `sfnt' driver interface (specification).                  */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006 by                   */
+/*  Copyright 1996-2006, 2009, 2012-2013 by                                */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -125,77 +125,6 @@
   (*TT_Done_Face_Func)( TT_Face  face );
 
 
-#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <FuncType>                                                            */
-  /*    TT_Load_SFNT_HeaderRec_Func                                        */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Loads the header of a SFNT font file.  Supports collections.       */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    face       :: A handle to the target face object.                  */
-  /*                                                                       */
-  /*    stream     :: The input stream.                                    */
-  /*                                                                       */
-  /*    face_index :: The index of the TrueType font, if we are opening a  */
-  /*                  collection.                                          */
-  /*                                                                       */
-  /* <Output>                                                              */
-  /*    sfnt       :: The SFNT header.                                     */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    FreeType error code.  0 means success.                             */
-  /*                                                                       */
-  /* <Note>                                                                */
-  /*    The stream cursor must be at the font file's origin.               */
-  /*                                                                       */
-  /*    This function recognizes fonts embedded in a `TrueType             */
-  /*    collection'.                                                       */
-  /*                                                                       */
-  /*    This function checks that the header is valid by looking at the    */
-  /*    values of `search_range', `entry_selector', and `range_shift'.     */
-  /*                                                                       */
-  typedef FT_Error
-  (*TT_Load_SFNT_HeaderRec_Func)( TT_Face      face,
-                                  FT_Stream    stream,
-                                  FT_Long      face_index,
-                                  SFNT_Header  sfnt );
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <FuncType>                                                            */
-  /*    TT_Load_Directory_Func                                             */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Loads the table directory into a face object.                      */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    face   :: A handle to the target face object.                      */
-  /*                                                                       */
-  /*    stream :: The input stream.                                        */
-  /*                                                                       */
-  /*    sfnt   :: The SFNT header.                                         */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    FreeType error code.  0 means success.                             */
-  /*                                                                       */
-  /* <Note>                                                                */
-  /*    The stream cursor must be on the first byte after the 4-byte font  */
-  /*    format tag.  This is the case just after a call to                 */
-  /*    TT_Load_Format_Tag().                                              */
-  /*                                                                       */
-  typedef FT_Error
-  (*TT_Load_Directory_Func)( TT_Face      face,
-                             FT_Stream    stream,
-                             SFNT_Header  sfnt );
-
-#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
-
-
   /*************************************************************************/
   /*                                                                       */
   /* <FuncType>                                                            */
@@ -363,88 +292,6 @@
                               TT_SBit_MetricsRec  *ametrics );
 
 
-#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <FuncType>                                                            */
-  /*    TT_Set_SBit_Strike_OldFunc                                         */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Select an sbit strike for a given size request.                    */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    face          :: The target face object.                           */
-  /*                                                                       */
-  /*    req           :: The size request.                                 */
-  /*                                                                       */
-  /* <Output>                                                              */
-  /*    astrike_index :: The index of the sbit strike.                     */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    FreeType error code.  0 means success.  Returns an error if no     */
-  /*    sbit strike exists for the selected ppem values.                   */
-  /*                                                                       */
-  typedef FT_Error
-  (*TT_Set_SBit_Strike_OldFunc)( TT_Face    face,
-                                 FT_UInt    x_ppem,
-                                 FT_UInt    y_ppem,
-                                 FT_ULong*  astrike_index );
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <FuncType>                                                            */
-  /*    TT_CharMap_Load_Func                                               */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Loads a given TrueType character map into memory.                  */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    face   :: A handle to the parent face object.                      */
-  /*                                                                       */
-  /*    stream :: A handle to the current stream object.                   */
-  /*                                                                       */
-  /* <InOut>                                                               */
-  /*    cmap   :: A pointer to a cmap object.                              */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    FreeType error code.  0 means success.                             */
-  /*                                                                       */
-  /* <Note>                                                                */
-  /*    The function assumes that the stream is already in use (i.e.,      */
-  /*    opened).  In case of error, all partially allocated tables are     */
-  /*    released.                                                          */
-  /*                                                                       */
-  typedef FT_Error
-  (*TT_CharMap_Load_Func)( TT_Face    face,
-                           void*      cmap,
-                           FT_Stream  input );
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <FuncType>                                                            */
-  /*    TT_CharMap_Free_Func                                               */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Destroys a character mapping table.                                */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    face :: A handle to the parent face object.                        */
-  /*                                                                       */
-  /*    cmap :: A handle to a cmap object.                                 */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    FreeType error code.  0 means success.                             */
-  /*                                                                       */
-  typedef FT_Error
-  (*TT_CharMap_Free_Func)( TT_Face       face,
-                           void*         cmap );
-
-#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
-
-
   /*************************************************************************/
   /*                                                                       */
   /* <FuncType>                                                            */
@@ -657,11 +504,6 @@
 
     TT_Load_Any_Func             load_any;
 
-#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
-    TT_Load_SFNT_HeaderRec_Func  load_sfnt_header;
-    TT_Load_Directory_Func       load_directory;
-#endif
-
     /* these functions are called by `load_face' but they can also  */
     /* be called from external modules, if there is a need to do so */
     TT_Load_Table_Func           load_head;
@@ -674,12 +516,6 @@
     TT_Load_Table_Func           load_name;
     TT_Free_Table_Func           free_name;
 
-    /* optional tables */
-#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
-    TT_Load_Table_Func           load_hdmx_stub;
-    TT_Free_Table_Func           free_hdmx_stub;
-#endif
-
     /* this field was called `load_kerning' up to version 2.1.10 */
     TT_Load_Table_Func           load_kern;
 
@@ -690,43 +526,12 @@
     /* version 2.1.10                                                   */
     TT_Load_Table_Func           load_bhed;
 
-#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
-
-    /* see `ttsbit.h' */
-    TT_Set_SBit_Strike_OldFunc   set_sbit_strike_stub;
-    TT_Load_Table_Func           load_sbits_stub;
-
-    /*
-     *  The following two fields appeared in version 2.1.8, and were placed
-     *  between `load_sbits' and `load_sbit_image'.  We support them as a
-     *  special exception since they are used by Xfont library within the
-     *  X.Org xserver, and because the probability that other rogue clients
-     *  use the other version 2.1.7 fields below is _extremely_ low.
-     *
-     *  Note that this forces us to disable an interesting memory-saving
-     *  optimization though...
-     */
-
-    TT_Find_SBit_Image_Func      find_sbit_image;
-    TT_Load_SBit_Metrics_Func    load_sbit_metrics;
-
-#endif
-
     TT_Load_SBit_Image_Func      load_sbit_image;
 
-#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
-    TT_Free_Table_Func           free_sbits_stub;
-#endif
-
     /* see `ttpost.h' */
     TT_Get_PS_Name_Func          get_psname;
     TT_Free_Table_Func           free_psnames;
 
-#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
-    TT_CharMap_Load_Func         load_charmap_stub;
-    TT_CharMap_Free_Func         free_charmap_stub;
-#endif
-
     /* starting here, the structure differs from version 2.1.7 */
 
     /* this field was introduced in version 2.1.8, named `get_psname' */
@@ -755,136 +560,141 @@
 
 #ifndef FT_CONFIG_OPTION_PIC
 
-#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
-#define FT_DEFINE_DRIVERS_OLD_INTERNAL(a) \
-  a,
-#else
-  #define FT_DEFINE_DRIVERS_OLD_INTERNAL(a)
-#endif
-#define FT_INTERNAL(a) \
-  a,
-
-#define FT_DEFINE_SFNT_INTERFACE(class_,                                     \
-    goto_table_, init_face_, load_face_, done_face_, get_interface_,         \
-    load_any_, load_sfnt_header_, load_directory_, load_head_,               \
-    load_hhea_, load_cmap_, load_maxp_, load_os2_, load_post_,               \
-    load_name_, free_name_, load_hdmx_stub_, free_hdmx_stub_,                \
-    load_kern_, load_gasp_, load_pclt_, load_bhed_,                          \
-    set_sbit_strike_stub_, load_sbits_stub_, find_sbit_image_,               \
-    load_sbit_metrics_, load_sbit_image_, free_sbits_stub_,                  \
-    get_psname_, free_psnames_, load_charmap_stub_, free_charmap_stub_,      \
-    get_kerning_, load_font_dir_, load_hmtx_, load_eblc_, free_eblc_,        \
-    set_sbit_strike_, load_strike_metrics_, get_metrics_ )                   \
-  static const SFNT_Interface class_ =                                       \
-  {                                                                          \
-    FT_INTERNAL(goto_table_) \
-    FT_INTERNAL(init_face_) \
-    FT_INTERNAL(load_face_) \
-    FT_INTERNAL(done_face_) \
-    FT_INTERNAL(get_interface_) \
-    FT_INTERNAL(load_any_) \
-    FT_DEFINE_DRIVERS_OLD_INTERNAL(load_sfnt_header_) \
-    FT_DEFINE_DRIVERS_OLD_INTERNAL(load_directory_) \
-    FT_INTERNAL(load_head_) \
-    FT_INTERNAL(load_hhea_) \
-    FT_INTERNAL(load_cmap_) \
-    FT_INTERNAL(load_maxp_) \
-    FT_INTERNAL(load_os2_) \
-    FT_INTERNAL(load_post_) \
-    FT_INTERNAL(load_name_) \
-    FT_INTERNAL(free_name_) \
-    FT_DEFINE_DRIVERS_OLD_INTERNAL(load_hdmx_stub_) \
-    FT_DEFINE_DRIVERS_OLD_INTERNAL(free_hdmx_stub_) \
-    FT_INTERNAL(load_kern_) \
-    FT_INTERNAL(load_gasp_) \
-    FT_INTERNAL(load_pclt_) \
-    FT_INTERNAL(load_bhed_) \
-    FT_DEFINE_DRIVERS_OLD_INTERNAL(set_sbit_strike_stub_) \
-    FT_DEFINE_DRIVERS_OLD_INTERNAL(load_sbits_stub_) \
-    FT_DEFINE_DRIVERS_OLD_INTERNAL(find_sbit_image_) \
-    FT_DEFINE_DRIVERS_OLD_INTERNAL(load_sbit_metrics_) \
-    FT_INTERNAL(load_sbit_image_) \
-    FT_DEFINE_DRIVERS_OLD_INTERNAL(free_sbits_stub_) \
-    FT_INTERNAL(get_psname_) \
-    FT_INTERNAL(free_psnames_) \
-    FT_DEFINE_DRIVERS_OLD_INTERNAL(load_charmap_stub_) \
-    FT_DEFINE_DRIVERS_OLD_INTERNAL(free_charmap_stub_) \
-    FT_INTERNAL(get_kerning_) \
-    FT_INTERNAL(load_font_dir_) \
-    FT_INTERNAL(load_hmtx_) \
-    FT_INTERNAL(load_eblc_) \
-    FT_INTERNAL(free_eblc_) \
-    FT_INTERNAL(set_sbit_strike_) \
-    FT_INTERNAL(load_strike_metrics_) \
-    FT_INTERNAL(get_metrics_) \
+#define FT_DEFINE_SFNT_INTERFACE(        \
+          class_,                        \
+          goto_table_,                   \
+          init_face_,                    \
+          load_face_,                    \
+          done_face_,                    \
+          get_interface_,                \
+          load_any_,                     \
+          load_head_,                    \
+          load_hhea_,                    \
+          load_cmap_,                    \
+          load_maxp_,                    \
+          load_os2_,                     \
+          load_post_,                    \
+          load_name_,                    \
+          free_name_,                    \
+          load_kern_,                    \
+          load_gasp_,                    \
+          load_pclt_,                    \
+          load_bhed_,                    \
+          load_sbit_image_,              \
+          get_psname_,                   \
+          free_psnames_,                 \
+          get_kerning_,                  \
+          load_font_dir_,                \
+          load_hmtx_,                    \
+          load_eblc_,                    \
+          free_eblc_,                    \
+          set_sbit_strike_,              \
+          load_strike_metrics_,          \
+          get_metrics_ )                 \
+  static const SFNT_Interface  class_ =  \
+  {                                      \
+    goto_table_,                         \
+    init_face_,                          \
+    load_face_,                          \
+    done_face_,                          \
+    get_interface_,                      \
+    load_any_,                           \
+    load_head_,                          \
+    load_hhea_,                          \
+    load_cmap_,                          \
+    load_maxp_,                          \
+    load_os2_,                           \
+    load_post_,                          \
+    load_name_,                          \
+    free_name_,                          \
+    load_kern_,                          \
+    load_gasp_,                          \
+    load_pclt_,                          \
+    load_bhed_,                          \
+    load_sbit_image_,                    \
+    get_psname_,                         \
+    free_psnames_,                       \
+    get_kerning_,                        \
+    load_font_dir_,                      \
+    load_hmtx_,                          \
+    load_eblc_,                          \
+    free_eblc_,                          \
+    set_sbit_strike_,                    \
+    load_strike_metrics_,                \
+    get_metrics_,                        \
   };
 
 #else /* FT_CONFIG_OPTION_PIC */
 
-#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
-#define FT_DEFINE_DRIVERS_OLD_INTERNAL(a, a_) \
-  clazz->a = a_;
-#else
-  #define FT_DEFINE_DRIVERS_OLD_INTERNAL(a, a_)
-#endif
-#define FT_INTERNAL(a, a_) \
-  clazz->a = a_;
+#define FT_INTERNAL( a, a_ )  \
+          clazz->a = a_;
 
-#define FT_DEFINE_SFNT_INTERFACE(class_,                                     \
-    goto_table_, init_face_, load_face_, done_face_, get_interface_,         \
-    load_any_, load_sfnt_header_, load_directory_, load_head_,               \
-    load_hhea_, load_cmap_, load_maxp_, load_os2_, load_post_,               \
-    load_name_, free_name_, load_hdmx_stub_, free_hdmx_stub_,                \
-    load_kern_, load_gasp_, load_pclt_, load_bhed_,                          \
-    set_sbit_strike_stub_, load_sbits_stub_, find_sbit_image_,               \
-    load_sbit_metrics_, load_sbit_image_, free_sbits_stub_,                  \
-    get_psname_, free_psnames_, load_charmap_stub_, free_charmap_stub_,      \
-    get_kerning_, load_font_dir_, load_hmtx_, load_eblc_, free_eblc_,        \
-    set_sbit_strike_, load_strike_metrics_, get_metrics_ )                   \
-  void                                                                       \
-  FT_Init_Class_##class_( FT_Library library, SFNT_Interface*  clazz )       \
-  {                                                                          \
-    FT_UNUSED(library);                                                      \
-    FT_INTERNAL(goto_table,goto_table_) \
-    FT_INTERNAL(init_face,init_face_) \
-    FT_INTERNAL(load_face,load_face_) \
-    FT_INTERNAL(done_face,done_face_) \
-    FT_INTERNAL(get_interface,get_interface_) \
-    FT_INTERNAL(load_any,load_any_) \
-    FT_DEFINE_DRIVERS_OLD_INTERNAL(load_sfnt_header,load_sfnt_header_) \
-    FT_DEFINE_DRIVERS_OLD_INTERNAL(load_directory,load_directory_) \
-    FT_INTERNAL(load_head,load_head_) \
-    FT_INTERNAL(load_hhea,load_hhea_) \
-    FT_INTERNAL(load_cmap,load_cmap_) \
-    FT_INTERNAL(load_maxp,load_maxp_) \
-    FT_INTERNAL(load_os2,load_os2_) \
-    FT_INTERNAL(load_post,load_post_) \
-    FT_INTERNAL(load_name,load_name_) \
-    FT_INTERNAL(free_name,free_name_) \
-    FT_DEFINE_DRIVERS_OLD_INTERNAL(load_hdmx_stub,load_hdmx_stub_) \
-    FT_DEFINE_DRIVERS_OLD_INTERNAL(free_hdmx_stub,free_hdmx_stub_) \
-    FT_INTERNAL(load_kern,load_kern_) \
-    FT_INTERNAL(load_gasp,load_gasp_) \
-    FT_INTERNAL(load_pclt,load_pclt_) \
-    FT_INTERNAL(load_bhed,load_bhed_) \
-    FT_DEFINE_DRIVERS_OLD_INTERNAL(set_sbit_strike_stub,set_sbit_strike_stub_) \
-    FT_DEFINE_DRIVERS_OLD_INTERNAL(load_sbits_stub,load_sbits_stub_) \
-    FT_DEFINE_DRIVERS_OLD_INTERNAL(find_sbit_image,find_sbit_image_) \
-    FT_DEFINE_DRIVERS_OLD_INTERNAL(load_sbit_metrics,load_sbit_metrics_) \
-    FT_INTERNAL(load_sbit_image,load_sbit_image_) \
-    FT_DEFINE_DRIVERS_OLD_INTERNAL(free_sbits_stub,free_sbits_stub_) \
-    FT_INTERNAL(get_psname,get_psname_) \
-    FT_INTERNAL(free_psnames,free_psnames_) \
-    FT_DEFINE_DRIVERS_OLD_INTERNAL(load_charmap_stub,load_charmap_stub_) \
-    FT_DEFINE_DRIVERS_OLD_INTERNAL(free_charmap_stub,free_charmap_stub_) \
-    FT_INTERNAL(get_kerning,get_kerning_) \
-    FT_INTERNAL(load_font_dir,load_font_dir_) \
-    FT_INTERNAL(load_hmtx,load_hmtx_) \
-    FT_INTERNAL(load_eblc,load_eblc_) \
-    FT_INTERNAL(free_eblc,free_eblc_) \
-    FT_INTERNAL(set_sbit_strike,set_sbit_strike_) \
-    FT_INTERNAL(load_strike_metrics,load_strike_metrics_) \
-    FT_INTERNAL(get_metrics,get_metrics_) \
+#define FT_DEFINE_SFNT_INTERFACE(                       \
+          class_,                                       \
+          goto_table_,                                  \
+          init_face_,                                   \
+          load_face_,                                   \
+          done_face_,                                   \
+          get_interface_,                               \
+          load_any_,                                    \
+          load_head_,                                   \
+          load_hhea_,                                   \
+          load_cmap_,                                   \
+          load_maxp_,                                   \
+          load_os2_,                                    \
+          load_post_,                                   \
+          load_name_,                                   \
+          free_name_,                                   \
+          load_kern_,                                   \
+          load_gasp_,                                   \
+          load_pclt_,                                   \
+          load_bhed_,                                   \
+          load_sbit_image_,                             \
+          get_psname_,                                  \
+          free_psnames_,                                \
+          get_kerning_,                                 \
+          load_font_dir_,                               \
+          load_hmtx_,                                   \
+          load_eblc_,                                   \
+          free_eblc_,                                   \
+          set_sbit_strike_,                             \
+          load_strike_metrics_,                         \
+          get_metrics_ )                                \
+  void                                                  \
+  FT_Init_Class_ ## class_( FT_Library       library,   \
+                            SFNT_Interface*  clazz )    \
+  {                                                     \
+    FT_UNUSED( library );                               \
+                                                        \
+    clazz->goto_table          = goto_table_;           \
+    clazz->init_face           = init_face_;            \
+    clazz->load_face           = load_face_;            \
+    clazz->done_face           = done_face_;            \
+    clazz->get_interface       = get_interface_;        \
+    clazz->load_any            = load_any_;             \
+    clazz->load_head           = load_head_;            \
+    clazz->load_hhea           = load_hhea_;            \
+    clazz->load_cmap           = load_cmap_;            \
+    clazz->load_maxp           = load_maxp_;            \
+    clazz->load_os2            = load_os2_;             \
+    clazz->load_post           = load_post_;            \
+    clazz->load_name           = load_name_;            \
+    clazz->free_name           = free_name_;            \
+    clazz->load_kern           = load_kern_;            \
+    clazz->load_gasp           = load_gasp_;            \
+    clazz->load_pclt           = load_pclt_;            \
+    clazz->load_bhed           = load_bhed_;            \
+    clazz->load_sbit_image     = load_sbit_image_;      \
+    clazz->get_psname          = get_psname_;           \
+    clazz->free_psnames        = free_psnames_;         \
+    clazz->get_kerning         = get_kerning_;          \
+    clazz->load_font_dir       = load_font_dir_;        \
+    clazz->load_hmtx           = load_hmtx_;            \
+    clazz->load_eblc           = load_eblc_;            \
+    clazz->free_eblc           = free_eblc_;            \
+    clazz->set_sbit_strike     = set_sbit_strike_;      \
+    clazz->load_strike_metrics = load_strike_metrics_;  \
+    clazz->get_metrics         = get_metrics_;          \
   }
 
 #endif /* FT_CONFIG_OPTION_PIC */
diff --git a/include/freetype/internal/t1types.h b/include/freetype/internal/t1types.h
index f859de2..e20237c 100644
--- a/include/freetype/internal/t1types.h
+++ b/include/freetype/internal/t1types.h
@@ -5,7 +5,7 @@
 /*    Basic Type1/Type2 type definitions and interface (specification      */
 /*    only).                                                               */
 /*                                                                         */
-/*  Copyright 1996-2004, 2006, 2008, 2009, 2011 by                         */
+/*  Copyright 1996-2004, 2006, 2008, 2009, 2011, 2013 by                   */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -205,10 +205,6 @@
     FT_CharMapRec   charmaprecs[2];
     FT_CharMap      charmaps[2];
 
-#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
-    PS_Unicodes     unicode_map;
-#endif
-
     /* support for Multiple Masters fonts */
     PS_Blend        blend;
 
diff --git a/include/freetype/internal/tttypes.h b/include/freetype/internal/tttypes.h
index 57b1731..1bbfe49 100644
--- a/include/freetype/internal/tttypes.h
+++ b/include/freetype/internal/tttypes.h
@@ -5,7 +5,7 @@
 /*    Basic SFNT/TrueType type definitions and interface (specification    */
 /*    only).                                                               */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2004, 2005, 2006, 2007, 2008 by             */
+/*  Copyright 1996-2002, 2004-2008, 2012-2013 by                           */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -311,87 +311,6 @@
   } TT_GaspRec;
 
 
-#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Struct>                                                              */
-  /*    TT_HdmxEntryRec                                                    */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    A small structure used to model the pre-computed widths of a given */
-  /*    size.  They are found in the `hdmx' table.                         */
-  /*                                                                       */
-  /* <Fields>                                                              */
-  /*    ppem      :: The pixels per EM value at which these metrics apply. */
-  /*                                                                       */
-  /*    max_width :: The maximum advance width for this metric.            */
-  /*                                                                       */
-  /*    widths    :: An array of widths.  Note: These are 8-bit bytes.     */
-  /*                                                                       */
-  typedef struct  TT_HdmxEntryRec_
-  {
-    FT_Byte   ppem;
-    FT_Byte   max_width;
-    FT_Byte*  widths;
-
-  } TT_HdmxEntryRec, *TT_HdmxEntry;
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Struct>                                                              */
-  /*    TT_HdmxRec                                                         */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    A structure used to model the `hdmx' table, which contains         */
-  /*    pre-computed widths for a set of given sizes/dimensions.           */
-  /*                                                                       */
-  /* <Fields>                                                              */
-  /*    version     :: The version number.                                 */
-  /*                                                                       */
-  /*    num_records :: The number of hdmx records.                         */
-  /*                                                                       */
-  /*    records     :: An array of hdmx records.                           */
-  /*                                                                       */
-  typedef struct  TT_HdmxRec_
-  {
-    FT_UShort     version;
-    FT_Short      num_records;
-    TT_HdmxEntry  records;
-
-  } TT_HdmxRec, *TT_Hdmx;
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Struct>                                                              */
-  /*    TT_Kern0_PairRec                                                   */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    A structure used to model a kerning pair for the kerning table     */
-  /*    format 0.  The engine now loads this table if it finds one in the  */
-  /*    font file.                                                         */
-  /*                                                                       */
-  /* <Fields>                                                              */
-  /*    left  :: The index of the left glyph in pair.                      */
-  /*                                                                       */
-  /*    right :: The index of the right glyph in pair.                     */
-  /*                                                                       */
-  /*    value :: The kerning distance.  A positive value spaces the        */
-  /*             glyphs, a negative one makes them closer.                 */
-  /*                                                                       */
-  typedef struct  TT_Kern0_PairRec_
-  {
-    FT_UShort  left;   /* index of left  glyph in pair */
-    FT_UShort  right;  /* index of right glyph in pair */
-    FT_FWord   value;  /* kerning value                */
-
-  } TT_Kern0_PairRec, *TT_Kern0_Pair;
-
-#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
-
-
   /*************************************************************************/
   /*************************************************************************/
   /*************************************************************************/
@@ -1269,9 +1188,6 @@
     TT_HoriHeader         horizontal;   /* TrueType horizontal header     */
 
     TT_MaxProfile         max_profile;
-#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
-    FT_ULong              max_components;  /* stubbed to 0 */
-#endif
 
     FT_Bool               vertical_info;
     TT_VertHeader         vertical;     /* TT Vertical header, if present */
@@ -1308,11 +1224,6 @@
     /*                                                                     */
     /***********************************************************************/
 
-    /* horizontal device metrics */
-#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
-    TT_HdmxRec            hdmx;
-#endif
-
     /* grid-fitting and scaling table */
     TT_GaspRec            gasp;                 /* the `gasp' table */
 
@@ -1320,11 +1231,6 @@
     TT_PCLT               pclt;
 
     /* embedded bitmaps support */
-#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
-    FT_ULong              num_sbit_strikes;
-    TT_SBit_Strike        sbit_strikes;
-#endif
-
     FT_ULong              num_sbit_scales;
     TT_SBit_Scale         sbit_scales;
 
@@ -1338,12 +1244,6 @@
     /*                                                                     */
     /***********************************************************************/
 
-    /* the glyph locations */
-#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
-    FT_UShort             num_locations_stub;
-    FT_Long*              glyph_locations_stub;
-#endif
-
     /* the font program, if any */
     FT_ULong              font_program_size;
     FT_Byte*              font_program;
@@ -1356,13 +1256,6 @@
     FT_ULong              cvt_size;
     FT_Short*             cvt;
 
-#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
-    /* the format 0 kerning table, if any */
-    FT_Int                num_kern_pairs;
-    FT_Int                kern_table_index;
-    TT_Kern0_Pair         kern_pairs;
-#endif
-
     /* A pointer to the bytecode interpreter to use.  This is also */
     /* used to hook the debugger for the `ttdebug' utility.        */
     TT_Interpreter        interpreter;
@@ -1383,11 +1276,8 @@
 
     const char*           postscript_name;
 
-    /* since version 2.1.8, but was originally placed after */
-    /* `glyph_locations_stub'                               */
     FT_ULong              glyf_len;
 
-    /* since version 2.1.8, but was originally placed before `extra' */
 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
     FT_Bool               doblend;
     GX_Blend              blend;
@@ -1428,6 +1318,13 @@
     FT_ULong              horz_metrics_offset;
     FT_ULong              vert_metrics_offset;
 
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+    /* since 2.4.12 */
+    FT_ULong              sph_found_func_flags; /* special functions found */
+                                                /* for this face           */
+    FT_Bool               sph_compatibility_mode;
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
   } TT_FaceRec;
 
 
@@ -1443,7 +1340,7 @@
   /*  <Fields>                                                             */
   /*     memory       :: A handle to the memory manager.                   */
   /*                                                                       */
-  /*     max_points   :: The maximal size in points of the zone.           */
+  /*     max_points   :: The maximum size in points of the zone.           */
   /*                                                                       */
   /*     max_contours :: Max size in links contours of the zone.           */
   /*                                                                       */
diff --git a/include/freetype/ttnameid.h b/include/freetype/ttnameid.h
index 66aef04..173f88c 100644
--- a/include/freetype/ttnameid.h
+++ b/include/freetype/ttnameid.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    TrueType name ID definitions (specification only).                   */
 /*                                                                         */
-/*  Copyright 1996-2002, 2003, 2004, 2006, 2007, 2008 by                   */
+/*  Copyright 1996-2004, 2006-2008, 2012 by                                */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -316,11 +316,12 @@
   /*                                                                       */
   /* Possible values of the language identifier field in the name records  */
   /* of the TTF `name' table if the `platform' identifier code is          */
-  /* TT_PLATFORM_MACINTOSH.                                                */
+  /* TT_PLATFORM_MACINTOSH.  These values are also used as return values   */
+  /* for function @FT_Get_CMap_Language_ID.                                */
   /*                                                                       */
   /* The canonical source for the Apple assigned Language ID's is at       */
   /*                                                                       */
-  /*   http://fonts.apple.com/TTRefMan/RM06/Chap6name.html                 */
+  /*   https://developer.apple.com/fonts/TTRefMan/RM06/Chap6name.html      */
   /*                                                                       */
 #define TT_MAC_LANGID_ENGLISH                       0
 #define TT_MAC_LANGID_FRENCH                        1
@@ -461,21 +462,10 @@
   /* of the TTF `name' table if the `platform' identifier code is          */
   /* TT_PLATFORM_MICROSOFT.                                                */
   /*                                                                       */
-  /* The canonical source for the MS assigned LCID's (seems to) be at      */
+  /* The canonical source for the MS assigned LCIDs is                     */
   /*                                                                       */
   /*   http://www.microsoft.com/globaldev/reference/lcid-all.mspx          */
   /*                                                                       */
-  /* It used to be at various places, among them                           */
-  /*                                                                       */
-  /*   http://www.microsoft.com/typography/OTSPEC/lcid-cp.txt              */
-  /*   http://www.microsoft.com/globaldev/reference/loclanghome.asp        */
-  /*   http://support.microsoft.com/support/kb/articles/Q224/8/04.ASP      */
-  /*   http://msdn.microsoft.com/library/en-us/passport25/                 */
-  /*           NET_Passport_VBScript_Documentation/Single_Sign_In/         */
-  /*           Advanced_Single_Sign_In/Localization_and_LCIDs.asp          */
-  /*                                                                       */
-  /* Hopefully, it seems now that the Globaldev site prevails...           */
-  /*                                   (updated by Antoine, 2004-02-17)    */
 
 #define TT_MS_LANGID_ARABIC_GENERAL                    0x0001
 #define TT_MS_LANGID_ARABIC_SAUDI_ARABIA               0x0401
diff --git a/include/freetype/tttables.h b/include/freetype/tttables.h
index 02236c2..fe07117 100644
--- a/include/freetype/tttables.h
+++ b/include/freetype/tttables.h
@@ -5,7 +5,7 @@
 /*    Basic SFNT/TrueType tables definitions and interface                 */
 /*    (specification only).                                                */
 /*                                                                         */
-/*  Copyright 1996-2005, 2008-2011 by                                      */
+/*  Copyright 1996-2005, 2008-2012 by                                      */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -600,6 +600,16 @@
   /*    by the sfnt, truetype, and opentype drivers.  See @FT_Sfnt_Tag for */
   /*    a list.                                                            */
   /*                                                                       */
+  /*    Here an example how to access the `vhea' table:                    */
+  /*                                                                       */
+  /*    {                                                                  */
+  /*      TT_VertHeader*  vert_header;                                     */
+  /*                                                                       */
+  /*                                                                       */
+  /*      vert_header =                                                    */
+  /*        (TT_VertHeader*)FT_Get_Sfnt_Table( face, ft_sfnt_vhea );       */
+  /*    }                                                                  */
+  /*                                                                       */
   FT_EXPORT( void* )
   FT_Get_Sfnt_Table( FT_Face      face,
                      FT_Sfnt_Tag  tag );
@@ -702,7 +712,8 @@
   *   FreeType error code.  0~means success.
   *
   * @note:
-  *   SFNT tables with length zero are treated as missing.
+  *   While parsing fonts, FreeType handles SFNT tables with length zero as
+  *   missing.
   *
   */
   FT_EXPORT( FT_Error )
@@ -729,6 +740,9 @@
   /*    The language ID of `charmap'.  If `charmap' doesn't belong to a    */
   /*    TrueType/sfnt face, just return~0 as the default value.            */
   /*                                                                       */
+  /*    For a format~14 cmap (to access Unicode IVS), the return value is  */
+  /*    0xFFFFFFFF.                                                        */
+  /*                                                                       */
   FT_EXPORT( FT_ULong )
   FT_Get_CMap_Language_ID( FT_CharMap  charmap );
 
diff --git a/include/freetype/tttags.h b/include/freetype/tttags.h
index 307ce4b..be8c524 100644
--- a/include/freetype/tttags.h
+++ b/include/freetype/tttags.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Tags for TrueType and OpenType tables (specification only).          */
 /*                                                                         */
-/*  Copyright 1996-2001, 2004, 2005, 2007, 2008 by                         */
+/*  Copyright 1996-2001, 2004, 2005, 2007, 2008, 2013 by                   */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -40,6 +40,8 @@
 #define TTAG_bhed  FT_MAKE_TAG( 'b', 'h', 'e', 'd' )
 #define TTAG_bloc  FT_MAKE_TAG( 'b', 'l', 'o', 'c' )
 #define TTAG_bsln  FT_MAKE_TAG( 'b', 's', 'l', 'n' )
+#define TTAG_CBDT  FT_MAKE_TAG( 'C', 'B', 'D', 'T' )
+#define TTAG_CBLC  FT_MAKE_TAG( 'C', 'B', 'L', 'C' )
 #define TTAG_CFF   FT_MAKE_TAG( 'C', 'F', 'F', ' ' )
 #define TTAG_CID   FT_MAKE_TAG( 'C', 'I', 'D', ' ' )
 #define TTAG_cmap  FT_MAKE_TAG( 'c', 'm', 'a', 'p' )
diff --git a/src/autofit/afangles.c b/src/autofit/afangles.c
index 790af17..b44a5ba 100644
--- a/src/autofit/afangles.c
+++ b/src/autofit/afangles.c
@@ -5,7 +5,7 @@
 /*    Routines used to compute vector angles with limited accuracy         */
 /*    and very high speed.  It also contains sorting routines (body).      */
 /*                                                                         */
-/*  Copyright 2003-2006, 2011 by                                           */
+/*  Copyright 2003-2006, 2011-2012 by                                      */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -255,7 +255,7 @@
     {
       for ( j = i; j > 0; j-- )
       {
-        if ( table[j] > table[j - 1] )
+        if ( table[j] >= table[j - 1] )
           break;
 
         swap         = table[j];
@@ -267,18 +267,26 @@
 
 
   FT_LOCAL_DEF( void )
-  af_sort_widths( FT_UInt   count,
-                  AF_Width  table )
+  af_sort_and_quantize_widths( FT_UInt*  count,
+                               AF_Width  table,
+                               FT_Pos    threshold )
   {
     FT_UInt      i, j;
+    FT_UInt      cur_idx;
+    FT_Pos       cur_val;
+    FT_Pos       sum;
     AF_WidthRec  swap;
 
 
-    for ( i = 1; i < count; i++ )
+    if ( *count == 1 )
+      return;
+
+    /* sort */
+    for ( i = 1; i < *count; i++ )
     {
       for ( j = i; j > 0; j-- )
       {
-        if ( table[j].org > table[j - 1].org )
+        if ( table[j].org >= table[j - 1].org )
           break;
 
         swap         = table[j];
@@ -286,6 +294,51 @@
         table[j - 1] = swap;
       }
     }
+
+    cur_idx = 0;
+    cur_val = table[cur_idx].org;
+
+    /* compute and use mean values for clusters not larger than  */
+    /* `threshold'; this is very primitive and might not yield   */
+    /* the best result, but normally, using reference character  */
+    /* `o', `*count' is 2, so the code below is fully sufficient */
+    for ( i = 1; i < *count; i++ )
+    {
+      if ( table[i].org - cur_val > threshold ||
+           i == *count - 1                    )
+      {
+        sum = 0;
+
+        /* fix loop for end of array */
+        if ( table[i].org - cur_val <= threshold &&
+             i == *count - 1                     )
+          i++;
+
+        for ( j = cur_idx; j < i; j++ )
+        {
+          sum         += table[j].org;
+          table[j].org = 0;
+        }
+        table[cur_idx].org = sum / j;
+
+        if ( i < *count - 1 )
+        {
+          cur_idx = i + 1;
+          cur_val = table[cur_idx].org;
+        }
+      }
+    }
+
+    cur_idx = 1;
+
+    /* compress array to remove zero values */
+    for ( i = 1; i < *count; i++ )
+    {
+      if ( table[i].org )
+        table[cur_idx++] = table[i];
+    }
+
+    *count = cur_idx;
   }
 
 
diff --git a/src/autofit/afcjk.c b/src/autofit/afcjk.c
index 8e407c8..f69a528 100644
--- a/src/autofit/afcjk.c
+++ b/src/autofit/afcjk.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter hinting routines for CJK script (body).                  */
 /*                                                                         */
-/*  Copyright 2006-2012 by                                                 */
+/*  Copyright 2006-2013 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -67,8 +67,7 @@
 
   FT_LOCAL_DEF( void )
   af_cjk_metrics_init_widths( AF_CJKMetrics  metrics,
-                              FT_Face        face,
-                              FT_ULong       charcode )
+                              FT_Face        face )
   {
     /* scan the array of segments in each direction */
     AF_GlyphHintsRec  hints[1];
@@ -87,7 +86,8 @@
       AF_Scaler         scaler = &dummy->root.scaler;
 
 
-      glyph_index = FT_Get_Char_Index( face, charcode );
+      glyph_index = FT_Get_Char_Index( face,
+                                       metrics->root.clazz->standard_char );
       if ( glyph_index == 0 )
         goto Exit;
 
@@ -150,7 +150,10 @@
           }
         }
 
-        af_sort_widths( num_widths, axis->widths );
+        /* this also replaces multiple almost identical stem widths */
+        /* with a single one (the value 100 is heuristic) */
+        af_sort_and_quantize_widths( &num_widths, axis->widths,
+                                     dummy->units_per_em / 100 );
         axis->width_count = num_widths;
       }
 
@@ -478,7 +481,8 @@
         FT_Bool  under_ref = FT_BOOL( shoot < ref );
 
 
-        if ( (AF_CJK_BLUE_TOP == bb || AF_CJK_BLUE_RIGHT == bb) ^ under_ref )
+        if ( ( AF_CJK_BLUE_TOP == bb   ||
+               AF_CJK_BLUE_RIGHT == bb ) ^ under_ref )
           *blue_shoot = *blue_ref = ( shoot + ref ) / 2;
       }
 
@@ -556,14 +560,14 @@
       face->charmap = NULL;
     else
     {
-      af_cjk_metrics_init_widths( metrics, face, 0x7530 );
+      af_cjk_metrics_init_widths( metrics, face );
       af_cjk_metrics_init_blues( metrics, face, af_cjk_hani_blue_chars );
       af_cjk_metrics_check_digits( metrics, face );
     }
 
     FT_Set_Charmap( face, oldmap );
 
-    return AF_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
@@ -699,7 +703,7 @@
     {
       AF_Point  pt   = seg->first;
       AF_Point  last = seg->last;
-      AF_Flags  f0   = (AF_Flags)(pt->flags & AF_FLAG_CONTROL);
+      AF_Flags  f0   = (AF_Flags)( pt->flags & AF_FLAG_CONTROL );
       AF_Flags  f1;
 
 
@@ -708,7 +712,7 @@
       for ( ; pt != last; f0 = f1 )
       {
         pt = pt->next;
-        f1 = (AF_Flags)(pt->flags & AF_FLAG_CONTROL);
+        f1 = (AF_Flags)( pt->flags & AF_FLAG_CONTROL );
 
         if ( !f0 && !f1 )
           break;
@@ -718,7 +722,7 @@
       }
     }
 
-    return AF_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
@@ -892,7 +896,7 @@
                               AF_Dimension   dim )
   {
     AF_AxisHints  axis   = &hints->axis[dim];
-    FT_Error      error  = AF_Err_Ok;
+    FT_Error      error  = FT_Err_Ok;
     FT_Memory     memory = hints->memory;
     AF_CJKAxis    laxis  = &((AF_CJKMetrics)hints->metrics)->axis[dim];
 
@@ -962,14 +966,15 @@
           /* can make a single edge.                                 */
           if ( link )
           {
-            AF_Segment  seg1 = edge->first;
-            AF_Segment  link1;
+            AF_Segment  seg1  = edge->first;
             FT_Pos      dist2 = 0;
 
 
             do
             {
-              link1 = seg1->link;
+              AF_Segment  link1 = seg1->link;
+
+
               if ( link1 )
               {
                 dist2 = AF_SEGMENT_DIST( link, link1 );
@@ -2190,6 +2195,7 @@
 
   static const AF_Script_UniRangeRec  af_cjk_uniranges[] =
   {
+    AF_UNIRANGE_REC(  0x1100UL,  0x11FFUL ),  /* Hangul Jamo                             */
     AF_UNIRANGE_REC(  0x2E80UL,  0x2EFFUL ),  /* CJK Radicals Supplement                 */
     AF_UNIRANGE_REC(  0x2F00UL,  0x2FDFUL ),  /* Kangxi Radicals                         */
     AF_UNIRANGE_REC(  0x2FF0UL,  0x2FFFUL ),  /* Ideographic Description Characters      */
@@ -2228,6 +2234,7 @@
   AF_DEFINE_SCRIPT_CLASS( af_cjk_script_class,
     AF_SCRIPT_CJK,
     af_cjk_uniranges,
+    0x7530, /* ç”° */
 
     sizeof ( AF_CJKMetricsRec ),
 
@@ -2250,6 +2257,7 @@
   AF_DEFINE_SCRIPT_CLASS( af_cjk_script_class,
     AF_SCRIPT_CJK,
     af_cjk_uniranges,
+    0,
 
     sizeof ( AF_CJKMetricsRec ),
 
diff --git a/src/autofit/afcjk.h b/src/autofit/afcjk.h
index 8416c0d..ab816f2 100644
--- a/src/autofit/afcjk.h
+++ b/src/autofit/afcjk.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter hinting routines for CJK script (specification).         */
 /*                                                                         */
-/*  Copyright 2006, 2007, 2011 by                                          */
+/*  Copyright 2006, 2007, 2011, 2012 by                                    */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -28,7 +28,7 @@
 
   /* the CJK-specific script class */
 
-  AF_DECLARE_SCRIPT_CLASS(af_cjk_script_class)
+  AF_DECLARE_SCRIPT_CLASS( af_cjk_script_class )
 
   /* CJK (global) metrics management */
 
@@ -103,6 +103,7 @@
   } AF_CJKMetricsRec, *AF_CJKMetrics;
 
 
+#ifdef AF_CONFIG_OPTION_CJK
   FT_LOCAL( FT_Error )
   af_cjk_metrics_init( AF_CJKMetrics  metrics,
                        FT_Face        face );
@@ -120,15 +121,15 @@
                       FT_Outline*    outline,
                       AF_CJKMetrics  metrics );
 
-  /* Shared. called from afindic.c */
+  /* shared; called from afindic.c */
   FT_LOCAL( void )
   af_cjk_metrics_check_digits( AF_CJKMetrics  metrics,
                                FT_Face        face );
 
   FT_LOCAL( void )
   af_cjk_metrics_init_widths( AF_CJKMetrics  metrics,
-                              FT_Face        face,
-                              FT_ULong       charcode );
+                              FT_Face        face );
+#endif /* AF_CONFIG_OPTION_CJK */
 
 
 /* */
diff --git a/src/autofit/afdummy.c b/src/autofit/afdummy.c
index 4bf278c..2294455 100644
--- a/src/autofit/afdummy.c
+++ b/src/autofit/afdummy.c
@@ -5,7 +5,7 @@
 /*    Auto-fitter dummy routines to be used if no hinting should be        */
 /*    performed (body).                                                    */
 /*                                                                         */
-/*  Copyright 2003-2005, 2011 by                                           */
+/*  Copyright 2003-2005, 2011, 2013 by                                     */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -28,7 +28,7 @@
   {
     af_glyph_hints_rescale( hints,
                             metrics );
-    return AF_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
@@ -39,13 +39,14 @@
     FT_UNUSED( hints );
     FT_UNUSED( outline );
 
-    return AF_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
   AF_DEFINE_SCRIPT_CLASS( af_dummy_script_class,
-    AF_SCRIPT_NONE,
+    AF_SCRIPT_DUMMY,
     NULL,
+    0,
 
     sizeof ( AF_ScriptMetricsRec ),
 
diff --git a/src/autofit/afglobal.c b/src/autofit/afglobal.c
index 3e0c02d..3e41465 100644
--- a/src/autofit/afglobal.c
+++ b/src/autofit/afglobal.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter routines to compute global hinting values (body).        */
 /*                                                                         */
-/*  Copyright 2003-2011 by                                                 */
+/*  Copyright 2003-2013 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -49,55 +49,33 @@
 
 #endif /* !FT_CONFIG_OPTION_PIC */
 
-  /* index of default script in `af_script_classes' */
-#define AF_SCRIPT_LIST_DEFAULT  2
-  /* a bit mask indicating an uncovered glyph       */
-#define AF_SCRIPT_LIST_NONE     0x7F
-  /* if this flag is set, we have an ASCII digit    */
-#define AF_DIGIT                0x80
-
-
-  /*
-   *  Note that glyph_scripts[] is used to map each glyph into
-   *  an index into the `af_script_classes' array.
-   *
-   */
-  typedef struct  AF_FaceGlobalsRec_
-  {
-    FT_Face           face;
-    FT_Long           glyph_count;    /* same as face->num_glyphs */
-    FT_Byte*          glyph_scripts;
-
-    AF_ScriptMetrics  metrics[AF_SCRIPT_MAX];
-
-  } AF_FaceGlobalsRec;
-
 
   /* Compute the script index of each glyph within a given face. */
 
   static FT_Error
   af_face_globals_compute_script_coverage( AF_FaceGlobals  globals )
   {
-    FT_Error    error       = AF_Err_Ok;
+    FT_Error    error;
     FT_Face     face        = globals->face;
     FT_CharMap  old_charmap = face->charmap;
     FT_Byte*    gscripts    = globals->glyph_scripts;
-    FT_UInt     ss, i;
+    FT_UInt     ss;
+    FT_UInt     i;
 
 
-    /* the value AF_SCRIPT_LIST_NONE means `uncovered glyph' */
+    /* the value AF_SCRIPT_NONE means `uncovered glyph' */
     FT_MEM_SET( globals->glyph_scripts,
-                AF_SCRIPT_LIST_NONE,
+                AF_SCRIPT_NONE,
                 globals->glyph_count );
 
     error = FT_Select_Charmap( face, FT_ENCODING_UNICODE );
     if ( error )
     {
      /*
-      *  Ignore this error; we simply use the default script.
+      *  Ignore this error; we simply use the fallback script.
       *  XXX: Shouldn't we rather disable hinting?
       */
-      error = AF_Err_Ok;
+      error = FT_Err_Ok;
       goto Exit;
     }
 
@@ -112,7 +90,7 @@
         continue;
 
       /*
-       *  Scan all unicode points in the range and set the corresponding
+       *  Scan all Unicode points in the range and set the corresponding
        *  glyph script index.
        */
       for ( range = clazz->script_uni_ranges; range->first != 0; range++ )
@@ -125,7 +103,7 @@
 
         if ( gindex != 0                             &&
              gindex < (FT_ULong)globals->glyph_count &&
-             gscripts[gindex] == AF_SCRIPT_LIST_NONE )
+             gscripts[gindex] == AF_SCRIPT_NONE )
           gscripts[gindex] = (FT_Byte)ss;
 
         for (;;)
@@ -136,7 +114,7 @@
             break;
 
           if ( gindex < (FT_ULong)globals->glyph_count &&
-               gscripts[gindex] == AF_SCRIPT_LIST_NONE )
+               gscripts[gindex] == AF_SCRIPT_NONE )
             gscripts[gindex] = (FT_Byte)ss;
         }
       }
@@ -154,19 +132,20 @@
 
   Exit:
     /*
-     *  By default, all uncovered glyphs are set to the latin script.
+     *  By default, all uncovered glyphs are set to the fallback script.
      *  XXX: Shouldn't we disable hinting or do something similar?
      */
+    if ( globals->module->fallback_script != AF_SCRIPT_NONE )
     {
       FT_Long  nn;
 
 
       for ( nn = 0; nn < globals->glyph_count; nn++ )
       {
-        if ( ( gscripts[nn] & ~AF_DIGIT ) == AF_SCRIPT_LIST_NONE )
+        if ( ( gscripts[nn] & ~AF_DIGIT ) == AF_SCRIPT_NONE )
         {
-          gscripts[nn] &= ~AF_SCRIPT_LIST_NONE;
-          gscripts[nn] |= AF_SCRIPT_LIST_DEFAULT;
+          gscripts[nn] &= ~AF_SCRIPT_NONE;
+          gscripts[nn] |= globals->module->fallback_script;
         }
       }
     }
@@ -178,7 +157,8 @@
 
   FT_LOCAL_DEF( FT_Error )
   af_face_globals_new( FT_Face          face,
-                       AF_FaceGlobals  *aglobals )
+                       AF_FaceGlobals  *aglobals,
+                       AF_Module        module )
   {
     FT_Error        error;
     FT_Memory       memory;
@@ -187,21 +167,25 @@
 
     memory = face->memory;
 
-    if ( !FT_ALLOC( globals, sizeof ( *globals ) +
-                             face->num_glyphs * sizeof ( FT_Byte ) ) )
-    {
-      globals->face          = face;
-      globals->glyph_count   = face->num_glyphs;
-      globals->glyph_scripts = (FT_Byte*)( globals + 1 );
+    if ( FT_ALLOC( globals, sizeof ( *globals ) +
+                            face->num_glyphs * sizeof ( FT_Byte ) ) )
+      goto Exit;
 
-      error = af_face_globals_compute_script_coverage( globals );
-      if ( error )
-      {
-        af_face_globals_free( globals );
-        globals = NULL;
-      }
+    globals->face          = face;
+    globals->glyph_count   = face->num_glyphs;
+    globals->glyph_scripts = (FT_Byte*)( globals + 1 );
+    globals->module        = module;
+
+    error = af_face_globals_compute_script_coverage( globals );
+    if ( error )
+    {
+      af_face_globals_free( globals );
+      globals = NULL;
     }
 
+    globals->increase_x_height = AF_PROP_INCREASE_X_HEIGHT_MAX;
+
+  Exit:
     *aglobals = globals;
     return error;
   }
@@ -253,18 +237,18 @@
     FT_UInt           script     = options & 15;
     const FT_Offset   script_max = sizeof ( AF_SCRIPT_CLASSES_GET ) /
                                      sizeof ( AF_SCRIPT_CLASSES_GET[0] );
-    FT_Error          error      = AF_Err_Ok;
+    FT_Error          error      = FT_Err_Ok;
 
 
     if ( gindex >= (FT_ULong)globals->glyph_count )
     {
-      error = AF_Err_Invalid_Argument;
+      error = FT_THROW( Invalid_Argument );
       goto Exit;
     }
 
     gidx = script;
     if ( gidx == 0 || gidx + 1 >= script_max )
-      gidx = globals->glyph_scripts[gindex] & AF_SCRIPT_LIST_NONE;
+      gidx = globals->glyph_scripts[gindex] & AF_SCRIPT_NONE;
 
     clazz = AF_SCRIPT_CLASSES_GET[gidx];
     if ( script == 0 )
@@ -273,14 +257,15 @@
     metrics = globals->metrics[clazz->script];
     if ( metrics == NULL )
     {
-      /* create the global metrics object when needed */
+      /* create the global metrics object if necessary */
       FT_Memory  memory = globals->face->memory;
 
 
       if ( FT_ALLOC( metrics, clazz->script_metrics_size ) )
         goto Exit;
 
-      metrics->clazz = clazz;
+      metrics->clazz   = clazz;
+      metrics->globals = globals;
 
       if ( clazz->script_metrics_init )
       {
diff --git a/src/autofit/afglobal.h b/src/autofit/afglobal.h
index cc6860b..2e24900 100644
--- a/src/autofit/afglobal.h
+++ b/src/autofit/afglobal.h
@@ -5,7 +5,7 @@
 /*    Auto-fitter routines to compute global hinting values                */
 /*    (specification).                                                     */
 /*                                                                         */
-/*  Copyright 2003-2005, 2007, 2009, 2011 by                               */
+/*  Copyright 2003-2005, 2007, 2009, 2011-2012 by                          */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -22,11 +22,29 @@
 
 
 #include "aftypes.h"
+#include "afmodule.h"
 
 
 FT_BEGIN_HEADER
 
 
+  /*
+   *  Default values and flags for both autofitter globals (found in
+   *  AF_ModuleRec) and face globals (in AF_FaceGlobalsRec).
+   */
+
+  /* index of fallback script in `af_script_classes' */
+#define AF_SCRIPT_FALLBACK  2
+  /* a bit mask indicating an uncovered glyph        */
+#define AF_SCRIPT_NONE      0x7F
+  /* if this flag is set, we have an ASCII digit     */
+#define AF_DIGIT            0x80
+
+  /* `increase-x-height' property */
+#define AF_PROP_INCREASE_X_HEIGHT_MIN  6
+#define AF_PROP_INCREASE_X_HEIGHT_MAX  0
+
+
   /************************************************************************/
   /************************************************************************/
   /*****                                                              *****/
@@ -37,15 +55,35 @@
 
 
   /*
+   *  Note that glyph_scripts[] is used to map each glyph into
+   *  an index into the `af_script_classes' array.
+   *
+   */
+  typedef struct  AF_FaceGlobalsRec_
+  {
+    FT_Face           face;
+    FT_Long           glyph_count;    /* same as face->num_glyphs */
+    FT_Byte*          glyph_scripts;
+
+    /* per-face auto-hinter properties */
+    FT_UInt           increase_x_height;
+
+    AF_ScriptMetrics  metrics[AF_SCRIPT_MAX];
+
+    AF_Module         module;         /* to access global properties */
+
+  } AF_FaceGlobalsRec;
+
+
+  /*
    *  model the global hints data for a given face, decomposed into
    *  script-specific items
    */
-  typedef struct AF_FaceGlobalsRec_*   AF_FaceGlobals;
-
 
   FT_LOCAL( FT_Error )
   af_face_globals_new( FT_Face          face,
-                       AF_FaceGlobals  *aglobals );
+                       AF_FaceGlobals  *aglobals,
+                       AF_Module        module );
 
   FT_LOCAL( FT_Error )
   af_face_globals_get_metrics( AF_FaceGlobals     globals,
diff --git a/src/autofit/afhints.c b/src/autofit/afhints.c
index f51066f..e8defaa 100644
--- a/src/autofit/afhints.c
+++ b/src/autofit/afhints.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter hinting routines (body).                                 */
 /*                                                                         */
-/*  Copyright 2003-2007, 2009-2011 by                                      */
+/*  Copyright 2003-2007, 2009-2013 by                                      */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -19,6 +19,17 @@
 #include "afhints.h"
 #include "aferrors.h"
 #include FT_INTERNAL_CALC_H
+#include FT_INTERNAL_DEBUG_H
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_afhints
 
 
   /* Get new segment for given axis. */
@@ -28,7 +39,7 @@
                              FT_Memory     memory,
                              AF_Segment   *asegment )
   {
-    FT_Error    error   = AF_Err_Ok;
+    FT_Error    error   = FT_Err_Ok;
     AF_Segment  segment = NULL;
 
 
@@ -41,7 +52,7 @@
 
       if ( old_max >= big_max )
       {
-        error = AF_Err_Out_Of_Memory;
+        error = FT_THROW( Out_Of_Memory );
         goto Exit;
       }
 
@@ -70,9 +81,9 @@
                           FT_Int        fpos,
                           AF_Direction  dir,
                           FT_Memory     memory,
-                          AF_Edge      *aedge )
+                          AF_Edge      *anedge )
   {
-    FT_Error  error = AF_Err_Ok;
+    FT_Error  error = FT_Err_Ok;
     AF_Edge   edge  = NULL;
     AF_Edge   edges;
 
@@ -86,7 +97,7 @@
 
       if ( old_max >= big_max )
       {
-        error = AF_Err_Out_Of_Memory;
+        error = FT_THROW( Out_Of_Memory );
         goto Exit;
       }
 
@@ -124,7 +135,7 @@
     edge->dir  = (FT_Char)dir;
 
   Exit:
-    *aedge = edge;
+    *anedge = edge;
     return error;
   }
 
@@ -175,29 +186,27 @@
     AF_Point  point;
 
 
-    printf( "Table of points:\n" );
-    printf(   "  [ index |  xorg |  yorg | xscale | yscale"
-              " |  xfit |  yfit |  flags ]\n" );
+    FT_TRACE7(( "Table of points:\n"
+                "  [ index |  xorg |  yorg | xscale | yscale"
+                " |  xfit |  yfit |  flags ]\n" ));
 
     for ( point = points; point < limit; point++ )
-    {
-      printf( "  [ %5d | %5d | %5d | %6.2f | %6.2f"
-              " | %5.2f | %5.2f | %c%c%c%c%c%c ]\n",
-              point - points,
-              point->fx,
-              point->fy,
-              point->ox / 64.0,
-              point->oy / 64.0,
-              point->x / 64.0,
-              point->y / 64.0,
-              ( point->flags & AF_FLAG_WEAK_INTERPOLATION ) ? 'w' : ' ',
-              ( point->flags & AF_FLAG_INFLECTION )         ? 'i' : ' ',
-              ( point->flags & AF_FLAG_EXTREMA_X )          ? '<' : ' ',
-              ( point->flags & AF_FLAG_EXTREMA_Y )          ? 'v' : ' ',
-              ( point->flags & AF_FLAG_ROUND_X )            ? '(' : ' ',
-              ( point->flags & AF_FLAG_ROUND_Y )            ? 'u' : ' ');
-    }
-    printf( "\n" );
+      FT_TRACE7(( "  [ %5d | %5d | %5d | %6.2f | %6.2f"
+                  " | %5.2f | %5.2f | %c%c%c%c%c%c ]\n",
+                  point - points,
+                  point->fx,
+                  point->fy,
+                  point->ox / 64.0,
+                  point->oy / 64.0,
+                  point->x / 64.0,
+                  point->y / 64.0,
+                  ( point->flags & AF_FLAG_WEAK_INTERPOLATION ) ? 'w' : ' ',
+                  ( point->flags & AF_FLAG_INFLECTION )         ? 'i' : ' ',
+                  ( point->flags & AF_FLAG_EXTREMA_X )          ? '<' : ' ',
+                  ( point->flags & AF_FLAG_EXTREMA_Y )          ? 'v' : ' ',
+                  ( point->flags & AF_FLAG_ROUND_X )            ? '(' : ' ',
+                  ( point->flags & AF_FLAG_ROUND_Y )            ? 'u' : ' '));
+    FT_TRACE7(( "\n" ));
   }
 #ifdef __cplusplus
   }
@@ -226,7 +235,7 @@
     if ( pos == 0 )
       return "normal";
 
-    temp[pos] = 0;
+    temp[pos] = '\0';
 
     return temp;
   }
@@ -246,30 +255,41 @@
     for ( dimension = 1; dimension >= 0; dimension-- )
     {
       AF_AxisHints  axis     = &hints->axis[dimension];
+      AF_Point      points   = hints->points;
+      AF_Edge       edges    = axis->edges;
       AF_Segment    segments = axis->segments;
       AF_Segment    limit    = segments + axis->num_segments;
       AF_Segment    seg;
 
 
-      printf ( "Table of %s segments:\n",
-               dimension == AF_DIMENSION_HORZ ? "vertical" : "horizontal" );
-      printf ( "  [ index |  pos  |  dir  | link | serif |"
-               " height | extra |    flags    ]\n" );
+      FT_TRACE7(( "Table of %s segments:\n",
+                  dimension == AF_DIMENSION_HORZ ? "vertical"
+                                                 : "horizontal" ));
+      if ( axis->num_segments )
+        FT_TRACE7(( "  [ index |  pos  |  dir  | from"
+                    " |  to  | link | serif | edge"
+                    " | height | extra |    flags    ]\n" ));
+      else
+        FT_TRACE7(( "  (none)\n" ));
 
       for ( seg = segments; seg < limit; seg++ )
-      {
-        printf ( "  [ %5d | %5.2g | %5s | %4d | %5d | %6d | %5d | %11s ]\n",
-                 seg - segments,
-                 dimension == AF_DIMENSION_HORZ ? (int)seg->first->ox / 64.0
-                                                : (int)seg->first->oy / 64.0,
-                 af_dir_str( (AF_Direction)seg->dir ),
-                 AF_INDEX_NUM( seg->link, segments ),
-                 AF_INDEX_NUM( seg->serif, segments ),
-                 seg->height,
-                 seg->height - ( seg->max_coord - seg->min_coord ),
-                 af_edge_flags_to_string( (AF_Edge_Flags)seg->flags ) );
-      }
-      printf( "\n" );
+        FT_TRACE7(( "  [ %5d | %5.2g | %5s | %4d"
+                    " | %4d | %4d | %5d | %4d"
+                    " | %6d | %5d | %11s ]\n",
+                    seg - segments,
+                    dimension == AF_DIMENSION_HORZ
+                                 ? (int)seg->first->ox / 64.0
+                                 : (int)seg->first->oy / 64.0,
+                    af_dir_str( (AF_Direction)seg->dir ),
+                    AF_INDEX_NUM( seg->first, points ),
+                    AF_INDEX_NUM( seg->last, points ),
+                    AF_INDEX_NUM( seg->link, segments ),
+                    AF_INDEX_NUM( seg->serif, segments ),
+                    AF_INDEX_NUM( seg->edge, edges ),
+                    seg->height,
+                    seg->height - ( seg->max_coord - seg->min_coord ),
+                    af_edge_flags_to_string( (AF_Edge_Flags)seg->flags ) ));
+      FT_TRACE7(( "\n" ));
     }
   }
 #ifdef __cplusplus
@@ -296,7 +316,7 @@
     axis          = &hints->axis[dim];
     *num_segments = axis->num_segments;
 
-    return AF_Err_Ok;
+    return FT_Err_Ok;
   }
 #ifdef __cplusplus
   }
@@ -320,20 +340,20 @@
 
 
     if ( !offset )
-      return AF_Err_Invalid_Argument;
+      return FT_THROW( Invalid_Argument );
 
     dim = ( dimension == 0 ) ? AF_DIMENSION_HORZ : AF_DIMENSION_VERT;
 
     axis = &hints->axis[dim];
 
     if ( idx < 0 || idx >= axis->num_segments )
-      return AF_Err_Invalid_Argument;
+      return FT_THROW( Invalid_Argument );
 
     seg     = &axis->segments[idx];
-    *offset = (dim == AF_DIMENSION_HORZ) ? seg->first->ox
-                                         : seg->first->oy;
+    *offset = ( dim == AF_DIMENSION_HORZ ) ? seg->first->ox
+                                           : seg->first->oy;
 
-    return AF_Err_Ok;
+    return FT_Err_Ok;
   }
 #ifdef __cplusplus
   }
@@ -363,26 +383,28 @@
        *  note: AF_DIMENSION_HORZ corresponds to _vertical_ edges
        *        since they have a constant X coordinate.
        */
-      printf ( "Table of %s edges:\n",
-               dimension == AF_DIMENSION_HORZ ? "vertical" : "horizontal" );
-      printf ( "  [ index |  pos  |  dir  | link |"
-               " serif | blue | opos  |  pos  |    flags    ]\n" );
+      FT_TRACE7(( "Table of %s edges:\n",
+                  dimension == AF_DIMENSION_HORZ ? "vertical"
+                                                 : "horizontal" ));
+      if ( axis->num_edges )
+        FT_TRACE7(( "  [ index |  pos  |  dir  | link"
+                    " | serif | blue | opos  |  pos  |    flags    ]\n" ));
+      else
+        FT_TRACE7(( "  (none)\n" ));
 
       for ( edge = edges; edge < limit; edge++ )
-      {
-        printf ( "  [ %5d | %5.2g | %5s | %4d |"
-                 " %5d |   %c  | %5.2f | %5.2f | %11s ]\n",
-                 edge - edges,
-                 (int)edge->opos / 64.0,
-                 af_dir_str( (AF_Direction)edge->dir ),
-                 AF_INDEX_NUM( edge->link, edges ),
-                 AF_INDEX_NUM( edge->serif, edges ),
-                 edge->blue_edge ? 'y' : 'n',
-                 edge->opos / 64.0,
-                 edge->pos / 64.0,
-                 af_edge_flags_to_string( (AF_Edge_Flags)edge->flags ) );
-      }
-      printf( "\n" );
+        FT_TRACE7(( "  [ %5d | %5.2g | %5s | %4d"
+                    " | %5d |   %c  | %5.2f | %5.2f | %11s ]\n",
+                    edge - edges,
+                    (int)edge->opos / 64.0,
+                    af_dir_str( (AF_Direction)edge->dir ),
+                    AF_INDEX_NUM( edge->link, edges ),
+                    AF_INDEX_NUM( edge->serif, edges ),
+                    edge->blue_edge ? 'y' : 'n',
+                    edge->opos / 64.0,
+                    edge->pos / 64.0,
+                    af_edge_flags_to_string( (AF_Edge_Flags)edge->flags ) ));
+      FT_TRACE7(( "\n" ));
     }
   }
 #ifdef __cplusplus
@@ -494,8 +516,8 @@
       }
     }
 
-    /* return no direction if arm lengths differ too much */
-    /* (value 14 is heuristic)                            */
+    /* return no direction if arm lengths differ too much            */
+    /* (value 14 is heuristic, corresponding to approx. 4.1 degrees) */
     ss *= 14;
     if ( FT_ABS( ll ) <= FT_ABS( ss ) )
       dir = AF_DIR_NONE;
@@ -516,40 +538,40 @@
   FT_LOCAL_DEF( void )
   af_glyph_hints_done( AF_GlyphHints  hints )
   {
-    if ( hints && hints->memory )
+    FT_Memory  memory = hints->memory;
+    int        dim;
+
+
+    if ( !( hints && hints->memory ) )
+      return;
+
+    /*
+     *  note that we don't need to free the segment and edge
+     *  buffers since they are really within the hints->points array
+     */
+    for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
     {
-      FT_Memory  memory = hints->memory;
-      int        dim;
+      AF_AxisHints  axis = &hints->axis[dim];
 
 
-      /*
-       *  note that we don't need to free the segment and edge
-       *  buffers since they are really within the hints->points array
-       */
-      for ( dim = 0; dim < AF_DIMENSION_MAX; dim++ )
-      {
-        AF_AxisHints  axis = &hints->axis[dim];
+      axis->num_segments = 0;
+      axis->max_segments = 0;
+      FT_FREE( axis->segments );
 
-
-        axis->num_segments = 0;
-        axis->max_segments = 0;
-        FT_FREE( axis->segments );
-
-        axis->num_edges = 0;
-        axis->max_edges = 0;
-        FT_FREE( axis->edges );
-      }
-
-      FT_FREE( hints->contours );
-      hints->max_contours = 0;
-      hints->num_contours = 0;
-
-      FT_FREE( hints->points );
-      hints->num_points = 0;
-      hints->max_points = 0;
-
-      hints->memory = NULL;
+      axis->num_edges = 0;
+      axis->max_edges = 0;
+      FT_FREE( axis->edges );
     }
+
+    FT_FREE( hints->contours );
+    hints->max_contours = 0;
+    hints->num_contours = 0;
+
+    FT_FREE( hints->points );
+    hints->num_points = 0;
+    hints->max_points = 0;
+
+    hints->memory = NULL;
   }
 
 
@@ -571,7 +593,7 @@
   af_glyph_hints_reload( AF_GlyphHints  hints,
                          FT_Outline*    outline )
   {
-    FT_Error   error   = AF_Err_Ok;
+    FT_Error   error   = FT_Err_Ok;
     AF_Point   points;
     FT_UInt    old_max, new_max;
     FT_Fixed   x_scale = hints->x_scale;
@@ -745,7 +767,7 @@
 
           /* check for weak points */
 
-          if ( point->flags & ( AF_FLAG_CONIC | AF_FLAG_CUBIC ) )
+          if ( point->flags & AF_FLAG_CONTROL )
           {
           Is_Weak_Point:
             point->flags |= AF_FLAG_WEAK_INTERPOLATION;
diff --git a/src/autofit/afhints.h b/src/autofit/afhints.h
index 1c52e0d..776b3c8 100644
--- a/src/autofit/afhints.h
+++ b/src/autofit/afhints.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter hinting routines (specification).                        */
 /*                                                                         */
-/*  Copyright 2003-2008, 2010-2011 by                                      */
+/*  Copyright 2003-2008, 2010-2012 by                                      */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -254,7 +254,7 @@
     FT_Char    out_dir;  /* direction of outwards vector */
 
     FT_Pos     ox, oy;   /* original, scaled position                   */
-    FT_Short   fx, fy;   /* original, unscaled position (font units)    */
+    FT_Short   fx, fy;   /* original, unscaled position (in font units) */
     FT_Pos     x, y;     /* current position                            */
     FT_Pos     u, v;     /* current (x,y) or (y,x) depending on context */
 
@@ -290,19 +290,19 @@
 
   typedef struct  AF_EdgeRec_
   {
-    FT_Short    fpos;       /* original, unscaled position (font units) */
-    FT_Pos      opos;       /* original, scaled position                */
-    FT_Pos      pos;        /* current position                         */
+    FT_Short    fpos;       /* original, unscaled position (in font units) */
+    FT_Pos      opos;       /* original, scaled position                   */
+    FT_Pos      pos;        /* current position                            */
 
     FT_Byte     flags;      /* edge flags                                   */
     FT_Char     dir;        /* edge direction                               */
     FT_Fixed    scale;      /* used to speed up interpolation between edges */
-    AF_Width    blue_edge;  /* non-NULL if this is a blue edge              */
 
-    AF_Edge     link;       /* link edge                 */
-    AF_Edge     serif;      /* primary edge for serifs   */
-    FT_Short    num_linked; /* number of linked edges    */
-    FT_Int      score;      /* used during stem matching */
+    AF_Width    blue_edge;  /* non-NULL if this is a blue edge */
+    AF_Edge     link;       /* link edge                       */
+    AF_Edge     serif;      /* primary edge for serifs         */
+    FT_Short    num_linked; /* number of linked edges          */
+    FT_Int      score;      /* used during stem matching       */
 
     AF_Segment  first;      /* first segment in edge */
     AF_Segment  last;       /* last segment in edge  */
diff --git a/src/autofit/afindic.c b/src/autofit/afindic.c
index 9c74838..8c24972 100644
--- a/src/autofit/afindic.c
+++ b/src/autofit/afindic.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter hinting routines for Indic scripts (body).               */
 /*                                                                         */
-/*  Copyright 2007, 2011 by                                                */
+/*  Copyright 2007, 2011-2013 by                                           */
 /*  Rahul Bhalerao <rahul.bhalerao@redhat.com>, <b.rahul.pm@gmail.com>.    */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -46,7 +46,7 @@
       face->charmap = NULL;
     else
     {
-      af_cjk_metrics_init_widths( metrics, face, 0x7530 );
+      af_cjk_metrics_init_widths( metrics, face );
 #if 0
       /* either need indic specific blue_chars[] or just skip blue zones */
       af_cjk_metrics_init_blues( metrics, face, af_cjk_blue_chars );
@@ -56,7 +56,7 @@
 
     FT_Set_Charmap( face, oldmap );
 
-    return AF_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
@@ -116,6 +116,7 @@
   AF_DEFINE_SCRIPT_CLASS( af_indic_script_class,
     AF_SCRIPT_INDIC,
     af_indic_uniranges,
+    'o', /* XXX */
 
     sizeof ( AF_CJKMetricsRec ),
 
@@ -138,6 +139,7 @@
   AF_DEFINE_SCRIPT_CLASS( af_indic_script_class,
     AF_SCRIPT_INDIC,
     af_indic_uniranges,
+    0,
 
     sizeof ( AF_CJKMetricsRec ),
 
diff --git a/src/autofit/afindic.h b/src/autofit/afindic.h
index 662a982..c252cf2 100644
--- a/src/autofit/afindic.h
+++ b/src/autofit/afindic.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter hinting routines for Indic scripts (specification).      */
 /*                                                                         */
-/*  Copyright 2007 by                                                      */
+/*  Copyright 2007, 2012 by                                                */
 /*  Rahul Bhalerao <rahul.bhalerao@redhat.com>, <b.rahul.pm@gmail.com>.    */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -27,7 +27,7 @@
 
   /* the Indic-specific script class */
 
-  AF_DECLARE_SCRIPT_CLASS(af_indic_script_class)
+  AF_DECLARE_SCRIPT_CLASS( af_indic_script_class )
 
 
 /* */
diff --git a/src/autofit/aflatin.c b/src/autofit/aflatin.c
index 30145a2..ef0157a 100644
--- a/src/autofit/aflatin.c
+++ b/src/autofit/aflatin.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter hinting routines for latin script (body).                */
 /*                                                                         */
-/*  Copyright 2003-2011 by                                                 */
+/*  Copyright 2003-2013 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -20,6 +20,7 @@
 #include FT_ADVANCES_H
 #include FT_INTERNAL_DEBUG_H
 
+#include "afglobal.h"
 #include "aflatin.h"
 #include "aferrors.h"
 
@@ -53,30 +54,36 @@
 
   FT_LOCAL_DEF( void )
   af_latin_metrics_init_widths( AF_LatinMetrics  metrics,
-                                FT_Face          face,
-                                FT_ULong         charcode )
+                                FT_Face          face )
   {
     /* scan the array of segments in each direction */
     AF_GlyphHintsRec  hints[1];
 
 
+    FT_TRACE5(( "standard widths computation\n"
+                "===========================\n\n" ));
+
     af_glyph_hints_init( hints, face->memory );
 
     metrics->axis[AF_DIMENSION_HORZ].width_count = 0;
     metrics->axis[AF_DIMENSION_VERT].width_count = 0;
 
     {
-      FT_Error             error;
-      FT_UInt              glyph_index;
-      int                  dim;
-      AF_LatinMetricsRec   dummy[1];
-      AF_Scaler            scaler = &dummy->root.scaler;
+      FT_Error            error;
+      FT_UInt             glyph_index;
+      int                 dim;
+      AF_LatinMetricsRec  dummy[1];
+      AF_Scaler           scaler = &dummy->root.scaler;
 
 
-      glyph_index = FT_Get_Char_Index( face, charcode );
+      glyph_index = FT_Get_Char_Index( face,
+                                       metrics->root.clazz->standard_char );
       if ( glyph_index == 0 )
         goto Exit;
 
+      FT_TRACE5(( "standard character: 0x%X (glyph index %d)\n",
+                  metrics->root.clazz->standard_char, glyph_index ));
+
       error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
       if ( error || face->glyph->outline.n_points <= 0 )
         goto Exit;
@@ -138,7 +145,10 @@
           }
         }
 
-        af_sort_widths( num_widths, axis->widths );
+        /* this also replaces multiple almost identical stem widths */
+        /* with a single one (the value 100 is heuristic) */
+        af_sort_and_quantize_widths( &num_widths, axis->widths,
+                                     dummy->units_per_em / 100 );
         axis->width_count = num_widths;
       }
 
@@ -157,9 +167,28 @@
         axis->edge_distance_threshold = stdw / 5;
         axis->standard_width          = stdw;
         axis->extra_light             = 0;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+        {
+          FT_UInt  i;
+
+
+          FT_TRACE5(( "%s widths:\n",
+                      dim == AF_DIMENSION_VERT ? "horizontal"
+                                               : "vertical" ));
+
+          FT_TRACE5(( "  %d (standard)", axis->standard_width ));
+          for ( i = 1; i < axis->width_count; i++ )
+            FT_TRACE5(( " %d", axis->widths[i].org ));
+
+          FT_TRACE5(( "\n" ));
+        }
+#endif
       }
     }
 
+    FT_TRACE5(( "\n" ));
+
     af_glyph_hints_done( hints );
   }
 
@@ -195,15 +224,15 @@
     AF_LatinBlue  blue;
     FT_Error      error;
     AF_LatinAxis  axis  = &metrics->axis[AF_DIMENSION_VERT];
-    FT_GlyphSlot  glyph = face->glyph;
+    FT_Outline    outline;
 
 
     /* we compute the blues simply by loading each character from the    */
     /* `af_latin_blue_chars[blues]' string, then finding its top-most or */
     /* bottom-most points (depending on `AF_IS_TOP_BLUE')                */
 
-    FT_TRACE5(( "blue zones computation\n" ));
-    FT_TRACE5(( "------------------------------------------------\n" ));
+    FT_TRACE5(( "blue zones computation\n"
+                "======================\n\n" ));
 
     for ( bb = 0; bb < AF_LATIN_BLUE_MAX; bb++ )
     {
@@ -213,7 +242,7 @@
       FT_Pos*      blue_shoot;
 
 
-      FT_TRACE5(( "blue %3d: ", bb ));
+      FT_TRACE5(( "blue zone %d:\n", bb ));
 
       num_flats  = 0;
       num_rounds = 0;
@@ -222,28 +251,27 @@
       {
         FT_UInt     glyph_index;
         FT_Pos      best_y;                            /* same as points.y */
-        FT_Int      best_point, best_first, best_last;
+        FT_Int      best_point, best_contour_first, best_contour_last;
         FT_Vector*  points;
         FT_Bool     round = 0;
 
 
-        FT_TRACE5(( "'%c'", *p ));
-
         /* load the character in the face -- skip unknown or empty ones */
         glyph_index = FT_Get_Char_Index( face, (FT_UInt)*p );
         if ( glyph_index == 0 )
           continue;
 
-        error = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
-        if ( error || glyph->outline.n_points <= 0 )
+        error   = FT_Load_Glyph( face, glyph_index, FT_LOAD_NO_SCALE );
+        outline = face->glyph->outline;
+        if ( error || outline.n_points <= 0 )
           continue;
 
         /* now compute min or max point indices and coordinates */
-        points      = glyph->outline.points;
-        best_point  = -1;
-        best_y      = 0;  /* make compiler happy */
-        best_first  = 0;  /* ditto */
-        best_last   = 0;  /* ditto */
+        points             = outline.points;
+        best_point         = -1;
+        best_y             = 0;  /* make compiler happy */
+        best_contour_first = 0;  /* ditto */
+        best_contour_last  = 0;  /* ditto */
 
         {
           FT_Int  nn;
@@ -251,15 +279,13 @@
           FT_Int  last  = -1;
 
 
-          for ( nn = 0;
-                nn < glyph->outline.n_contours;
-                first = last + 1, nn++ )
+          for ( nn = 0; nn < outline.n_contours; first = last + 1, nn++ )
           {
             FT_Int  old_best_point = best_point;
             FT_Int  pp;
 
 
-            last = glyph->outline.contours[nn];
+            last = outline.contours[nn];
 
             /* Avoid single-point contours since they are never rasterized. */
             /* In some fonts, they correspond to mark attachment points     */
@@ -288,11 +314,11 @@
 
             if ( best_point != old_best_point )
             {
-              best_first = first;
-              best_last  = last;
+              best_contour_first = first;
+              best_contour_last  = last;
             }
           }
-          FT_TRACE5(( "%5d", best_y ));
+          FT_TRACE5(( "  %c  %ld", *p, best_y ));
         }
 
         /* now check whether the point belongs to a straight or round   */
@@ -300,47 +326,86 @@
         /* lies, then inspect its previous and next points              */
         if ( best_point >= 0 )
         {
+          FT_Pos  best_x = points[best_point].x;
           FT_Int  prev, next;
+          FT_Int  best_on_point_first, best_on_point_last;
           FT_Pos  dist;
 
 
-          /* now look for the previous and next points that are not on the */
-          /* same Y coordinate.  Threshold the `closeness'...              */
+          if ( FT_CURVE_TAG( outline.tags[best_point] ) == FT_CURVE_TAG_ON )
+          {
+            best_on_point_first = best_point;
+            best_on_point_last  = best_point;
+          }
+          else
+          {
+            best_on_point_first = -1;
+            best_on_point_last  = -1;
+          }
+
+          /* look for the previous and next points that are not on the */
+          /* same Y coordinate, then threshold the `closeness'...      */
           prev = best_point;
           next = prev;
 
           do
           {
-            if ( prev > best_first )
+            if ( prev > best_contour_first )
               prev--;
             else
-              prev = best_last;
+              prev = best_contour_last;
 
-            dist = points[prev].y - best_y;
-            if ( dist < -5 || dist > 5 )
-              break;
+            dist = FT_ABS( points[prev].y - best_y );
+            /* accept a small distance or a small angle (both values are */
+            /* heuristic; value 20 corresponds to approx. 2.9 degrees)   */
+            if ( dist > 5 )
+              if ( FT_ABS( points[prev].x - best_x ) <= 20 * dist )
+                break;
+
+            if ( FT_CURVE_TAG( outline.tags[prev] ) == FT_CURVE_TAG_ON )
+            {
+              best_on_point_first = prev;
+              if ( best_on_point_last < 0 )
+                best_on_point_last = prev;
+            }
 
           } while ( prev != best_point );
 
           do
           {
-            if ( next < best_last )
+            if ( next < best_contour_last )
               next++;
             else
-              next = best_first;
+              next = best_contour_first;
 
-            dist = points[next].y - best_y;
-            if ( dist < -5 || dist > 5 )
-              break;
+            dist = FT_ABS( points[next].y - best_y );
+            if ( dist > 5 )
+              if ( FT_ABS( points[next].x - best_x ) <= 20 * dist )
+                break;
+
+            if ( FT_CURVE_TAG( outline.tags[next] ) == FT_CURVE_TAG_ON )
+            {
+              best_on_point_last = next;
+              if ( best_on_point_first < 0 )
+                best_on_point_first = next;
+            }
 
           } while ( next != best_point );
 
           /* now set the `round' flag depending on the segment's kind */
-          round = FT_BOOL(
-            FT_CURVE_TAG( glyph->outline.tags[prev] ) != FT_CURVE_TAG_ON ||
-            FT_CURVE_TAG( glyph->outline.tags[next] ) != FT_CURVE_TAG_ON );
+          /* (value 8 is heuristic)                                   */
+          if ( best_on_point_first >= 0                               &&
+               best_on_point_last >= 0                                &&
+               (FT_UInt)( FT_ABS( points[best_on_point_last].x -
+                                  points[best_on_point_first].x ) ) >
+                 metrics->units_per_em / 8                            )
+            round = 0;
+          else
+            round = FT_BOOL(
+              FT_CURVE_TAG( outline.tags[prev] ) != FT_CURVE_TAG_ON ||
+              FT_CURVE_TAG( outline.tags[next] ) != FT_CURVE_TAG_ON );
 
-          FT_TRACE5(( "%c ", round ? 'r' : 'f' ));
+          FT_TRACE5(( " (%s)\n", round ? "round" : "flat" ));
         }
 
         if ( round )
@@ -349,15 +414,13 @@
           flats[num_flats++]   = best_y;
       }
 
-      FT_TRACE5(( "\n" ));
-
       if ( num_flats == 0 && num_rounds == 0 )
       {
         /*
          *  we couldn't find a single glyph to compute this blue zone,
          *  we will simply ignore it then
          */
-        FT_TRACE5(( "empty\n" ));
+        FT_TRACE5(( "  empty\n" ));
         continue;
       }
 
@@ -400,8 +463,13 @@
 
 
         if ( AF_LATIN_IS_TOP_BLUE( bb ) ^ over_ref )
+        {
           *blue_ref   =
           *blue_shoot = ( shoot + ref ) / 2;
+
+          FT_TRACE5(( "  [overshoot smaller than reference,"
+                      " taking mean value]\n" ));
+        }
       }
 
       blue->flags = 0;
@@ -416,7 +484,9 @@
       if ( bb == AF_LATIN_BLUE_SMALL_TOP )
         blue->flags |= AF_LATIN_BLUE_ADJUSTMENT;
 
-      FT_TRACE5(( "-- ref = %ld, shoot = %ld\n", *blue_ref, *blue_shoot ));
+      FT_TRACE5(( "    -> reference = %ld\n"
+                  "       overshoot = %ld\n",
+                  *blue_ref, *blue_shoot ));
     }
 
     FT_TRACE5(( "\n" ));
@@ -478,41 +548,20 @@
   af_latin_metrics_init( AF_LatinMetrics  metrics,
                          FT_Face          face )
   {
-    FT_Error    error = AF_Err_Ok;
     FT_CharMap  oldmap = face->charmap;
-    FT_UInt     ee;
-
-    static const FT_Encoding  latin_encodings[] =
-    {
-      FT_ENCODING_UNICODE,
-      FT_ENCODING_APPLE_ROMAN,
-      FT_ENCODING_ADOBE_STANDARD,
-      FT_ENCODING_ADOBE_LATIN_1,
-
-      FT_ENCODING_NONE  /* end of list */
-    };
 
 
     metrics->units_per_em = face->units_per_EM;
 
-    /* do we have a latin charmap in there? */
-    for ( ee = 0; latin_encodings[ee] != FT_ENCODING_NONE; ee++ )
+    if ( !FT_Select_Charmap( face, FT_ENCODING_UNICODE ) )
     {
-      error = FT_Select_Charmap( face, latin_encodings[ee] );
-      if ( !error )
-        break;
-    }
-
-    if ( !error )
-    {
-      /* For now, compute the standard width and height from the `o'. */
-      af_latin_metrics_init_widths( metrics, face, 'o' );
+      af_latin_metrics_init_widths( metrics, face );
       af_latin_metrics_init_blues( metrics, face );
       af_latin_metrics_check_digits( metrics, face );
     }
 
     FT_Set_Charmap( face, oldmap );
-    return AF_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
@@ -569,10 +618,27 @@
 
       if ( blue )
       {
-        FT_Pos  scaled = FT_MulFix( blue->shoot.org, scaler->y_scale );
-        FT_Pos  fitted = ( scaled + 40 ) & ~63;
+        FT_Pos   scaled;
+        FT_Pos   threshold;
+        FT_Pos   fitted;
+        FT_UInt  limit;
+        FT_UInt  ppem;
 
 
+        scaled    = FT_MulFix( blue->shoot.org, scaler->y_scale );
+        ppem      = metrics->root.scaler.face->size->metrics.x_ppem;
+        limit     = metrics->root.globals->increase_x_height;
+        threshold = 40;
+
+        /* if the `increase-x-height' property is active, */
+        /* we round up much more often                    */
+        if ( limit                                 &&
+             ppem <= limit                         &&
+             ppem >= AF_PROP_INCREASE_X_HEIGHT_MIN )
+          threshold = 52;
+
+        fitted = ( scaled + threshold ) & ~63;
+
         if ( scaled != fitted )
         {
 #if 0
@@ -677,7 +743,7 @@
 
           if ( delta2 < 32 )
             delta2 = 0;
-          else if ( delta < 48 )
+          else if ( delta2 < 48 )
             delta2 = 32;
           else
             delta2 = 64;
@@ -705,6 +771,7 @@
   {
     metrics->root.scaler.render_mode = scaler->render_mode;
     metrics->root.scaler.face        = scaler->face;
+    metrics->root.scaler.flags       = scaler->flags;
 
     af_latin_metrics_scale_dim( metrics, scaler, AF_DIMENSION_HORZ );
     af_latin_metrics_scale_dim( metrics, scaler, AF_DIMENSION_VERT );
@@ -728,7 +795,7 @@
   {
     AF_AxisHints   axis          = &hints->axis[dim];
     FT_Memory      memory        = hints->memory;
-    FT_Error       error         = AF_Err_Ok;
+    FT_Error       error         = FT_Err_Ok;
     AF_Segment     segment       = NULL;
     AF_SegmentRec  seg0;
     AF_Point*      contour       = hints->contours;
@@ -848,7 +915,7 @@
 
             on_edge = 0;
             segment = NULL;
-            /* fallthrough */
+            /* fall through */
           }
         }
 
@@ -884,8 +951,8 @@
     } /* contours */
 
 
-    /* now slightly increase the height of segments when this makes */
-    /* sense -- this is used to better detect and ignore serifs     */
+    /* now slightly increase the height of segments if this makes */
+    /* sense -- this is used to better detect and ignore serifs   */
     {
       AF_Segment  segments     = axis->segments;
       AF_Segment  segments_end = segments + axis->num_segments;
@@ -1040,7 +1107,7 @@
                                 AF_Dimension   dim )
   {
     AF_AxisHints  axis   = &hints->axis[dim];
-    FT_Error      error  = AF_Err_Ok;
+    FT_Error      error  = FT_Err_Ok;
     FT_Memory     memory = hints->memory;
     AF_LatinAxis  laxis  = &((AF_LatinMetrics)hints->metrics)->axis[dim];
 
@@ -1169,17 +1236,17 @@
     }
 
 
-    /*********************************************************************/
-    /*                                                                   */
-    /* Good, we will now compute each edge's properties according to     */
-    /* the segments found on its position.  Basically, these are         */
-    /*                                                                   */
-    /*  - the edge's main direction                                      */
-    /*  - stem edge, serif edge or both (which defaults to stem then)    */
-    /*  - rounded edge, straight or both (which defaults to straight)    */
-    /*  - link for edge                                                  */
-    /*                                                                   */
-    /*********************************************************************/
+    /******************************************************************/
+    /*                                                                */
+    /* Good, we now compute each edge's properties according to the   */
+    /* segments found on its position.  Basically, these are          */
+    /*                                                                */
+    /*  - the edge's main direction                                   */
+    /*  - stem edge, serif edge or both (which defaults to stem then) */
+    /*  - rounded edge, straight or both (which defaults to straight) */
+    /*  - link for edge                                               */
+    /*                                                                */
+    /******************************************************************/
 
     /* first of all, set the `edge' field in each segment -- this is */
     /* required in order to compute edge links                       */
@@ -1367,7 +1434,7 @@
     /* for each horizontal edge search the blue zone which is closest */
     for ( ; edge < edge_limit; edge++ )
     {
-      FT_Int    bb;
+      FT_UInt   bb;
       AF_Width  best_blue = NULL;
       FT_Pos    best_dist;  /* initial threshold */
 
@@ -1380,7 +1447,7 @@
       if ( best_dist > 64 / 2 )
         best_dist = 64 / 2;
 
-      for ( bb = 0; bb < AF_LATIN_BLUE_MAX; bb++ )
+      for ( bb = 0; bb < latin->blue_count; bb++ )
       {
         AF_LatinBlue  blue = latin->blues + bb;
         FT_Bool       is_top_blue, is_major_dir;
@@ -1476,9 +1543,7 @@
 
 #if 0 /* #ifdef AF_CONFIG_OPTION_USE_WARPER */
     if ( mode == FT_RENDER_MODE_LCD || mode == FT_RENDER_MODE_LCD_V )
-    {
       metrics->root.scaler.render_mode = mode = FT_RENDER_MODE_NORMAL;
-    }
 #endif
 
     scaler_flags = hints->scaler_flags;
@@ -1518,7 +1583,7 @@
     hints->scaler_flags = scaler_flags;
     hints->other_flags  = other_flags;
 
-    return AF_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
@@ -1722,7 +1787,7 @@
             if ( delta < 0 )
               delta = -delta;
 
-            if (delta >= 16)
+            if ( delta >= 16 )
             {
               dist = org_dist;
               if ( dist < 48 )
@@ -1762,7 +1827,7 @@
 
     stem_edge->pos = base_edge->pos + fitted_width;
 
-    FT_TRACE5(( "  LINK: edge %d (opos=%.2f) linked to (%.2f),"
+    FT_TRACE5(( "  LINK: edge %d (opos=%.2f) linked to %.2f,"
                 " dist was %.2f, now %.2f\n",
                 stem_edge-hints->axis[dim].edges, stem_edge->opos / 64.0,
                 stem_edge->pos / 64.0, dist / 64.0, fitted_width / 64.0 ));
@@ -1808,9 +1873,13 @@
     AF_Edge       anchor     = NULL;
     FT_Int        has_serifs = 0;
 
+#ifdef FT_DEBUG_LEVEL_TRACE
+    FT_UInt       num_actions = 0;
+#endif
 
-    FT_TRACE5(("%s edge hinting\n", dim == AF_DIMENSION_VERT ? "horizontal"
-                                                             : "vertical"));
+
+    FT_TRACE5(( "%s edge hinting\n",
+                dim == AF_DIMENSION_VERT ? "horizontal" : "vertical" ));
 
     /* we begin by aligning all stems relative to the blue zone */
     /* if needed -- that's only for horizontal edges            */
@@ -1844,10 +1913,20 @@
         if ( !edge1 )
           continue;
 
-        FT_TRACE5(( "  BLUE: edge %d (opos=%.2f) snapped to (%.2f),"
-                    " was (%.2f)\n",
-                    edge1 - edges, edge1->opos / 64.0, blue->fit / 64.0,
-                    edge1->pos / 64.0 ));
+#ifdef FT_DEBUG_LEVEL_TRACE
+        if ( !anchor )
+          FT_TRACE5(( "  BLUE_ANCHOR: edge %d (opos=%.2f) snapped to %.2f,"
+                      " was %.2f (anchor=edge %d)\n",
+                      edge1 - edges, edge1->opos / 64.0, blue->fit / 64.0,
+                      edge1->pos / 64.0, edge - edges ));
+        else
+          FT_TRACE5(( "  BLUE: edge %d (opos=%.2f) snapped to %.2f,"
+                      " was %.2f\n",
+                      edge1 - edges, edge1->opos / 64.0, blue->fit / 64.0,
+                      edge1->pos / 64.0 ));
+
+        num_actions++;
+#endif
 
         edge1->pos    = blue->fit;
         edge1->flags |= AF_EDGE_DONE;
@@ -1856,6 +1935,10 @@
         {
           af_latin_align_linked_edge( hints, dim, edge1, edge2 );
           edge2->flags |= AF_EDGE_DONE;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+          num_actions++;
+#endif
         }
 
         if ( !anchor )
@@ -1890,6 +1973,10 @@
 
         af_latin_align_linked_edge( hints, dim, edge2, edge );
         edge->flags |= AF_EDGE_DONE;
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+        num_actions++;
+#endif
         continue;
       }
 
@@ -1947,16 +2034,20 @@
         else
           edge->pos = FT_PIX_ROUND( edge->opos );
 
+        anchor       = edge;
+        edge->flags |= AF_EDGE_DONE;
+
         FT_TRACE5(( "  ANCHOR: edge %d (opos=%.2f) and %d (opos=%.2f)"
-                    " snapped to (%.2f) (%.2f)\n",
+                    " snapped to %.2f and %.2f\n",
                     edge - edges, edge->opos / 64.0,
                     edge2 - edges, edge2->opos / 64.0,
                     edge->pos / 64.0, edge2->pos / 64.0 ));
-        anchor = edge;
-
-        edge->flags |= AF_EDGE_DONE;
 
         af_latin_align_linked_edge( hints, dim, edge, edge2 );
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+        num_actions += 2;
+#endif
       }
       else
       {
@@ -1989,7 +2080,7 @@
 
           cur_pos1 = FT_PIX_ROUND( org_center );
 
-          if (cur_len <= 64 )
+          if ( cur_len <= 64 )
           {
             u_off = 32;
             d_off = 32;
@@ -2016,12 +2107,13 @@
           edge->pos  = cur_pos1 - cur_len / 2;
           edge2->pos = cur_pos1 + cur_len / 2;
 
-          FT_TRACE5(( "  STEM: %d (opos=%.2f) to %d (opos=%.2f)"
-                      " snapped to (%.2f) and (%.2f)\n",
+          FT_TRACE5(( "  STEM: edge %d (opos=%.2f) linked to %d (opos=%.2f)"
+                      " snapped to %.2f and %.2f\n",
                       edge - edges, edge->opos / 64.0,
                       edge2 - edges, edge2->opos / 64.0,
                       edge->pos / 64.0, edge2->pos / 64.0 ));
         }
+
         else
         {
           org_pos    = anchor->pos + ( edge->opos - anchor->opos );
@@ -2046,20 +2138,29 @@
           edge->pos  = ( delta1 < delta2 ) ? cur_pos1 : cur_pos2;
           edge2->pos = edge->pos + cur_len;
 
-          FT_TRACE5(( "  STEM: %d (opos=%.2f) to %d (opos=%.2f)"
-                      " snapped to (%.2f) and (%.2f)\n",
+          FT_TRACE5(( "  STEM: edge %d (opos=%.2f) linked to %d (opos=%.2f)"
+                      " snapped to %.2f and %.2f\n",
                       edge - edges, edge->opos / 64.0,
                       edge2 - edges, edge2->opos / 64.0,
                       edge->pos / 64.0, edge2->pos / 64.0 ));
         }
 
+#ifdef FT_DEBUG_LEVEL_TRACE
+        num_actions++;
+#endif
+
         edge->flags  |= AF_EDGE_DONE;
         edge2->flags |= AF_EDGE_DONE;
 
         if ( edge > edges && edge->pos < edge[-1].pos )
         {
-          FT_TRACE5(( "  BOUND: %d (pos=%.2f) to (%.2f)\n",
+#ifdef FT_DEBUG_LEVEL_TRACE
+          FT_TRACE5(( "  BOUND: edge %d (pos=%.2f) moved to %.2f\n",
                       edge - edges, edge->pos / 64.0, edge[-1].pos / 64.0 ));
+
+          num_actions++;
+#endif
+
           edge->pos = edge[-1].pos;
         }
       }
@@ -2154,7 +2255,7 @@
         {
           af_latin_align_serif_edge( hints, edge->serif, edge );
           FT_TRACE5(( "  SERIF: edge %d (opos=%.2f) serif to %d (opos=%.2f)"
-                      " aligned to (%.2f)\n",
+                      " aligned to %.2f\n",
                       edge - edges, edge->opos / 64.0,
                       edge->serif - edges, edge->serif->opos / 64.0,
                       edge->pos / 64.0 ));
@@ -2164,7 +2265,7 @@
           edge->pos = FT_PIX_ROUND( edge->opos );
           anchor    = edge;
           FT_TRACE5(( "  SERIF_ANCHOR: edge %d (opos=%.2f)"
-                      " snapped to (%.2f)\n",
+                      " snapped to %.2f\n",
                       edge-edges, edge->opos / 64.0, edge->pos / 64.0 ));
         }
         else
@@ -2191,7 +2292,7 @@
                                      after->pos - before->pos,
                                      after->opos - before->opos );
 
-            FT_TRACE5(( "  SERIF_LINK1: edge %d (opos=%.2f) snapped to (%.2f)"
+            FT_TRACE5(( "  SERIF_LINK1: edge %d (opos=%.2f) snapped to %.2f"
                         " from %d (opos=%.2f)\n",
                         edge - edges, edge->opos / 64.0,
                         edge->pos / 64.0,
@@ -2201,26 +2302,49 @@
           {
             edge->pos = anchor->pos +
                         ( ( edge->opos - anchor->opos + 16 ) & ~31 );
-
             FT_TRACE5(( "  SERIF_LINK2: edge %d (opos=%.2f)"
-                        " snapped to (%.2f)\n",
+                        " snapped to %.2f\n",
                         edge - edges, edge->opos / 64.0, edge->pos / 64.0 ));
           }
         }
 
+#ifdef FT_DEBUG_LEVEL_TRACE
+        num_actions++;
+#endif
         edge->flags |= AF_EDGE_DONE;
 
         if ( edge > edges && edge->pos < edge[-1].pos )
+        {
+#ifdef FT_DEBUG_LEVEL_TRACE
+          FT_TRACE5(( "  BOUND: edge %d (pos=%.2f) moved to %.2f\n",
+                      edge - edges, edge->pos / 64.0, edge[-1].pos / 64.0 ));
+
+          num_actions++;
+#endif
           edge->pos = edge[-1].pos;
+        }
 
         if ( edge + 1 < edge_limit        &&
              edge[1].flags & AF_EDGE_DONE &&
              edge->pos > edge[1].pos      )
+        {
+#ifdef FT_DEBUG_LEVEL_TRACE
+          FT_TRACE5(( "  BOUND: edge %d (pos=%.2f) moved to %.2f\n",
+                      edge - edges, edge->pos / 64.0, edge[1].pos / 64.0 ));
+
+          num_actions++;
+#endif
+
           edge->pos = edge[1].pos;
+        }
       }
     }
 
+#ifdef FT_DEBUG_LEVEL_TRACE
+    if ( !num_actions )
+      FT_TRACE5(( "  (none)\n" ));
     FT_TRACE5(( "\n" ));
+#endif
   }
 
 
@@ -2333,10 +2457,12 @@
     AF_UNIRANGE_REC(  0x2460UL,  0x24FFUL ),  /* Enclosed Alphanumerics */
     AF_UNIRANGE_REC(  0x2C60UL,  0x2C7FUL ),  /* Latin Extended-C */
     AF_UNIRANGE_REC(  0x2DE0UL,  0x2DFFUL ),  /* Cyrillic Extended-A */
+    AF_UNIRANGE_REC(  0x2E00UL,  0x2E7FUL ),  /* Supplemental Punctuation */
     AF_UNIRANGE_REC(  0xA640UL,  0xA69FUL ),  /* Cyrillic Extended-B */
     AF_UNIRANGE_REC(  0xA720UL,  0xA7FFUL ),  /* Latin Extended-D */
     AF_UNIRANGE_REC(  0xFB00UL,  0xFB06UL ),  /* Alphab. Present. Forms (Latin Ligs) */
     AF_UNIRANGE_REC( 0x1D400UL, 0x1D7FFUL ),  /* Mathematical Alphanumeric Symbols */
+    AF_UNIRANGE_REC( 0x1F100UL, 0x1F1FFUL ),  /* Enclosed Alphanumeric Supplement */
     AF_UNIRANGE_REC(       0UL,       0UL )
   };
 
@@ -2344,6 +2470,7 @@
   AF_DEFINE_SCRIPT_CLASS( af_latin_script_class,
     AF_SCRIPT_LATIN,
     af_latin_uniranges,
+    'o',
 
     sizeof ( AF_LatinMetricsRec ),
 
diff --git a/src/autofit/aflatin.h b/src/autofit/aflatin.h
index c5c2d13..d9170b3 100644
--- a/src/autofit/aflatin.h
+++ b/src/autofit/aflatin.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter hinting routines for latin script (specification).       */
 /*                                                                         */
-/*  Copyright 2003-2007, 2009, 2011 by                                     */
+/*  Copyright 2003-2007, 2009, 2011-2012 by                                */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -27,7 +27,7 @@
 
   /* the latin-specific script class */
 
-  AF_DECLARE_SCRIPT_CLASS(af_latin_script_class)
+  AF_DECLARE_SCRIPT_CLASS( af_latin_script_class )
 
 
   /* constants are given with units_per_em == 2048 in mind */
@@ -133,8 +133,7 @@
 
   FT_LOCAL( void )
   af_latin_metrics_init_widths( AF_LatinMetrics  metrics,
-                                FT_Face          face,
-                                FT_ULong         charcode );
+                                FT_Face          face );
 
   FT_LOCAL( void )
   af_latin_metrics_check_digits( AF_LatinMetrics  metrics,
@@ -174,25 +173,17 @@
 
 
   /*
-   *  This shouldn't normally be exported.  However, other scripts might
-   *  like to use this function as-is.
+   *  The next functions shouldn't normally be exported.  However, other
+   *  scripts might like to use these functions as-is.
    */
   FT_LOCAL( FT_Error )
   af_latin_hints_compute_segments( AF_GlyphHints  hints,
                                    AF_Dimension   dim );
 
-  /*
-   *  This shouldn't normally be exported.  However, other scripts might
-   *  want to use this function as-is.
-   */
   FT_LOCAL( void )
   af_latin_hints_link_segments( AF_GlyphHints  hints,
                                 AF_Dimension   dim );
 
-  /*
-   *  This shouldn't normally be exported.  However, other scripts might
-   *  want to use this function as-is.
-   */
   FT_LOCAL( FT_Error )
   af_latin_hints_compute_edges( AF_GlyphHints  hints,
                                 AF_Dimension   dim );
diff --git a/src/autofit/aflatin2.c b/src/autofit/aflatin2.c
index ea6af8d..b1e9658 100644
--- a/src/autofit/aflatin2.c
+++ b/src/autofit/aflatin2.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter hinting routines for latin script (body).                */
 /*                                                                         */
-/*  Copyright 2003-2011 by                                                 */
+/*  Copyright 2003-2013 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -18,6 +18,7 @@
 
 #include FT_ADVANCES_H
 
+#include "afglobal.h"
 #include "aflatin.h"
 #include "aflatin2.h"
 #include "aferrors.h"
@@ -56,8 +57,7 @@
 
   FT_LOCAL_DEF( void )
   af_latin2_metrics_init_widths( AF_LatinMetrics  metrics,
-                                 FT_Face          face,
-                                 FT_ULong         charcode )
+                                 FT_Face          face )
   {
     /* scan the array of segments in each direction */
     AF_GlyphHintsRec  hints[1];
@@ -76,7 +76,8 @@
       AF_Scaler            scaler = &dummy->root.scaler;
 
 
-      glyph_index = FT_Get_Char_Index( face, charcode );
+      glyph_index = FT_Get_Char_Index( face,
+                                       metrics->root.clazz->standard_char );
       if ( glyph_index == 0 )
         goto Exit;
 
@@ -198,8 +199,8 @@
     /* 'af_latin2_blue_chars[blues]' string, then compute its top-most or */
     /* bottom-most points (depending on `AF_IS_TOP_BLUE')                 */
 
-    FT_TRACE5(( "blue zones computation\n" ));
-    FT_TRACE5(( "------------------------------------------------\n" ));
+    FT_TRACE5(( "blue zones computation\n"
+                "======================\n\n" ));
 
     for ( bb = 0; bb < AF_LATIN_BLUE_MAX; bb++ )
     {
@@ -209,7 +210,7 @@
       FT_Pos*      blue_shoot;
 
 
-      FT_TRACE5(( "blue %3d: ", bb ));
+      FT_TRACE5(( "blue zone %d:\n", bb ));
 
       num_flats  = 0;
       num_rounds = 0;
@@ -222,8 +223,6 @@
         FT_Bool     round;
 
 
-        FT_TRACE5(( "'%c'", *p ));
-
         /* load the character in the face -- skip unknown or empty ones */
         glyph_index = FT_Get_Char_Index( face, (FT_UInt)*p );
         if ( glyph_index == 0 )
@@ -285,13 +284,14 @@
               best_last  = last;
             }
           }
-          FT_TRACE5(( "%5d", best_y ));
+          FT_TRACE5(( "  %c  %d", *p, best_y ));
         }
 
         /* now check whether the point belongs to a straight or round   */
         /* segment; we first need to find in which contour the extremum */
         /* lies, then inspect its previous and next points              */
         {
+          FT_Pos  best_x = points[best_point].x;
           FT_Int  start, end, prev, next;
           FT_Pos  dist;
 
@@ -302,13 +302,16 @@
 
           do
           {
-            prev = start-1;
+            prev = start - 1;
             if ( prev < best_first )
               prev = best_last;
 
-            dist = points[prev].y - best_y;
-            if ( dist < -5 || dist > 5 )
-              break;
+            dist = FT_ABS( points[prev].y - best_y );
+            /* accept a small distance or a small angle (both values are */
+            /* heuristic; value 20 corresponds to approx. 2.9 degrees)   */
+            if ( dist > 5 )
+              if ( FT_ABS( points[prev].x - best_x ) <= 20 * dist )
+                break;
 
             start = prev;
 
@@ -316,13 +319,14 @@
 
           do
           {
-            next = end+1;
+            next = end + 1;
             if ( next > best_last )
               next = best_first;
 
-            dist = points[next].y - best_y;
-            if ( dist < -5 || dist > 5 )
-              break;
+            dist = FT_ABS( points[next].y - best_y );
+            if ( dist > 5 )
+              if ( FT_ABS( points[next].x - best_x ) <= 20 * dist )
+                break;
 
             end = next;
 
@@ -333,7 +337,7 @@
             FT_CURVE_TAG( glyph->outline.tags[start] ) != FT_CURVE_TAG_ON ||
             FT_CURVE_TAG( glyph->outline.tags[ end ] ) != FT_CURVE_TAG_ON );
 
-          FT_TRACE5(( "%c ", round ? 'r' : 'f' ));
+          FT_TRACE5(( " (%s)\n", round ? "round" : "flat" ));
         }
 
         if ( round )
@@ -342,15 +346,13 @@
           flats[num_flats++]   = best_y;
       }
 
-      FT_TRACE5(( "\n" ));
-
       if ( num_flats == 0 && num_rounds == 0 )
       {
         /*
          *  we couldn't find a single glyph to compute this blue zone,
          *  we will simply ignore it then
          */
-        FT_TRACE5(( "empty\n" ));
+        FT_TRACE5(( "  empty\n" ));
         continue;
       }
 
@@ -393,7 +395,13 @@
 
 
         if ( AF_LATIN_IS_TOP_BLUE( bb ) ^ over_ref )
-          *blue_shoot = *blue_ref = ( shoot + ref ) / 2;
+        {
+          *blue_ref   =
+          *blue_shoot = ( shoot + ref ) / 2;
+
+          FT_TRACE5(( "  [overshoot smaller than reference,"
+                      " taking mean value]\n" ));
+        }
       }
 
       blue->flags = 0;
@@ -408,7 +416,9 @@
       if ( bb == AF_LATIN_BLUE_SMALL_TOP )
         blue->flags |= AF_LATIN_BLUE_ADJUSTMENT;
 
-      FT_TRACE5(( "-- ref = %ld, shoot = %ld\n", *blue_ref, *blue_shoot ));
+      FT_TRACE5(( "    -> reference = %ld\n"
+                  "       overshoot = %ld\n",
+                  *blue_ref, *blue_shoot ));
     }
 
     return;
@@ -465,7 +475,7 @@
   af_latin2_metrics_init( AF_LatinMetrics  metrics,
                           FT_Face          face )
   {
-    FT_Error    error = AF_Err_Ok;
+    FT_Error    error  = FT_Err_Ok;
     FT_CharMap  oldmap = face->charmap;
     FT_UInt     ee;
 
@@ -491,14 +501,13 @@
 
     if ( !error )
     {
-      /* For now, compute the standard width and height from the `o'. */
-      af_latin2_metrics_init_widths( metrics, face, 'o' );
+      af_latin2_metrics_init_widths( metrics, face );
       af_latin2_metrics_init_blues( metrics, face );
       af_latin2_metrics_check_digits( metrics, face );
     }
 
     FT_Set_Charmap( face, oldmap );
-    return AF_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
@@ -553,8 +562,26 @@
 
       if ( blue )
       {
-        FT_Pos  scaled = FT_MulFix( blue->shoot.org, scaler->y_scale );
-        FT_Pos  fitted = ( scaled + 40 ) & ~63;
+        FT_Pos   scaled;
+        FT_Pos   threshold;
+        FT_Pos   fitted;
+        FT_UInt  limit;
+        FT_UInt  ppem;
+
+
+        scaled    = FT_MulFix( blue->shoot.org, scaler->y_scale );
+        ppem      = metrics->root.scaler.face->size->metrics.x_ppem;
+        limit     = metrics->root.globals->increase_x_height;
+        threshold = 40;
+
+        /* if the `increase-x-height' property is active, */
+        /* we round up much more often                    */
+        if ( limit                                 &&
+             ppem <= limit                         &&
+             ppem >= AF_PROP_INCREASE_X_HEIGHT_MIN )
+          threshold = 52;
+
+        fitted = ( scaled + threshold ) & ~63;
 
 #if 1
         if ( scaled != fitted )
@@ -658,6 +685,7 @@
   {
     metrics->root.scaler.render_mode = scaler->render_mode;
     metrics->root.scaler.face        = scaler->face;
+    metrics->root.scaler.flags       = scaler->flags;
 
     af_latin2_metrics_scale_dim( metrics, scaler, AF_DIMENSION_HORZ );
     af_latin2_metrics_scale_dim( metrics, scaler, AF_DIMENSION_VERT );
@@ -680,7 +708,7 @@
   {
     AF_AxisHints  axis          = &hints->axis[dim];
     FT_Memory     memory        = hints->memory;
-    FT_Error      error         = AF_Err_Ok;
+    FT_Error      error         = FT_Err_Ok;
     AF_Segment    segment       = NULL;
     AF_SegmentRec seg0;
     AF_Point*     contour       = hints->contours;
@@ -796,17 +824,17 @@
         segment->dir       = first->out_dir;
         segment->first     = first;
         segment->last      = point;
-        segment->pos       = (FT_Short)(( min_u + max_u ) >> 1);
+        segment->pos       = (FT_Short)( ( min_u + max_u ) >> 1 );
         segment->min_coord = (FT_Short) min_v;
         segment->max_coord = (FT_Short) max_v;
-        segment->height    = (FT_Short)(max_v - min_v);
+        segment->height    = (FT_Short)( max_v - min_v );
 
         /* a segment is round if it doesn't have successive */
         /* on-curve points.                                 */
         {
           AF_Point  pt   = first;
           AF_Point  last = point;
-          AF_Flags  f0   = (AF_Flags)(pt->flags & AF_FLAG_CONTROL);
+          AF_Flags  f0   = (AF_Flags)( pt->flags & AF_FLAG_CONTROL );
           AF_Flags  f1;
 
 
@@ -815,7 +843,7 @@
           for ( ; pt != last; f0 = f1 )
           {
             pt = pt->next;
-            f1 = (AF_Flags)(pt->flags & AF_FLAG_CONTROL);
+            f1 = (AF_Flags)( pt->flags & AF_FLAG_CONTROL );
 
             if ( !f0 && !f1 )
               break;
@@ -832,7 +860,7 @@
           break;
 
         /* jump to the start of the next segment, if any */
-        while ( FT_ABS(point->out_dir) != major_dir )
+        while ( FT_ABS( point->out_dir ) != major_dir )
         {
           point = point->next;
 
@@ -900,16 +928,17 @@
       FT_UInt     count    = axis->num_segments;
       FT_UInt     ii, jj;
 
-      for (ii = 0; ii < count; ii++)
+      for ( ii = 0; ii < count; ii++ )
       {
         if ( segments[ii].dir > 0 )
         {
-          for (jj = ii+1; jj < count; jj++)
+          for ( jj = ii + 1; jj < count; jj++ )
           {
             if ( segments[jj].dir < 0 )
             {
               AF_SegmentRec  tmp;
 
+
               tmp          = segments[ii];
               segments[ii] = segments[jj];
               segments[jj] = tmp;
@@ -1036,7 +1065,7 @@
                                  AF_Dimension   dim )
   {
     AF_AxisHints  axis   = &hints->axis[dim];
-    FT_Error      error  = AF_Err_Ok;
+    FT_Error      error  = FT_Err_Ok;
     FT_Memory     memory = hints->memory;
     AF_LatinAxis  laxis  = &((AF_LatinMetrics)hints->metrics)->axis[dim];
 
@@ -1070,7 +1099,7 @@
     if ( dim == AF_DIMENSION_HORZ )
     {
       if ( laxis->width_count > 0 )
-        segment_length_threshold = (laxis->standard_width * 10 ) >> 4;
+        segment_length_threshold = ( laxis->standard_width * 10 ) >> 4;
       else
         segment_length_threshold = FT_DivFix( 64, hints->y_scale );
     }
@@ -1116,10 +1145,11 @@
       {
         FT_Pos  dist = seg->serif->pos - seg->pos;
 
-        if (dist < 0)
+
+        if ( dist < 0 )
           dist = -dist;
 
-        if (dist >= laxis->standard_width >> 1)
+        if ( dist >= laxis->standard_width >> 1 )
         {
           /* unlink this serif, it is too distant from its reference stem */
           seg->serif = NULL;
@@ -1417,7 +1447,7 @@
             compare = &blue->ref;
 
           dist = edge->fpos - compare->org;
-          if (dist < 0)
+          if ( dist < 0 )
             dist = -dist;
 
           dist = FT_MulFix( dist, scale );
@@ -1521,8 +1551,8 @@
      *  In `light' hinting mode we disable horizontal hinting completely.
      *  We also do it if the face is italic.
      */
-    if ( mode == FT_RENDER_MODE_LIGHT                    ||
-         (face->style_flags & FT_STYLE_FLAG_ITALIC) != 0 )
+    if ( mode == FT_RENDER_MODE_LIGHT                      ||
+         ( face->style_flags & FT_STYLE_FLAG_ITALIC ) != 0 )
       scaler_flags |= AF_SCALER_FLAG_NO_HORIZONTAL;
 
     hints->scaler_flags = scaler_flags;
@@ -1603,8 +1633,8 @@
     FT_Int           sign     = 0;
     FT_Int           vertical = ( dim == AF_DIMENSION_VERT );
 
+    FT_UNUSED( base_flags );
 
-    FT_UNUSED(base_flags);
 
     if ( !AF_LATIN_HINTS_DO_STEM_ADJUST( hints ) ||
           axis->extra_light                      )
@@ -1734,7 +1764,7 @@
             if ( delta < 0 )
               delta = -delta;
 
-            if (delta >= 16)
+            if ( delta >= 16 )
             {
               dist = org_dist;
               if ( dist < 48 )
@@ -1788,7 +1818,7 @@
   {
     FT_UNUSED( hints );
 
-    serif->pos = base->pos + (serif->opos - base->opos);
+    serif->pos = base->pos + ( serif->opos - base->opos );
   }
 
 
@@ -1870,9 +1900,10 @@
         {
           anchor = edge;
 
-          anchor_drift = (anchor->pos - anchor->opos);
-          if (edge2)
-            anchor_drift = (anchor_drift + (edge2->pos - edge2->opos)) >> 1;
+          anchor_drift = ( anchor->pos - anchor->opos );
+          if ( edge2 )
+            anchor_drift = ( anchor_drift +
+                             ( edge2->pos - edge2->opos ) ) >> 1;
         }
       }
     }
@@ -1964,8 +1995,8 @@
 
         edge2->flags |= AF_EDGE_DONE;
 
-        anchor_drift = ( (anchor->pos - anchor->opos) +
-                         (edge2->pos - edge2->opos)) >> 1;
+        anchor_drift = ( ( anchor->pos - anchor->opos ) +
+                         ( edge2->pos - edge2->opos ) ) >> 1;
 
         FT_TRACE5(( "DRIFT: %.2f\n", anchor_drift/64.0 ));
       }
@@ -1984,8 +2015,8 @@
                    (AF_Edge_Flags)edge->flags,
                    (AF_Edge_Flags)edge2->flags );
 
-        org_left  = org_pos + ((org_len - cur_len) >> 1);
-        org_right = org_pos + ((org_len + cur_len) >> 1);
+        org_left  = org_pos + ( ( org_len - cur_len ) >> 1 );
+        org_right = org_pos + ( ( org_len + cur_len ) >> 1 );
 
         FT_TRACE5(( "ALIGN: left=%.2f right=%.2f ",
                     org_left / 64.0, org_right / 64.0 ));
@@ -2013,13 +2044,13 @@
           }
 
           /* if the span is within a single pixel, don't touch it */
-          if ( FT_PIX_FLOOR(org_left) == FT_PIX_CEIL(org_right) )
+          if ( FT_PIX_FLOOR( org_left ) == FT_PIX_CEIL( org_right ) )
           {
             FT_TRACE5(( "single pixel stem\n" ));
             goto AlignStem;
           }
 
-          if (cur_len <= 96)
+          if ( cur_len <= 96 )
           {
            /* we want to avoid the absolute worst case which is
             * when the left and right edges of the span each represent
@@ -2027,43 +2058,43 @@
             * to 25/75%, since this is much more pleasant to the eye with
             * very acceptable distortion
             */
-            FT_Pos  frac_left  = (org_left) & 63;
-            FT_Pos  frac_right = (org_right) & 63;
+            FT_Pos  frac_left  = org_left  & 63;
+            FT_Pos  frac_right = org_right & 63;
 
             if ( frac_left  >= 22 && frac_left  <= 42 &&
                  frac_right >= 22 && frac_right <= 42 )
             {
               org = frac_left;
-              fit = (org <= 32) ? 16 : 48;
-              delta = FT_ABS(fit - org);
+              fit = ( org <= 32 ) ? 16 : 48;
+              delta = FT_ABS( fit - org );
               displacements[count] = fit - org;
               scores[count++]      = delta;
-              FT_TRACE5(( "dispA=%.2f (%d) ", (fit - org) / 64.0, delta ));
+              FT_TRACE5(( "dispA=%.2f (%d) ", ( fit - org ) / 64.0, delta ));
 
               org = frac_right;
-              fit = (org <= 32) ? 16 : 48;
-              delta = FT_ABS(fit - org);
+              fit = ( org <= 32 ) ? 16 : 48;
+              delta = FT_ABS( fit - org );
               displacements[count] = fit - org;
               scores[count++]     = delta;
-              FT_TRACE5(( "dispB=%.2f (%d) ", (fit - org) / 64.0, delta ));
+              FT_TRACE5(( "dispB=%.2f (%d) ", ( fit - org ) / 64.0, delta ));
             }
           }
 
           /* snapping the left edge to the grid */
           org   = org_left;
-          fit   = FT_PIX_ROUND(org);
-          delta = FT_ABS(fit - org);
+          fit   = FT_PIX_ROUND( org );
+          delta = FT_ABS( fit - org );
           displacements[count] = fit - org;
           scores[count++]      = delta;
-          FT_TRACE5(( "dispC=%.2f (%d) ", (fit - org) / 64.0, delta ));
+          FT_TRACE5(( "dispC=%.2f (%d) ", ( fit - org ) / 64.0, delta ));
 
           /* snapping the right edge to the grid */
           org   = org_right;
-          fit   = FT_PIX_ROUND(org);
-          delta = FT_ABS(fit - org);
+          fit   = FT_PIX_ROUND( org );
+          delta = FT_ABS( fit - org );
           displacements[count] = fit - org;
           scores[count++]      = delta;
-          FT_TRACE5(( "dispD=%.2f (%d) ", (fit - org) / 64.0, delta ));
+          FT_TRACE5(( "dispD=%.2f (%d) ", ( fit - org ) / 64.0, delta ));
 
           /* now find the best displacement */
           {
@@ -2071,9 +2102,9 @@
             FT_Pos  best_disp  = displacements[0];
             FT_UInt nn;
 
-            for (nn = 1; nn < count; nn++)
+            for ( nn = 1; nn < count; nn++ )
             {
-              if (scores[nn] < best_score)
+              if ( scores[nn] < best_score )
               {
                 best_score = scores[nn];
                 best_disp  = displacements[nn];
@@ -2086,7 +2117,7 @@
         }
 
       AlignStem:
-        edge->pos  = cur_center - (cur_len >> 1);
+        edge->pos  = cur_center - ( cur_len >> 1 );
         edge2->pos = edge->pos + cur_len;
 
         FT_TRACE5(( "STEM1: %d (opos=%.2f) to %d (opos=%.2f)"
@@ -2359,6 +2390,7 @@
   AF_DEFINE_SCRIPT_CLASS( af_latin2_script_class,
     AF_SCRIPT_LATIN2,
     af_latin2_uniranges,
+    'o',
 
     sizeof ( AF_LatinMetricsRec ),
 
diff --git a/src/autofit/aflatin2.h b/src/autofit/aflatin2.h
index 925c621..cbfa395 100644
--- a/src/autofit/aflatin2.h
+++ b/src/autofit/aflatin2.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter hinting routines for latin script (specification).       */
 /*                                                                         */
-/*  Copyright 2003, 2004, 2005, 2006, 2007 by                              */
+/*  Copyright 2003-2007, 2012 by                                           */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -27,7 +27,7 @@
 
   /* the latin-specific script class */
 
-  AF_DECLARE_SCRIPT_CLASS(af_latin2_script_class)
+  AF_DECLARE_SCRIPT_CLASS( af_latin2_script_class )
 
 /* */
 
diff --git a/src/autofit/afloader.c b/src/autofit/afloader.c
index 34ef9d8..17a6fb7 100644
--- a/src/autofit/afloader.c
+++ b/src/autofit/afloader.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter glyph loading routines (body).                           */
 /*                                                                         */
-/*  Copyright 2003-2009, 2011-2012 by                                      */
+/*  Copyright 2003-2009, 2011-2013 by                                      */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,18 +16,22 @@
 /***************************************************************************/
 
 
+#include "afglobal.h"
 #include "afloader.h"
 #include "afhints.h"
-#include "afglobal.h"
 #include "aferrors.h"
+#include "afmodule.h"
 
 
   /* Initialize glyph loader. */
 
   FT_LOCAL_DEF( FT_Error )
-  af_loader_init( AF_Loader  loader,
-                  FT_Memory  memory )
+  af_loader_init( AF_Module  module )
   {
+    AF_Loader  loader = module->loader;
+    FT_Memory  memory = module->root.library->memory;
+
+
     FT_ZERO( loader );
 
     af_glyph_hints_init( &loader->hints, memory );
@@ -41,10 +45,11 @@
   /* Reset glyph loader and compute globals if necessary. */
 
   FT_LOCAL_DEF( FT_Error )
-  af_loader_reset( AF_Loader  loader,
+  af_loader_reset( AF_Module  module,
                    FT_Face    face )
   {
-    FT_Error  error = AF_Err_Ok;
+    FT_Error   error  = FT_Err_Ok;
+    AF_Loader  loader = module->loader;
 
 
     loader->face    = face;
@@ -54,7 +59,7 @@
 
     if ( loader->globals == NULL )
     {
-      error = af_face_globals_new( face, &loader->globals );
+      error = af_face_globals_new( face, &loader->globals, module );
       if ( !error )
       {
         face->autohint.data =
@@ -71,8 +76,11 @@
   /* Finalize glyph loader. */
 
   FT_LOCAL_DEF( void )
-  af_loader_done( AF_Loader  loader )
+  af_loader_done( AF_Module  module )
   {
+    AF_Loader  loader = module->loader;
+
+
     af_glyph_hints_done( &loader->hints );
 
     loader->face    = NULL;
@@ -104,9 +112,11 @@
     AF_GlyphHints     hints    = &loader->hints;
     FT_GlyphSlot      slot     = face->glyph;
     FT_Slot_Internal  internal = slot->internal;
+    FT_Int32          flags;
 
 
-    error = FT_Load_Glyph( face, glyph_index, load_flags );
+    flags = load_flags | FT_LOAD_LINEAR_DESIGN;
+    error = FT_Load_Glyph( face, glyph_index, flags );
     if ( error )
       goto Exit;
 
@@ -124,10 +134,6 @@
       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:
@@ -137,8 +143,8 @@
                               loader->trans_delta.x,
                               loader->trans_delta.y );
 
-      /* copy the outline points in the loader's current               */
-      /* extra points which is used to keep original glyph coordinates */
+      /* copy the outline points in the loader's current                */
+      /* extra points which are used to keep original glyph coordinates */
       error = FT_GLYPHLOADER_CHECK_POINTS( gloader,
                                            slot->outline.n_points + 4,
                                            slot->outline.n_contours );
@@ -343,14 +349,14 @@
             if ( start_point + k >= num_base_points         ||
                                l >= (FT_UInt)num_new_points )
             {
-              error = AF_Err_Invalid_Composite;
+              error = FT_THROW( 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 */
+            /* for now, only use the current point coordinates; */
+            /* we eventually may consider another approach      */
             p1 = gloader->base.outline.points + start_point + k;
             p2 = gloader->base.outline.points + start_point + l;
 
@@ -381,7 +387,7 @@
 
     default:
       /* we don't support other formats (yet?) */
-      error = AF_Err_Unimplemented_Feature;
+      error = FT_THROW( Unimplemented_Feature );
     }
 
   Hint_Metrics:
@@ -484,18 +490,19 @@
   /* Load a glyph. */
 
   FT_LOCAL_DEF( FT_Error )
-  af_loader_load_glyph( AF_Loader  loader,
+  af_loader_load_glyph( AF_Module  module,
                         FT_Face    face,
                         FT_UInt    gindex,
                         FT_Int32   load_flags )
   {
     FT_Error      error;
-    FT_Size       size = face->size;
+    FT_Size       size   = face->size;
+    AF_Loader     loader = module->loader;
     AF_ScalerRec  scaler;
 
 
     if ( !size )
-      return AF_Err_Invalid_Argument;
+      return FT_THROW( Invalid_Argument );
 
     FT_ZERO( &scaler );
 
@@ -508,7 +515,7 @@
     scaler.render_mode = FT_LOAD_TARGET_MODE( load_flags );
     scaler.flags       = 0;  /* XXX: fix this */
 
-    error = af_loader_reset( loader, face );
+    error = af_loader_reset( module, face );
     if ( !error )
     {
       AF_ScriptMetrics  metrics;
diff --git a/src/autofit/afloader.h b/src/autofit/afloader.h
index eec0e92..1f34d17 100644
--- a/src/autofit/afloader.h
+++ b/src/autofit/afloader.h
@@ -25,11 +25,24 @@
 
 FT_BEGIN_HEADER
 
-  typedef struct AF_LoaderRec_
+  typedef struct AF_ModuleRec_*  AF_Module;
+
+  /*
+   *  The autofitter module's (global) data structure to communicate with
+   *  actual fonts.  If necessary, `local' data like the current face, the
+   *  current face's auto-hint data, or the current glyph's parameters
+   *  relevant to auto-hinting are `swapped in'.  Cf. functions like
+   *  `af_loader_reset' and `af_loader_load_g'.
+   */
+
+  typedef struct  AF_LoaderRec_
   {
-    FT_Face           face;           /* current face */
-    AF_FaceGlobals    globals;        /* current face globals */
-    FT_GlyphLoader    gloader;        /* glyph loader */
+    /* current face data */
+    FT_Face           face;
+    AF_FaceGlobals    globals;
+
+    /* current glyph data */
+    FT_GlyphLoader    gloader;
     AF_GlyphHintsRec  hints;
     AF_ScriptMetrics  metrics;
     FT_Bool           transformed;
@@ -43,21 +56,20 @@
 
 
   FT_LOCAL( FT_Error )
-  af_loader_init( AF_Loader  loader,
-                  FT_Memory  memory );
+  af_loader_init( AF_Module  module );
 
 
   FT_LOCAL( FT_Error )
-  af_loader_reset( AF_Loader  loader,
+  af_loader_reset( AF_Module  module,
                    FT_Face    face );
 
 
   FT_LOCAL( void )
-  af_loader_done( AF_Loader  loader );
+  af_loader_done( AF_Module  module );
 
 
   FT_LOCAL( FT_Error )
-  af_loader_load_glyph( AF_Loader  loader,
+  af_loader_load_glyph( AF_Module  module,
                         FT_Face    face,
                         FT_UInt    gindex,
                         FT_Int32   load_flags );
diff --git a/src/autofit/afmodule.c b/src/autofit/afmodule.c
index 20b6218..b1bb5ee 100644
--- a/src/autofit/afmodule.c
+++ b/src/autofit/afmodule.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter module implementation (body).                            */
 /*                                                                         */
-/*  Copyright 2003-2006, 2009, 2011 by                                     */
+/*  Copyright 2003-2006, 2009, 2011-2013 by                                */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,8 +16,10 @@
 /***************************************************************************/
 
 
+#include "afglobal.h"
 #include "afmodule.h"
 #include "afloader.h"
+#include "aferrors.h"
 #include "afpic.h"
 
 #ifdef FT_DEBUG_AUTOFIT
@@ -28,66 +30,235 @@
 #endif
 
 #include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_DEBUG_H
+#include FT_AUTOHINTER_H
+#include FT_SERVICE_PROPERTIES_H
 
 
-  typedef struct  FT_AutofitterRec_
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_afmodule
+
+
+  FT_Error
+  af_property_get_face_globals( FT_Face          face,
+                                AF_FaceGlobals*  aglobals,
+                                AF_Module        module )
   {
-    FT_ModuleRec  root;
-    AF_LoaderRec  loader[1];
+    FT_Error        error = FT_Err_Ok;
+    AF_FaceGlobals  globals;
 
-  } FT_AutofitterRec, *FT_Autofitter;
+
+    if ( !face )
+      return FT_THROW( Invalid_Argument );
+
+    globals = (AF_FaceGlobals)face->autohint.data;
+    if ( !globals )
+    {
+      /* trigger computation of the global script data */
+      /* in case it hasn't been done yet               */
+      error = af_face_globals_new( face, &globals, module );
+      if ( !error )
+      {
+        face->autohint.data =
+          (FT_Pointer)globals;
+        face->autohint.finalizer =
+          (FT_Generic_Finalizer)af_face_globals_free;
+      }
+    }
+
+    if ( !error )
+      *aglobals = globals;
+
+    return error;
+  }
+
+
+  FT_Error
+  af_property_set( FT_Module    ft_module,
+                   const char*  property_name,
+                   const void*  value )
+  {
+    FT_Error   error  = FT_Err_Ok;
+    AF_Module  module = (AF_Module)ft_module;
+
+
+    if ( !ft_strcmp( property_name, "fallback-script" ) )
+    {
+      FT_UInt*  fallback_script = (FT_UInt*)value;
+
+
+      module->fallback_script = *fallback_script;
+
+      return error;
+    }
+    else if ( !ft_strcmp( property_name, "increase-x-height" ) )
+    {
+      FT_Prop_IncreaseXHeight*  prop = (FT_Prop_IncreaseXHeight*)value;
+      AF_FaceGlobals            globals;
+
+
+      error = af_property_get_face_globals( prop->face, &globals, module );
+      if ( !error )
+        globals->increase_x_height = prop->limit;
+
+      return error;
+    }
+
+    FT_TRACE0(( "af_property_set: missing property `%s'\n",
+                property_name ));
+    return FT_THROW( Missing_Property );
+  }
+
+
+  FT_Error
+  af_property_get( FT_Module    ft_module,
+                   const char*  property_name,
+                   void*        value )
+  {
+    FT_Error   error           = FT_Err_Ok;
+    AF_Module  module          = (AF_Module)ft_module;
+    FT_UInt    fallback_script = module->fallback_script;
+
+
+    if ( !ft_strcmp( property_name, "glyph-to-script-map" ) )
+    {
+      FT_Prop_GlyphToScriptMap*  prop = (FT_Prop_GlyphToScriptMap*)value;
+      AF_FaceGlobals             globals;
+
+
+      error = af_property_get_face_globals( prop->face, &globals, module );
+      if ( !error )
+        prop->map = globals->glyph_scripts;
+
+      return error;
+    }
+    else if ( !ft_strcmp( property_name, "fallback-script" ) )
+    {
+      FT_UInt*  val = (FT_UInt*)value;
+
+
+      *val = fallback_script;
+
+      return error;
+    }
+    else if ( !ft_strcmp( property_name, "increase-x-height" ) )
+    {
+      FT_Prop_IncreaseXHeight*  prop = (FT_Prop_IncreaseXHeight*)value;
+      AF_FaceGlobals            globals;
+
+
+      error = af_property_get_face_globals( prop->face, &globals, module );
+      if ( !error )
+        prop->limit = globals->increase_x_height;
+
+      return error;
+    }
+
+
+    FT_TRACE0(( "af_property_get: missing property `%s'\n",
+                property_name ));
+    return FT_THROW( Missing_Property );
+  }
+
+
+  FT_DEFINE_SERVICE_PROPERTIESREC(
+    af_service_properties,
+    (FT_Properties_SetFunc)af_property_set,
+    (FT_Properties_GetFunc)af_property_get )
+
+
+  FT_DEFINE_SERVICEDESCREC1(
+    af_services,
+    FT_SERVICE_ID_PROPERTIES, &AF_SERVICE_PROPERTIES_GET )
+
+
+  FT_CALLBACK_DEF( FT_Module_Interface )
+  af_get_interface( FT_Module    module,
+                    const char*  module_interface )
+  {
+    /* AF_SERVICES_GET derefers `library' in PIC mode */
+#ifdef FT_CONFIG_OPTION_PIC
+    FT_Library  library;
+
+
+    if ( !module )
+      return NULL;
+    library = module->library;
+    if ( !library )
+      return NULL;
+#else
+    FT_UNUSED( module );
+#endif
+
+    return ft_service_list_lookup( AF_SERVICES_GET, module_interface );
+  }
 
 
   FT_CALLBACK_DEF( FT_Error )
-  af_autofitter_init( FT_Autofitter  module )
+  af_autofitter_init( FT_Module  ft_module )      /* AF_Module */
   {
-    return af_loader_init( module->loader, module->root.library->memory );
+    AF_Module  module = (AF_Module)ft_module;
+
+
+    module->fallback_script = AF_SCRIPT_FALLBACK;
+
+    return af_loader_init( module );
   }
 
 
   FT_CALLBACK_DEF( void )
-  af_autofitter_done( FT_Autofitter  module )
+  af_autofitter_done( FT_Module  ft_module )      /* AF_Module */
   {
-    af_loader_done( module->loader );
+    AF_Module  module = (AF_Module)ft_module;
+
+
+    af_loader_done( module );
   }
 
 
   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 )
+  af_autofitter_load_glyph( AF_Module     module,
+                            FT_GlyphSlot  slot,
+                            FT_Size       size,
+                            FT_UInt       glyph_index,
+                            FT_Int32      load_flags )
   {
     FT_UNUSED( size );
 
-    return af_loader_load_glyph( module->loader, slot->face,
+    return af_loader_load_glyph( module, slot->face,
                                  glyph_index, load_flags );
   }
 
 
-  FT_DEFINE_AUTOHINTER_SERVICE(
-    af_autofitter_service,
-    NULL,
-    NULL,
-    NULL,
-    (FT_AutoHinter_GlyphLoadFunc)af_autofitter_load_glyph )
+  FT_DEFINE_AUTOHINTER_INTERFACE(
+    af_autofitter_interface,
+    NULL,                                                    /* reset_face */
+    NULL,                                              /* get_global_hints */
+    NULL,                                             /* done_global_hints */
+    (FT_AutoHinter_GlyphLoadFunc)af_autofitter_load_glyph )  /* load_glyph */
+
 
   FT_DEFINE_MODULE(
     autofit_module_class,
 
     FT_MODULE_HINTER,
-    sizeof ( FT_AutofitterRec ),
+    sizeof ( AF_ModuleRec ),
 
     "autofitter",
     0x10000L,   /* version 1.0 of the autofitter  */
     0x20000L,   /* requires FreeType 2.0 or above */
 
-    (const void*)&AF_AF_AUTOFITTER_SERVICE_GET,
+    (const void*)&AF_INTERFACE_GET,
 
     (FT_Module_Constructor)af_autofitter_init,
     (FT_Module_Destructor) af_autofitter_done,
-    (FT_Module_Requester)  NULL )
+    (FT_Module_Requester)  af_get_interface )
 
 
 /* END */
diff --git a/src/autofit/afmodule.h b/src/autofit/afmodule.h
index d979239..c4e8f8f 100644
--- a/src/autofit/afmodule.h
+++ b/src/autofit/afmodule.h
@@ -23,9 +23,30 @@
 #include FT_INTERNAL_OBJECTS_H
 #include FT_MODULE_H
 
+#include "afloader.h"
+
 
 FT_BEGIN_HEADER
 
+
+  /*
+   *  This is the `extended' FT_Module structure which holds the
+   *  autofitter's global data.  Right before hinting a glyph, the data
+   *  specific to the glyph's face (blue zones, stem widths, etc.) are
+   *  loaded into `loader' (see function `af_loader_reset').
+   */
+
+  typedef struct  AF_ModuleRec_
+  {
+    FT_ModuleRec  root;
+
+    FT_UInt       fallback_script;
+
+    AF_LoaderRec  loader[1];
+
+  } AF_ModuleRec;
+
+
 FT_DECLARE_MODULE(autofit_module_class)
 
 
diff --git a/src/autofit/afpic.c b/src/autofit/afpic.c
index 87074af..45e1448 100644
--- a/src/autofit/afpic.c
+++ b/src/autofit/afpic.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType position independent code services for autofit module.  */
 /*                                                                         */
-/*  Copyright 2009, 2010, 2011 by                                          */
+/*  Copyright 2009-2013 by                                                 */
 /*  Oran Agra and Mickey Gabel.                                            */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -22,12 +22,25 @@
 #include "afpic.h"
 #include "aferrors.h"
 
+
 #ifdef FT_CONFIG_OPTION_PIC
 
   /* forward declaration of PIC init functions from afmodule.c */
-  void FT_Init_Class_af_autofitter_service(
-    FT_Library                 library,
-    FT_AutoHinter_ServiceRec*  clazz );
+  FT_Error
+  FT_Create_Class_af_services( FT_Library           library,
+                               FT_ServiceDescRec**  output_class );
+
+  void
+  FT_Destroy_Class_af_services( FT_Library          library,
+                                FT_ServiceDescRec*  clazz );
+
+  void
+  FT_Init_Class_af_service_properties( FT_Service_PropertiesRec*  clazz );
+
+  void FT_Init_Class_af_autofitter_interface(
+    FT_Library                   library,
+    FT_AutoHinter_InterfaceRec*  clazz );
+
 
   /* forward declaration of PIC init functions from script classes */
 #include "aflatin.h"
@@ -38,6 +51,7 @@
 #include "afdummy.h"
 #include "afindic.h"
 
+
   void
   autofit_module_class_pic_free( FT_Library  library )
   {
@@ -47,7 +61,15 @@
 
     if ( pic_container->autofit )
     {
-      FT_FREE( pic_container->autofit );
+      AFModulePIC*  container = (AFModulePIC*)pic_container->autofit;
+
+
+      if ( container->af_services )
+        FT_Destroy_Class_af_services( library,
+                                      container->af_services );
+      container->af_services = NULL;
+
+      FT_FREE( container );
       pic_container->autofit = NULL;
     }
   }
@@ -58,8 +80,8 @@
   {
     FT_PIC_Container*  pic_container = &library->pic_container;
     FT_UInt            ss;
-    FT_Error           error         = AF_Err_Ok;
-    AFModulePIC*       container;
+    FT_Error           error         = FT_Err_Ok;
+    AFModulePIC*       container     = NULL;
     FT_Memory          memory        = library->memory;
 
 
@@ -71,6 +93,13 @@
 
     /* initialize pointer table -                       */
     /* this is how the module usually expects this data */
+    error = FT_Create_Class_af_services( library,
+                                         &container->af_services );
+    if ( error )
+      goto Exit;
+
+    FT_Init_Class_af_service_properties( &container->af_service_properties );
+
     for ( ss = 0 ; ss < AF_SCRIPT_CLASSES_REC_COUNT ; ss++ )
     {
       container->af_script_classes[ss] =
@@ -93,17 +122,15 @@
     FT_Init_Class_af_indic_script_class(
       &container->af_script_classes_rec[ss++] );
 
-    FT_Init_Class_af_autofitter_service(
-      library, &container->af_autofitter_service );
+    FT_Init_Class_af_autofitter_interface(
+      library, &container->af_autofitter_interface );
 
-/* Exit: */
-
+  Exit:
     if ( error )
       autofit_module_class_pic_free( library );
     return error;
   }
 
-
 #endif /* FT_CONFIG_OPTION_PIC */
 
 
diff --git a/src/autofit/afpic.h b/src/autofit/afpic.h
index 21b0ff9..0acf803 100644
--- a/src/autofit/afpic.h
+++ b/src/autofit/afpic.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType position independent code services for autofit module.  */
 /*                                                                         */
-/*  Copyright 2009, 2011 by                                                */
+/*  Copyright 2009, 2011-2012 by                                           */
 /*  Oran Agra and Mickey Gabel.                                            */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -24,38 +24,58 @@
 
 #include FT_INTERNAL_PIC_H
 
+
 #ifndef FT_CONFIG_OPTION_PIC
 
-#define AF_SCRIPT_CLASSES_GET         af_script_classes
-#define AF_AF_AUTOFITTER_SERVICE_GET  af_autofitter_service
+#define AF_SERVICES_GET            af_services
+#define AF_SERVICE_PROPERTIES_GET  af_service_properties
+
+#define AF_SCRIPT_CLASSES_GET      af_script_classes
+#define AF_INTERFACE_GET           af_autofitter_interface
 
 #else /* FT_CONFIG_OPTION_PIC */
 
+  /* some include files required for members of AFModulePIC */
+#include FT_SERVICE_PROPERTIES_H
+
 #include "aftypes.h"
 
   /* increase these when you add new scripts, */
   /* and update autofit_module_class_pic_init */
 #ifdef FT_OPTION_AUTOFIT2
-#define AF_SCRIPT_CLASSES_COUNT     6
+#define AF_SCRIPT_CLASSES_COUNT  6
 #else
-#define AF_SCRIPT_CLASSES_COUNT     5
+#define AF_SCRIPT_CLASSES_COUNT  5
 #endif
+
 #define AF_SCRIPT_CLASSES_REC_COUNT  ( AF_SCRIPT_CLASSES_COUNT - 1 )
 
-  typedef struct AFModulePIC_
+
+  typedef struct  AFModulePIC_
   {
-    AF_ScriptClass            af_script_classes[AF_SCRIPT_CLASSES_COUNT];
-    AF_ScriptClassRec         af_script_classes_rec[AF_SCRIPT_CLASSES_REC_COUNT];
-    FT_AutoHinter_ServiceRec  af_autofitter_service;
+    FT_ServiceDescRec*          af_services;
+    FT_Service_PropertiesRec    af_service_properties;
+
+    AF_ScriptClass              af_script_classes[AF_SCRIPT_CLASSES_COUNT];
+    AF_ScriptClassRec           af_script_classes_rec[AF_SCRIPT_CLASSES_REC_COUNT];
+    FT_AutoHinter_InterfaceRec  af_autofitter_interface;
 
   } AFModulePIC;
 
-#define GET_PIC( lib )                                                     \
+
+#define GET_PIC( lib )  \
           ( (AFModulePIC*)((lib)->pic_container.autofit) )
-#define AF_SCRIPT_CLASSES_GET                                              \
-          ( GET_PIC( FT_FACE_LIBRARY(globals->face) )->af_script_classes )
-#define AF_AF_AUTOFITTER_SERVICE_GET                                       \
-          ( GET_PIC( library )->af_autofitter_service )
+
+#define AF_SERVICES_GET  \
+          ( GET_PIC( library )->af_services )
+#define AF_SERVICE_PROPERTIES_GET  \
+          ( GET_PIC( library )->af_service_properties )
+
+#define AF_SCRIPT_CLASSES_GET  \
+          ( GET_PIC( FT_FACE_LIBRARY( globals->face ) )->af_script_classes )
+#define AF_INTERFACE_GET  \
+          ( GET_PIC( library )->af_autofitter_interface )
+
 
   /* see afpic.c for the implementation */
   void
diff --git a/src/autofit/aftypes.h b/src/autofit/aftypes.h
index 21e442c..9acd7ad 100644
--- a/src/autofit/aftypes.h
+++ b/src/autofit/aftypes.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auto-fitter types (specification only).                              */
 /*                                                                         */
-/*  Copyright 2003-2009, 2011 by                                           */
+/*  Copyright 2003-2009, 2011-2012 by                                      */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -87,8 +87,9 @@
                FT_Pos*  table );
 
   FT_LOCAL( void )
-  af_sort_widths( FT_UInt   count,
-                  AF_Width  widths );
+  af_sort_and_quantize_widths( FT_UInt*  count,
+                               AF_Width  widths,
+                               FT_Pos    threshold );
 
 
   /*************************************************************************/
@@ -228,12 +229,12 @@
 
   typedef enum  AF_Script_
   {
-    AF_SCRIPT_NONE  = 0,
+    AF_SCRIPT_DUMMY = 0,
     AF_SCRIPT_LATIN = 1,
     AF_SCRIPT_CJK   = 2,
     AF_SCRIPT_INDIC = 3,
 #ifdef FT_OPTION_AUTOFIT2
-    AF_SCRIPT_LATIN2,
+    AF_SCRIPT_LATIN2 = 4,
 #endif
 
     /* add new scripts here.  Don't forget to update the list in */
@@ -245,6 +246,7 @@
 
 
   typedef struct AF_ScriptClassRec_ const*  AF_ScriptClass;
+  typedef struct AF_FaceGlobalsRec_*        AF_FaceGlobals;
 
   typedef struct  AF_ScriptMetricsRec_
   {
@@ -252,6 +254,8 @@
     AF_ScalerRec    scaler;
     FT_Bool         digits_have_same_width;
 
+    AF_FaceGlobals  globals;    /* to access properties */
+
   } AF_ScriptMetricsRec, *AF_ScriptMetrics;
 
 
@@ -294,8 +298,9 @@
 
   typedef struct  AF_ScriptClassRec_
   {
-    AF_Script                   script;
-    AF_Script_UniRange          script_uni_ranges; /* last must be { 0, 0 } */
+    AF_Script           script;
+    AF_Script_UniRange  script_uni_ranges; /* last must be { 0, 0 }        */
+    FT_UInt32           standard_char;     /* for default width and height */
 
     FT_Offset                   script_metrics_size;
     AF_Script_InitMetricsFunc   script_metrics_init;
@@ -315,13 +320,14 @@
   FT_CALLBACK_TABLE const AF_ScriptClassRec     \
   script_class;
 
-#define AF_DEFINE_SCRIPT_CLASS( script_class, script_, ranges, m_size,     \
+#define AF_DEFINE_SCRIPT_CLASS( script_class, script_, ranges, def_char,   \
+                                m_size,                                    \
                                 m_init, m_scale, m_done, h_init, h_apply ) \
-  FT_CALLBACK_TABLE_DEF const AF_ScriptClassRec                            \
-  script_class =                                                           \
+  FT_CALLBACK_TABLE_DEF const AF_ScriptClassRec  script_class =            \
   {                                                                        \
     script_,                                                               \
     ranges,                                                                \
+    def_char,                                                              \
                                                                            \
     m_size,                                                                \
                                                                            \
@@ -335,17 +341,19 @@
 
 #else /* FT_CONFIG_OPTION_PIC */
 
-#define AF_DECLARE_SCRIPT_CLASS( script_class )          \
-  FT_LOCAL( void )                                       \
-  FT_Init_Class_##script_class( AF_ScriptClassRec* ac );
+#define AF_DECLARE_SCRIPT_CLASS( script_class )             \
+  FT_LOCAL( void )                                          \
+  FT_Init_Class_ ## script_class( AF_ScriptClassRec*  ac );
 
-#define AF_DEFINE_SCRIPT_CLASS( script_class, script_, ranges, m_size,     \
+#define AF_DEFINE_SCRIPT_CLASS( script_class, script_, ranges, def_char,   \
+                                m_size,                                    \
                                 m_init, m_scale, m_done, h_init, h_apply ) \
   FT_LOCAL_DEF( void )                                                     \
-  FT_Init_Class_##script_class( AF_ScriptClassRec* ac )                    \
+  FT_Init_Class_ ## script_class( AF_ScriptClassRec*  ac )                 \
   {                                                                        \
     ac->script               = script_;                                    \
     ac->script_uni_ranges    = ranges;                                     \
+    ac->default_char         = def_char;                                   \
                                                                            \
     ac->script_metrics_size  = m_size;                                     \
                                                                            \
diff --git a/src/base/basepic.c b/src/base/basepic.c
index d754eb1..0af770e 100644
--- a/src/base/basepic.c
+++ b/src/base/basepic.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType position independent code services for base.            */
 /*                                                                         */
-/*  Copyright 2009 by                                                      */
+/*  Copyright 2009, 2012 by                                                */
 /*  Oran Agra and Mickey Gabel.                                            */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -21,14 +21,22 @@
 #include FT_INTERNAL_OBJECTS_H
 #include "basepic.h"
 
+
 #ifdef FT_CONFIG_OPTION_PIC
 
   /* forward declaration of PIC init functions from ftglyph.c */
-  void FT_Init_Class_ft_outline_glyph_class( FT_Glyph_Class*  clazz );
-  void FT_Init_Class_ft_bitmap_glyph_class( FT_Glyph_Class*  clazz );
+  void
+  FT_Init_Class_ft_outline_glyph_class( FT_Glyph_Class*  clazz );
 
-  /* forward declaration of PIC init function from ftrfork.c (not modularized) */
-  void FT_Init_Table_raccess_guess_table( ft_raccess_guess_rec*  record );
+  void
+  FT_Init_Class_ft_bitmap_glyph_class( FT_Glyph_Class*  clazz );
+
+#ifdef FT_CONFIG_OPTION_MAC_FONTS
+  /* forward declaration of PIC init function from ftrfork.c */
+  /* (not modularized)                                       */
+  void
+  FT_Init_Table_raccess_guess_table( ft_raccess_guess_rec*  record );
+#endif
 
   /* forward declaration of PIC init functions from ftinit.c */
   FT_Error
@@ -37,14 +45,18 @@
   void
   ft_destroy_default_module_classes( FT_Library  library );
 
+
   void
   ft_base_pic_free( FT_Library  library )
   {
     FT_PIC_Container*  pic_container = &library->pic_container;
-    FT_Memory          memory = library->memory;
+    FT_Memory          memory        = library->memory;
+
+
     if ( pic_container->base )
     {
-      /* Destroy default module classes (in case FT_Add_Default_Modules was used) */
+      /* destroy default module classes            */
+      /* (in case FT_Add_Default_Modules was used) */
       ft_destroy_default_module_classes( library );
 
       FT_FREE( pic_container->base );
@@ -57,12 +69,13 @@
   ft_base_pic_init( FT_Library  library )
   {
     FT_PIC_Container*  pic_container = &library->pic_container;
-    FT_Error           error = FT_Err_Ok;
-    BasePIC*           container;
-    FT_Memory          memory = library->memory;
+    FT_Error           error         = FT_Err_Ok;
+    BasePIC*           container     = NULL;
+    FT_Memory          memory        = library->memory;
+
 
     /* allocate pointer, clear and set global container pointer */
-    if ( FT_ALLOC ( container, sizeof ( *container ) ) )
+    if ( FT_ALLOC( container, sizeof ( *container ) ) )
       return error;
     FT_MEM_SET( container, 0, sizeof ( *container ) );
     pic_container->base = container;
@@ -72,21 +85,23 @@
     if ( error )
       goto Exit;
 
-    /* initialize pointer table - this is how the module usually expects this data */
+    /* initialize pointer table -                       */
+    /* this is how the module usually expects this data */
     FT_Init_Class_ft_outline_glyph_class(
       &container->ft_outline_glyph_class );
     FT_Init_Class_ft_bitmap_glyph_class(
       &container->ft_bitmap_glyph_class );
+#ifdef FT_CONFIG_OPTION_MAC_FONTS
     FT_Init_Table_raccess_guess_table(
-      (ft_raccess_guess_rec*)&container->ft_raccess_guess_table);
+      (ft_raccess_guess_rec*)&container->ft_raccess_guess_table );
+#endif
 
-Exit:
-    if( error )
+  Exit:
+    if ( error )
       ft_base_pic_free( library );
     return error;
   }
 
-
 #endif /* FT_CONFIG_OPTION_PIC */
 
 
diff --git a/src/base/basepic.h b/src/base/basepic.h
index bf90bef..329d7c8 100644
--- a/src/base/basepic.h
+++ b/src/base/basepic.h
@@ -25,11 +25,13 @@
 #include FT_INTERNAL_PIC_H
 
 #ifndef FT_CONFIG_OPTION_PIC
-#define FT_OUTLINE_GLYPH_CLASS_GET &ft_outline_glyph_class
-#define FT_BITMAP_GLYPH_CLASS_GET  &ft_bitmap_glyph_class
-#define FT_DEFAULT_MODULES_GET     ft_default_modules
+
+#define FT_OUTLINE_GLYPH_CLASS_GET  &ft_outline_glyph_class
+#define FT_BITMAP_GLYPH_CLASS_GET   &ft_bitmap_glyph_class
+#define FT_DEFAULT_MODULES_GET      ft_default_modules
+
 #ifdef FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK
-#define FT_RACCESS_GUESS_TABLE_GET ft_raccess_guess_table
+#define FT_RACCESS_GUESS_TABLE_GET  ft_raccess_guess_table
 #endif
 
 #else /* FT_CONFIG_OPTION_PIC */
@@ -41,25 +43,35 @@
 #endif
 
 
-  typedef struct BasePIC_
+  typedef struct  BasePIC_
   {
-    FT_Module_Class** default_module_classes;
-    FT_Glyph_Class ft_outline_glyph_class;
-    FT_Glyph_Class ft_bitmap_glyph_class;
+    FT_Module_Class**  default_module_classes;
+    FT_Glyph_Class     ft_outline_glyph_class;
+    FT_Glyph_Class     ft_bitmap_glyph_class;
+
 #ifdef FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK
-    ft_raccess_guess_rec ft_raccess_guess_table[FT_RACCESS_N_RULES];
+    ft_raccess_guess_rec  ft_raccess_guess_table[FT_RACCESS_N_RULES];
 #endif
+
   } BasePIC;
 
-#define GET_PIC(lib)                  ((BasePIC*)((lib)->pic_container.base))
-#define FT_OUTLINE_GLYPH_CLASS_GET    (&GET_PIC(library)->ft_outline_glyph_class)
-#define FT_BITMAP_GLYPH_CLASS_GET     (&GET_PIC(library)->ft_bitmap_glyph_class)
-#define FT_DEFAULT_MODULES_GET        (GET_PIC(library)->default_module_classes)
+
+#define GET_PIC( lib )  ( (BasePIC*)( (lib)->pic_container.base ) )
+
+#define FT_OUTLINE_GLYPH_CLASS_GET                      \
+          ( &GET_PIC( library )->ft_outline_glyph_class )
+#define FT_BITMAP_GLYPH_CLASS_GET                        \
+          ( &GET_PIC( library )->ft_bitmap_glyph_class )
+#define FT_DEFAULT_MODULES_GET                           \
+          ( GET_PIC( library )->default_module_classes )
+
 #ifdef FT_CONFIG_OPTION_GUESSING_EMBEDDED_RFORK
-#define FT_RACCESS_GUESS_TABLE_GET    (GET_PIC(library)->ft_raccess_guess_table)
+#define FT_RACCESS_GUESS_TABLE_GET                       \
+          ( GET_PIC( library )->ft_raccess_guess_table )
 #endif
 
-  /* see basepic.c for the implementation. */
+
+  /* see basepic.c for the implementation */
   void
   ft_base_pic_free( FT_Library  library );
 
@@ -67,7 +79,8 @@
   ft_base_pic_init( FT_Library  library );
 
 #endif /* FT_CONFIG_OPTION_PIC */
- /* */
+
+  /* */
 
 FT_END_HEADER
 
diff --git a/src/base/ftadvanc.c b/src/base/ftadvanc.c
index a8bb43d..5207847 100644
--- a/src/base/ftadvanc.c
+++ b/src/base/ftadvanc.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Quick computation of advance widths (body).                          */
 /*                                                                         */
-/*  Copyright 2008, 2009, 2011 by                                          */
+/*  Copyright 2008, 2009, 2011, 2013 by                                    */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -17,6 +17,8 @@
 
 
 #include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+
 #include FT_ADVANCES_H
 #include FT_INTERNAL_OBJECTS_H
 
@@ -35,7 +37,7 @@
       return FT_Err_Ok;
 
     if ( face->size == NULL )
-      return FT_Err_Invalid_Size_Handle;
+      return FT_THROW( Invalid_Size_Handle );
 
     if ( flags & FT_LOAD_VERTICAL_LAYOUT )
       scale = face->size->metrics.y_scale;
@@ -76,10 +78,10 @@
 
 
     if ( !face )
-      return FT_Err_Invalid_Face_Handle;
+      return FT_THROW( Invalid_Face_Handle );
 
     if ( gindex >= (FT_UInt)face->num_glyphs )
-      return FT_Err_Invalid_Glyph_Index;
+      return FT_THROW( Invalid_Glyph_Index );
 
     func = face->driver->clazz->get_advances;
     if ( func && LOAD_ADVANCE_FAST_CHECK( flags ) )
@@ -91,7 +93,7 @@
       if ( !error )
         return _ft_face_scale_advances( face, padvance, 1, flags );
 
-      if ( error != FT_ERROR_BASE( FT_Err_Unimplemented_Feature ) )
+      if ( FT_ERR_NEQ( error, Unimplemented_Feature ) )
         return error;
     }
 
@@ -114,12 +116,12 @@
 
 
     if ( !face )
-      return FT_Err_Invalid_Face_Handle;
+      return FT_THROW( Invalid_Face_Handle );
 
     num = (FT_UInt)face->num_glyphs;
     end = start + count;
     if ( start >= num || end < start || end > num )
-      return FT_Err_Invalid_Glyph_Index;
+      return FT_THROW( Invalid_Glyph_Index );
 
     if ( count == 0 )
       return FT_Err_Ok;
@@ -131,14 +133,14 @@
       if ( !error )
         return _ft_face_scale_advances( face, padvances, count, flags );
 
-      if ( error != FT_ERROR_BASE( FT_Err_Unimplemented_Feature ) )
+      if ( FT_ERR_NEQ( error, Unimplemented_Feature ) )
         return error;
     }
 
     error = FT_Err_Ok;
 
     if ( flags & FT_ADVANCE_FLAG_FAST_ONLY )
-      return FT_Err_Unimplemented_Feature;
+      return FT_THROW( Unimplemented_Feature );
 
     flags |= (FT_UInt32)FT_LOAD_ADVANCE_ONLY;
     for ( nn = 0; nn < count; nn++ )
diff --git a/src/base/ftbbox.c b/src/base/ftbbox.c
index 4b8e911..6d1c44c 100644
--- a/src/base/ftbbox.c
+++ b/src/base/ftbbox.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType bbox computation (body).                                    */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2004, 2006, 2010 by                         */
+/*  Copyright 1996-2002, 2004, 2006, 2010, 2013 by                         */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used        */
@@ -25,6 +25,8 @@
 
 
 #include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+
 #include FT_BBOX_H
 #include FT_IMAGE_H
 #include FT_OUTLINE_H
@@ -222,65 +224,100 @@
                     FT_Pos*  min,
                     FT_Pos*  max )
   {
-    FT_Pos  stack[32*3 + 1], *arc;
+    FT_Pos  q1, q2, q3, q4;
 
 
-    arc = stack;
+    q1 = p1;
+    q2 = p2;
+    q3 = p3;
+    q4 = p4;
 
-    arc[0] = p1;
-    arc[1] = p2;
-    arc[2] = p3;
-    arc[3] = p4;
-
-    do
+    /* for a conic segment to possibly reach new maximum     */
+    /* one of its off-points must be above the current value */
+    while ( q2 > *max || q3 > *max )
     {
-      FT_Pos  y1 = arc[0];
-      FT_Pos  y2 = arc[1];
-      FT_Pos  y3 = arc[2];
-      FT_Pos  y4 = arc[3];
-
-
-      if ( y1 == y4 )
+      /* determine which half contains the maximum and split */
+      if ( q1 + q2 > q3 + q4 ) /* first half */
       {
-        if ( y1 == y2 && y1 == y3 )                         /* flat */
-          goto Test;
+        q4 = q4 + q3;
+        q3 = q3 + q2;
+        q2 = q2 + q1;
+        q4 = q4 + q3;
+        q3 = q3 + q2;
+        q4 = ( q4 + q3 ) / 8;
+        q3 = q3 / 4;
+        q2 = q2 / 2;
       }
-      else if ( y1 < y4 )
+      else                     /* second half */
       {
-        if ( y2 >= y1 && y2 <= y4 && y3 >= y1 && y3 <= y4 ) /* ascending */
-          goto Test;
-      }
-      else
-      {
-        if ( y2 >= y4 && y2 <= y1 && y3 >= y4 && y3 <= y1 ) /* descending */
-        {
-          y2 = y1;
-          y1 = y4;
-          y4 = y2;
-          goto Test;
-        }
+        q1 = q1 + q2;
+        q2 = q2 + q3;
+        q3 = q3 + q4;
+        q1 = q1 + q2;
+        q2 = q2 + q3;
+        q1 = ( q1 + q2 ) / 8;
+        q2 = q2 / 4;
+        q3 = q3 / 2;
       }
 
-      /* unknown direction -- split the arc in two */
-      arc[6] = y4;
-      arc[1] = y1 = ( y1 + y2 ) / 2;
-      arc[5] = y4 = ( y4 + y3 ) / 2;
-      y2 = ( y2 + y3 ) / 2;
-      arc[2] = y1 = ( y1 + y2 ) / 2;
-      arc[4] = y4 = ( y4 + y2 ) / 2;
-      arc[3] = ( y1 + y4 ) / 2;
+      /* check if either end reached the maximum */
+      if ( q1 == q2 && q1 >= q3 )
+      {
+        *max = q1;
+        break;
+      }
+      if ( q3 == q4 && q2 <= q4 )
+      {
+        *max = q4;
+        break;
+      }
+    }
 
-      arc += 3;
-      goto Suite;
+    q1 = p1;
+    q2 = p2;
+    q3 = p3;
+    q4 = p4;
 
-   Test:
-      if ( y1 < *min ) *min = y1;
-      if ( y4 > *max ) *max = y4;
-      arc -= 3;
+    /* for a conic segment to possibly reach new minimum     */
+    /* one of its off-points must be below the current value */
+    while ( q2 < *min || q3 < *min )
+    {
+      /* determine which half contains the minimum and split */
+      if ( q1 + q2 < q3 + q4 ) /* first half */
+      {
+        q4 = q4 + q3;
+        q3 = q3 + q2;
+        q2 = q2 + q1;
+        q4 = q4 + q3;
+        q3 = q3 + q2;
+        q4 = ( q4 + q3 ) / 8;
+        q3 = q3 / 4;
+        q2 = q2 / 2;
+      }
+      else                     /* second half */
+      {
+        q1 = q1 + q2;
+        q2 = q2 + q3;
+        q3 = q3 + q4;
+        q1 = q1 + q2;
+        q2 = q2 + q3;
+        q1 = ( q1 + q2 ) / 8;
+        q2 = q2 / 4;
+        q3 = q3 / 2;
+      }
 
-    Suite:
-      ;
-    } while ( arc >= stack );
+      /* check if either end reached the minimum */
+      if ( q1 == q2 && q1 <= q3 )
+      {
+        *min = q1;
+        break;
+      }
+      if ( q3 == q4 && q2 >= q4 )
+      {
+        *min = q4;
+        break;
+      }
+    }
   }
 
 #else
@@ -358,107 +395,57 @@
         return;
     }
 
-    /* There are some split points.  Find them. */
+    /* There are some split points.  Find them.                        */
+    /* We already made sure that a, b, and c below cannot be all zero. */
     {
       FT_Pos    a = y4 - 3*y3 + 3*y2 - y1;
       FT_Pos    b = y3 - 2*y2 + y1;
       FT_Pos    c = y2 - y1;
       FT_Pos    d;
       FT_Fixed  t;
+      FT_Int    shift;
 
 
       /* We need to solve `ax^2+2bx+c' here, without floating points!      */
       /* The trick is to normalize to a different representation in order  */
-      /* to use our 16.16 fixed point routines.                            */
+      /* to use our 16.16 fixed-point routines.                            */
       /*                                                                   */
       /* We compute FT_MulFix(b,b) and FT_MulFix(a,c) after normalization. */
       /* These values must fit into a single 16.16 value.                  */
       /*                                                                   */
-      /* We normalize a, b, and c to `8.16' fixed float values to ensure   */
-      /* that its product is held in a `16.16' value.                      */
+      /* We normalize a, b, and c to `8.16' fixed-point values to ensure   */
+      /* that their product is held in a `16.16' value including the sign. */
+      /* Necessarily, we need to shift `a', `b', and `c' so that the most  */
+      /* significant bit of their absolute values is at position 22.       */
+      /*                                                                   */
+      /* This also means that we are using 23 bits of precision to compute */
+      /* the zeros, independently of the range of the original polynomial  */
+      /* coefficients.                                                     */
+      /*                                                                   */
+      /* This algorithm should ensure reasonably accurate values for the   */
+      /* zeros.  Note that they are only expressed with 16 bits when       */
+      /* computing the extrema (the zeros need to be in 0..1 exclusive     */
+      /* to be considered part of the arc).                                */
 
+      shift = FT_MSB( FT_ABS( a ) | FT_ABS( b ) | FT_ABS( c ) );
+
+      if ( shift > 22 )
       {
-        FT_ULong  t1, t2;
-        int       shift = 0;
+        shift -= 22;
 
+        /* this loses some bits of precision, but we use 23 of them */
+        /* for the computation anyway                               */
+        a >>= shift;
+        b >>= shift;
+        c >>= shift;
+      }
+      else
+      {
+        shift = 22 - shift;
 
-        /* The following computation is based on the fact that for   */
-        /* any value `y', if `n' is the position of the most         */
-        /* significant bit of `abs(y)' (starting from 0 for the      */
-        /* least significant bit), then `y' is in the range          */
-        /*                                                           */
-        /*   -2^n..2^n-1                                             */
-        /*                                                           */
-        /* We want to shift `a', `b', and `c' concurrently in order  */
-        /* to ensure that they all fit in 8.16 values, which maps    */
-        /* to the integer range `-2^23..2^23-1'.                     */
-        /*                                                           */
-        /* Necessarily, we need to shift `a', `b', and `c' so that   */
-        /* the most significant bit of its absolute values is at     */
-        /* _most_ at position 23.                                    */
-        /*                                                           */
-        /* We begin by computing `t1' as the bitwise `OR' of the     */
-        /* absolute values of `a', `b', `c'.                         */
-
-        t1  = (FT_ULong)( ( a >= 0 ) ? a : -a );
-        t2  = (FT_ULong)( ( b >= 0 ) ? b : -b );
-        t1 |= t2;
-        t2  = (FT_ULong)( ( c >= 0 ) ? c : -c );
-        t1 |= t2;
-
-        /* Now we can be sure that the most significant bit of `t1'  */
-        /* is the most significant bit of either `a', `b', or `c',   */
-        /* depending on the greatest integer range of the particular */
-        /* variable.                                                 */
-        /*                                                           */
-        /* Next, we compute the `shift', by shifting `t1' as many    */
-        /* times as necessary to move its MSB to position 23.  This  */
-        /* corresponds to a value of `t1' that is in the range       */
-        /* 0x40_0000..0x7F_FFFF.                                     */
-        /*                                                           */
-        /* Finally, we shift `a', `b', and `c' by the same amount.   */
-        /* This ensures that all values are now in the range         */
-        /* -2^23..2^23, i.e., they are now expressed as 8.16         */
-        /* fixed-float numbers.  This also means that we are using   */
-        /* 24 bits of precision to compute the zeros, independently  */
-        /* of the range of the original polynomial coefficients.     */
-        /*                                                           */
-        /* This algorithm should ensure reasonably accurate values   */
-        /* for the zeros.  Note that they are only expressed with    */
-        /* 16 bits when computing the extrema (the zeros need to     */
-        /* be in 0..1 exclusive to be considered part of the arc).   */
-
-        if ( t1 == 0 )  /* all coefficients are 0! */
-          return;
-
-        if ( t1 > 0x7FFFFFUL )
-        {
-          do
-          {
-            shift++;
-            t1 >>= 1;
-
-          } while ( t1 > 0x7FFFFFUL );
-
-          /* this loses some bits of precision, but we use 24 of them */
-          /* for the computation anyway                               */
-          a >>= shift;
-          b >>= shift;
-          c >>= shift;
-        }
-        else if ( t1 < 0x400000UL )
-        {
-          do
-          {
-            shift++;
-            t1 <<= 1;
-
-          } while ( t1 < 0x400000UL );
-
-          a <<= shift;
-          b <<= shift;
-          c <<= shift;
-        }
+        a <<= shift;
+        b <<= shift;
+        c <<= shift;
       }
 
       /* handle a == 0 */
@@ -581,10 +568,10 @@
 
 
     if ( !abbox )
-      return FT_Err_Invalid_Argument;
+      return FT_THROW( Invalid_Argument );
 
     if ( !outline )
-      return FT_Err_Invalid_Outline;
+      return FT_THROW( Invalid_Outline );
 
     /* if outline is empty, return (0,0,0,0) */
     if ( outline->n_points == 0 || outline->n_contours <= 0 )
diff --git a/src/base/ftbitmap.c b/src/base/ftbitmap.c
index 84fa322..975818e 100644
--- a/src/base/ftbitmap.c
+++ b/src/base/ftbitmap.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType utility functions for bitmaps (body).                       */
 /*                                                                         */
-/*  Copyright 2004-2009, 2011 by                                           */
+/*  Copyright 2004-2009, 2011, 2013 by                                     */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -17,6 +17,8 @@
 
 
 #include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+
 #include FT_BITMAP_H
 #include FT_IMAGE_H
 #include FT_INTERNAL_OBJECTS_H
@@ -135,7 +137,7 @@
       new_pitch = ( width + xpixels );
       break;
     default:
-      return FT_Err_Invalid_Glyph_Format;
+      return FT_THROW( Invalid_Glyph_Format );
     }
 
     /* if no need to allocate memory */
@@ -223,14 +225,14 @@
 
 
     if ( !library )
-      return FT_Err_Invalid_Library_Handle;
+      return FT_THROW( Invalid_Library_Handle );
 
     if ( !bitmap || !bitmap->buffer )
-      return FT_Err_Invalid_Argument;
+      return FT_THROW( Invalid_Argument );
 
     if ( ( ( FT_PIX_ROUND( xStrength ) >> 6 ) > FT_INT_MAX ) ||
          ( ( FT_PIX_ROUND( yStrength ) >> 6 ) > FT_INT_MAX ) )
-      return FT_Err_Invalid_Argument;
+      return FT_THROW( Invalid_Argument );
 
     xstr = (FT_Int)FT_PIX_ROUND( xStrength ) >> 6;
     ystr = (FT_Int)FT_PIX_ROUND( yStrength ) >> 6;
@@ -238,7 +240,7 @@
     if ( xstr == 0 && ystr == 0 )
       return FT_Err_Ok;
     else if ( xstr < 0 || ystr < 0 )
-      return FT_Err_Invalid_Argument;
+      return FT_THROW( Invalid_Argument );
 
     switch ( bitmap->pixel_mode )
     {
@@ -277,6 +279,10 @@
     case FT_PIXEL_MODE_LCD_V:
       ystr *= 3;
       break;
+
+    case FT_PIXEL_MODE_BGRA:
+      /* We don't embolden color glyphs. */
+      return FT_Err_Ok;
     }
 
     error = ft_bitmap_assure_buffer( library->memory, bitmap, xstr, ystr );
@@ -369,6 +375,59 @@
   }
 
 
+  FT_Byte
+  ft_gray_for_premultiplied_srgb_bgra( const FT_Byte*  bgra )
+  {
+    FT_Long  a = bgra[3];
+    FT_Long  b = bgra[0];
+    FT_Long  g = bgra[1];
+    FT_Long  r = bgra[2];
+    FT_Long  l;
+
+
+    /*
+     * Luminosity for sRGB is defined using ~0.2126,0.7152,0.0722
+     * coefficients for RGB channels *on the linear colors*.
+     * A gamma of 2.2 is fair to assume.  And then, we need to
+     * undo the premultiplication too.
+     *
+     * http://accessibility.kde.org/hsl-adjusted.php
+     *
+     * We do the computation with integers only.
+     */
+
+    /* Undo premultification, get the number in a 16.16 form. */
+    b = FT_MulDiv( b, 65536, a );
+    g = FT_MulDiv( g, 65536, a );
+    r = FT_MulDiv( r, 65536, a );
+    a = a * 256;
+
+    /* Apply gamma of 2.0 instead of 2.2. */
+    b = FT_MulFix( b, b );
+    g = FT_MulFix( g, g );
+    r = FT_MulFix( r, r );
+
+    /* Apply coefficients. */
+    b = FT_MulFix( b,  4731 /* 0.0722 * 65536 */ );
+    g = FT_MulFix( g, 46871 /* 0.7152 * 65536 */ );
+    r = FT_MulFix( r, 13933 /* 0.2126 * 65536 */ );
+
+    l = r + g + b;
+
+    /*
+     * Final transparency can be determined this way:
+     *
+     * - If alpha is zero, we want 0.
+     * - If alpha is zero and luminosity is zero, we want 255.
+     * - If alpha is zero and luminosity is one, we want 0.
+     *
+     * So the formula is a * (1 - l).
+     */
+
+    return (FT_Byte)( FT_MulFix( 65535 - l, a ) >> 8 );
+  }
+
+
   /* documentation is in ftbitmap.h */
 
   FT_EXPORT_DEF( FT_Error )
@@ -382,7 +441,7 @@
 
 
     if ( !library )
-      return FT_Err_Invalid_Library_Handle;
+      return FT_THROW( Invalid_Library_Handle );
 
     memory = library->memory;
 
@@ -394,6 +453,7 @@
     case FT_PIXEL_MODE_GRAY4:
     case FT_PIXEL_MODE_LCD:
     case FT_PIXEL_MODE_LCD_V:
+    case FT_PIXEL_MODE_BGRA:
       {
         FT_Int   pad;
         FT_Long  old_size;
@@ -419,7 +479,7 @@
 
         if ( target->pitch > 0                                     &&
              (FT_ULong)target->rows > FT_ULONG_MAX / target->pitch )
-          return FT_Err_Invalid_Argument;
+          return FT_THROW( Invalid_Argument );
 
         if ( target->rows * target->pitch > old_size             &&
              FT_QREALLOC( target->buffer,
@@ -429,7 +489,7 @@
       break;
 
     default:
-      error = FT_Err_Invalid_Argument;
+      error = FT_THROW( Invalid_Argument );
     }
 
     switch ( source->pixel_mode )
@@ -606,6 +666,37 @@
       }
       break;
 
+    case FT_PIXEL_MODE_BGRA:
+      {
+        FT_Byte*  s       = source->buffer;
+        FT_Byte*  t       = target->buffer;
+        FT_Int    s_pitch = source->pitch;
+        FT_Int    t_pitch = target->pitch;
+        FT_Int    i;
+
+
+        target->num_grays = 256;
+
+        for ( i = source->rows; i > 0; i-- )
+        {
+          FT_Byte*  ss = s;
+          FT_Byte*  tt = t;
+          FT_Int    j;
+
+
+          for ( j = source->width; j > 0; j-- )
+          {
+            tt[0] = ft_gray_for_premultiplied_srgb_bgra( ss );
+
+            ss += 4;
+            tt += 1;
+          }
+
+          s += s_pitch;
+          t += t_pitch;
+        }
+      }
+      break;
 
     default:
       ;
@@ -650,10 +741,10 @@
 
 
     if ( !library )
-      return FT_Err_Invalid_Library_Handle;
+      return FT_THROW( Invalid_Library_Handle );
 
     if ( !bitmap )
-      return FT_Err_Invalid_Argument;
+      return FT_THROW( Invalid_Argument );
 
     memory = library->memory;
 
diff --git a/src/base/ftcalc.c b/src/base/ftcalc.c
index 2aeea04..0ec0d78 100644
--- a/src/base/ftcalc.c
+++ b/src/base/ftcalc.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Arithmetic computations (body).                                      */
 /*                                                                         */
-/*  Copyright 1996-2006, 2008, 2012 by                                     */
+/*  Copyright 1996-2006, 2008, 2012-2013 by                                */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -34,6 +34,7 @@
 
 #include <ft2build.h>
 #include FT_GLYPH_H
+#include FT_TRIGONOMETRY_H
 #include FT_INTERNAL_CALC_H
 #include FT_INTERNAL_DEBUG_H
 #include FT_INTERNAL_OBJECTS_H
@@ -42,13 +43,9 @@
 #undef FT_MulFix
 #endif
 
-/* we need to define a 64-bits data type here */
+/* we need to emulate a 64-bit data type if a real one isn't available */
 
-#ifdef FT_LONG64
-
-  typedef FT_INT64  FT_Int64;
-
-#else
+#ifndef FT_LONG64
 
   typedef struct  FT_Int64_
   {
@@ -57,7 +54,7 @@
 
   } FT_Int64;
 
-#endif /* FT_LONG64 */
+#endif /* !FT_LONG64 */
 
 
   /*************************************************************************/
@@ -103,39 +100,57 @@
   }
 
 
-#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
+  FT_BASE_DEF ( FT_Int )
+  FT_MSB( FT_UInt32 z )
+  {
+    FT_Int shift = 0;
+
+    /* determine msb bit index in `shift' */
+    if ( z >= ( 1L << 16 ) )
+    {
+      z     >>= 16;
+      shift  += 16;
+    }
+    if ( z >= ( 1L << 8 ) )
+    {
+      z     >>= 8;
+      shift  += 8;
+    }
+    if ( z >= ( 1L << 4 ) )
+    {
+      z     >>= 4;
+      shift  += 4;
+    }
+    if ( z >= ( 1L << 2 ) )
+    {
+      z     >>= 2;
+      shift  += 2;
+    }
+    if ( z >= ( 1L << 1 ) )
+    {
+      z     >>= 1;
+      shift  += 1;
+    }
+
+    return shift;
+  }
+
 
   /* documentation is in ftcalc.h */
 
-  FT_EXPORT_DEF( FT_Int32 )
-  FT_Sqrt32( FT_Int32  x )
+  FT_BASE_DEF( FT_Fixed )
+  FT_Hypot( FT_Fixed  x,
+            FT_Fixed  y )
   {
-    FT_UInt32  val, root, newroot, mask;
+    FT_Vector  v;
 
 
-    root = 0;
-    mask = (FT_UInt32)0x40000000UL;
-    val  = (FT_UInt32)x;
+    v.x = x;
+    v.y = y;
 
-    do
-    {
-      newroot = root + mask;
-      if ( newroot <= val )
-      {
-        val -= newroot;
-        root = newroot + mask;
-      }
-
-      root >>= 1;
-      mask >>= 2;
-
-    } while ( mask != 0 );
-
-    return root;
+    return FT_Vector_Length( &v );
   }
 
-#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
-
 
 #ifdef FT_LONG64
 
@@ -163,8 +178,6 @@
   }
 
 
-#ifdef TT_USE_BYTECODE_INTERPRETER
-
   /* documentation is in ftcalc.h */
 
   FT_BASE_DEF( FT_Long )
@@ -187,8 +200,6 @@
     return ( s > 0 ) ? d : -d;
   }
 
-#endif /* TT_USE_BYTECODE_INTERPRETER */
-
 
   /* documentation is in freetype.h */
 
@@ -235,16 +246,25 @@
     FT_Int32   s;
     FT_UInt32  q;
 
+
     s = 1;
-    if ( a < 0 ) { a = -a; s = -1; }
-    if ( b < 0 ) { b = -b; s = -s; }
+    if ( a < 0 )
+    {
+      a = -a;
+      s = -1;
+    }
+    if ( b < 0 )
+    {
+      b = -b;
+      s = -s;
+    }
 
     if ( b == 0 )
       /* check for division by 0 */
       q = 0x7FFFFFFFL;
     else
       /* compute result directly */
-      q = (FT_UInt32)( ( ( (FT_Int64)a << 16 ) + ( b >> 1 ) ) / b );
+      q = (FT_UInt32)( ( ( (FT_UInt64)a << 16 ) + ( b >> 1 ) ) / b );
 
     return ( s < 0 ? -(FT_Long)q : (FT_Long)q );
   }
@@ -392,8 +412,6 @@
   }
 
 
-#ifdef TT_USE_BYTECODE_INTERPRETER
-
   FT_BASE_DEF( FT_Long )
   FT_MulDiv_No_Round( FT_Long  a,
                       FT_Long  b,
@@ -426,8 +444,6 @@
     return ( s < 0 ? -a : a );
   }
 
-#endif /* TT_USE_BYTECODE_INTERPRETER */
-
 
   /* documentation is in freetype.h */
 
@@ -552,7 +568,7 @@
     else if ( ( a >> 16 ) == 0 )
     {
       /* compute result directly */
-      q = (FT_UInt32)( ( a << 16 ) + ( b >> 1 ) ) / (FT_UInt32)b;
+      q = (FT_UInt32)( ( (FT_ULong)a << 16 ) + ( b >> 1 ) ) / (FT_UInt32)b;
     }
     else
     {
@@ -560,8 +576,8 @@
       FT_Int64  temp, temp2;
 
 
-      temp.hi  = (FT_Int32) ( a >> 16 );
-      temp.lo  = (FT_UInt32)( a << 16 );
+      temp.hi  = (FT_Int32)( a >> 16 );
+      temp.lo  = (FT_UInt32)a << 16;
       temp2.hi = 0;
       temp2.lo = (FT_UInt32)( b >> 1 );
       FT_Add64( &temp, &temp2, &temp );
@@ -727,14 +743,14 @@
 
 
     if ( !matrix )
-      return FT_Err_Invalid_Argument;
+      return FT_THROW( Invalid_Argument );
 
     /* compute discriminant */
     delta = FT_MulFix( matrix->xx, matrix->yy ) -
             FT_MulFix( matrix->xy, matrix->yx );
 
     if ( !delta )
-      return FT_Err_Invalid_Argument;  /* matrix can't be inverted */
+      return FT_THROW( Invalid_Argument );  /* matrix can't be inverted */
 
     matrix->xy = - FT_DivFix( matrix->xy, delta );
     matrix->yx = - FT_DivFix( matrix->yx, delta );
diff --git a/src/base/ftdbgmem.c b/src/base/ftdbgmem.c
index 12fed04..6fb86fe 100644
--- a/src/base/ftdbgmem.c
+++ b/src/base/ftdbgmem.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Memory debugger (body).                                              */
 /*                                                                         */
-/*  Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2009 by                  */
+/*  Copyright 2001-2006, 2009, 2013 by                                     */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -344,85 +344,80 @@
   ft_mem_table_destroy( FT_MemTable  table )
   {
     FT_ULong  i;
+    FT_Long   leak_count = 0;
+    FT_ULong  leaks      = 0;
 
 
     FT_DumpMemory( table->memory );
 
-    if ( table )
+    /* remove all blocks from the table, revealing leaked ones */
+    for ( i = 0; i < table->size; i++ )
     {
-      FT_Long   leak_count = 0;
-      FT_ULong  leaks      = 0;
+      FT_MemNode  *pnode = table->buckets + i, next, node = *pnode;
 
 
-      /* remove all blocks from the table, revealing leaked ones */
-      for ( i = 0; i < table->size; i++ )
+      while ( node )
       {
-        FT_MemNode  *pnode = table->buckets + i, next, node = *pnode;
+        next       = node->link;
+        node->link = 0;
 
-
-        while ( node )
+        if ( node->size > 0 )
         {
-          next       = node->link;
-          node->link = 0;
+          printf(
+            "leaked memory block at address %p, size %8ld in (%s:%ld)\n",
+            node->address, node->size,
+            FT_FILENAME( node->source->file_name ),
+            node->source->line_no );
 
-          if ( node->size > 0 )
-          {
-            printf(
-              "leaked memory block at address %p, size %8ld in (%s:%ld)\n",
-              node->address, node->size,
-              FT_FILENAME( node->source->file_name ),
-              node->source->line_no );
+          leak_count++;
+          leaks += node->size;
 
-            leak_count++;
-            leaks += node->size;
-
-            ft_mem_table_free( table, node->address );
-          }
-
-          node->address = NULL;
-          node->size    = 0;
-
-          ft_mem_table_free( table, node );
-          node = next;
-        }
-        table->buckets[i] = 0;
-      }
-
-      ft_mem_table_free( table, table->buckets );
-      table->buckets = NULL;
-
-      table->size  = 0;
-      table->nodes = 0;
-
-      /* remove all sources */
-      for ( i = 0; i < FT_MEM_SOURCE_BUCKETS; i++ )
-      {
-        FT_MemSource  source, next;
-
-
-        for ( source = table->sources[i]; source != NULL; source = next )
-        {
-          next = source->link;
-          ft_mem_table_free( table, source );
+          ft_mem_table_free( table, node->address );
         }
 
-        table->sources[i] = NULL;
+        node->address = NULL;
+        node->size    = 0;
+
+        ft_mem_table_free( table, node );
+        node = next;
       }
-
-      printf(
-        "FreeType: total memory allocations = %ld\n", table->alloc_total );
-      printf(
-        "FreeType: maximum memory footprint = %ld\n", table->alloc_max );
-
-      ft_mem_table_free( table, table );
-
-      if ( leak_count > 0 )
-        ft_mem_debug_panic(
-          "FreeType: %ld bytes of memory leaked in %ld blocks\n",
-          leaks, leak_count );
-
-      printf( "FreeType: no memory leaks detected\n" );
+      table->buckets[i] = 0;
     }
+
+    ft_mem_table_free( table, table->buckets );
+    table->buckets = NULL;
+
+    table->size  = 0;
+    table->nodes = 0;
+
+    /* remove all sources */
+    for ( i = 0; i < FT_MEM_SOURCE_BUCKETS; i++ )
+    {
+      FT_MemSource  source, next;
+
+
+      for ( source = table->sources[i]; source != NULL; source = next )
+      {
+        next = source->link;
+        ft_mem_table_free( table, source );
+      }
+
+      table->sources[i] = NULL;
+    }
+
+    printf( "FreeType: total memory allocations = %ld\n",
+            table->alloc_total );
+    printf( "FreeType: maximum memory footprint = %ld\n",
+            table->alloc_max );
+
+    ft_mem_table_free( table, table );
+
+    if ( leak_count > 0 )
+      ft_mem_debug_panic(
+        "FreeType: %ld bytes of memory leaked in %ld blocks\n",
+        leaks, leak_count );
+
+    printf( "FreeType: no memory leaks detected\n" );
   }
 
 
diff --git a/src/base/ftdebug.c b/src/base/ftdebug.c
index 2adbeab..b9156d1 100644
--- a/src/base/ftdebug.c
+++ b/src/base/ftdebug.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Debugging and logging component (body).                              */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2004, 2008 by                               */
+/*  Copyright 1996-2001, 2002, 2004, 2008, 2013 by                         */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -51,7 +51,8 @@
   /* documentation is in ftdebug.h */
 
   FT_BASE_DEF( void )
-  FT_Message( const char*  fmt, ... )
+  FT_Message( const char*  fmt,
+              ... )
   {
     va_list  ap;
 
@@ -65,7 +66,8 @@
   /* documentation is in ftdebug.h */
 
   FT_BASE_DEF( void )
-  FT_Panic( const char*  fmt, ... )
+  FT_Panic( const char*  fmt,
+            ... )
   {
     va_list  ap;
 
@@ -77,6 +79,21 @@
     exit( EXIT_FAILURE );
   }
 
+
+  /* documentation is in ftdebug.h */
+
+  FT_BASE_DEF( int )
+  FT_Throw( FT_Error     error,
+            int          line,
+            const char*  file )
+  {
+    FT_UNUSED( error );
+    FT_UNUSED( line );
+    FT_UNUSED( file );
+
+    return 0;
+  }
+
 #endif /* FT_DEBUG_LEVEL_ERROR */
 
 
@@ -164,6 +181,9 @@
         while ( *p && *p != ':' )
           p++;
 
+        if ( !*p )
+          break;
+
         if ( *p == ':' && p > q )
         {
           FT_Int  n, i, len = (FT_Int)( p - q );
@@ -192,7 +212,7 @@
           p++;
           if ( *p )
           {
-            level = *p++ - '0';
+            level = *p - '0';
             if ( level < 0 || level > 7 )
               level = -1;
           }
diff --git a/src/base/ftgloadr.c b/src/base/ftgloadr.c
index 8483450..663db26 100644
--- a/src/base/ftgloadr.c
+++ b/src/base/ftgloadr.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType glyph loader (body).                                    */
 /*                                                                         */
-/*  Copyright 2002, 2003, 2004, 2005, 2006, 2010 by                        */
+/*  Copyright 2002-2006, 2010, 2013 by                                     */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg                       */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -17,6 +17,7 @@
 
 
 #include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
 #include FT_INTERNAL_GLYPH_LOADER_H
 #include FT_INTERNAL_MEMORY_H
 #include FT_INTERNAL_OBJECTS_H
@@ -219,7 +220,7 @@
       new_max = FT_PAD_CEIL( new_max, 8 );
 
       if ( new_max > FT_OUTLINE_POINTS_MAX )
-        return FT_Err_Array_Too_Large;
+        return FT_THROW( Array_Too_Large );
 
       if ( FT_RENEW_ARRAY( base->points, old_max, new_max ) ||
            FT_RENEW_ARRAY( base->tags,   old_max, new_max ) )
@@ -251,7 +252,7 @@
       new_max = FT_PAD_CEIL( new_max, 4 );
 
       if ( new_max > FT_OUTLINE_CONTOURS_MAX )
-        return FT_Err_Array_Too_Large;
+        return FT_THROW( Array_Too_Large );
 
       if ( FT_RENEW_ARRAY( base->contours, old_max, new_max ) )
         goto Exit;
@@ -318,7 +319,7 @@
   }
 
 
-  /* add current glyph to the base image - and prepare for another */
+  /* add current glyph to the base image -- and prepare for another */
   FT_BASE_DEF( void )
   FT_GlyphLoader_Add( FT_GlyphLoader  loader )
   {
diff --git a/src/base/ftglyph.c b/src/base/ftglyph.c
index 591b57a..5dd28a8 100644
--- a/src/base/ftglyph.c
+++ b/src/base/ftglyph.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType convenience functions to handle glyphs (body).              */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2007, 2008, 2010 by       */
+/*  Copyright 1996-2005, 2007, 2008, 2010, 2012, 2013 by                   */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -29,6 +29,8 @@
 
 
 #include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+
 #include FT_GLYPH_H
 #include FT_OUTLINE_H
 #include FT_BITMAP_H
@@ -65,7 +67,7 @@
 
     if ( slot->format != FT_GLYPH_FORMAT_BITMAP )
     {
-      error = FT_Err_Invalid_Glyph_Format;
+      error = FT_THROW( Invalid_Glyph_Format );
       goto Exit;
     }
 
@@ -166,7 +168,7 @@
     /* check format in glyph slot */
     if ( slot->format != FT_GLYPH_FORMAT_OUTLINE )
     {
-      error = FT_Err_Invalid_Glyph_Format;
+      error = FT_THROW( Invalid_Glyph_Format );
       goto Exit;
     }
 
@@ -314,7 +316,7 @@
     /* check arguments */
     if ( !target )
     {
-      error = FT_Err_Invalid_Argument;
+      error = FT_THROW( Invalid_Argument );
       goto Exit;
     }
 
@@ -322,7 +324,7 @@
 
     if ( !source || !source->clazz )
     {
-      error = FT_Err_Invalid_Argument;
+      error = FT_THROW( Invalid_Argument );
       goto Exit;
     }
 
@@ -361,12 +363,12 @@
 
 
     if ( !slot )
-      return FT_Err_Invalid_Slot_Handle;
+      return FT_THROW( Invalid_Slot_Handle );
 
     library = slot->library;
 
     if ( !aglyph )
-      return FT_Err_Invalid_Argument;
+      return FT_THROW( Invalid_Argument );
 
     /* if it is a bitmap, that's easy :-) */
     if ( slot->format == FT_GLYPH_FORMAT_BITMAP )
@@ -388,7 +390,7 @@
 
     if ( !clazz )
     {
-      error = FT_Err_Invalid_Glyph_Format;
+      error = FT_THROW( Invalid_Glyph_Format );
       goto Exit;
     }
 
@@ -427,7 +429,7 @@
 
 
     if ( !glyph || !glyph->clazz )
-      error = FT_Err_Invalid_Argument;
+      error = FT_THROW( Invalid_Argument );
     else
     {
       clazz = glyph->clazz;
@@ -441,7 +443,7 @@
           FT_Vector_Transform( &glyph->advance, matrix );
       }
       else
-        error = FT_Err_Invalid_Glyph_Format;
+        error = FT_THROW( Invalid_Glyph_Format );
     }
     return error;
   }
@@ -510,7 +512,7 @@
     FT_GlyphSlotRec           dummy;
     FT_GlyphSlot_InternalRec  dummy_internal;
     FT_Error                  error = FT_Err_Ok;
-    FT_Glyph                  glyph;
+    FT_Glyph                  b, glyph;
     FT_BitmapGlyph            bitmap = NULL;
     const FT_Glyph_Class*     clazz;
 
@@ -547,10 +549,10 @@
     dummy.format   = clazz->glyph_format;
 
     /* create result bitmap glyph */
-    error = ft_new_glyph( library, FT_BITMAP_GLYPH_CLASS_GET,
-                          (FT_Glyph*)(void*)&bitmap );
+    error = ft_new_glyph( library, FT_BITMAP_GLYPH_CLASS_GET, &b );
     if ( error )
       goto Exit;
+    bitmap = (FT_BitmapGlyph)b;
 
 #if 1
     /* if `origin' is set, translate the glyph image */
@@ -600,7 +602,7 @@
     return error;
 
   Bad:
-    error = FT_Err_Invalid_Argument;
+    error = FT_THROW( Invalid_Argument );
     goto Exit;
   }
 
diff --git a/src/base/ftinit.c b/src/base/ftinit.c
index 91f8e2a..85f321f 100644
--- a/src/base/ftinit.c
+++ b/src/base/ftinit.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType initialization layer (body).                                */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2005, 2007, 2009, 2012 by                   */
+/*  Copyright 1996-2002, 2005, 2007, 2009, 2012, 2013 by                   */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -156,7 +156,7 @@
   {
     FT_Error           error;
     FT_Memory          memory;
-    FT_Module_Class*  *classes;
+    FT_Module_Class*  *classes = NULL;
     FT_Module_Class*   clazz;
     FT_UInt            i;
     BasePIC*           pic_container = (BasePIC*)library->pic_container.base;
@@ -166,7 +166,7 @@
 
     pic_container->default_module_classes = 0;
 
-    if ( FT_ALLOC( classes, sizeof ( FT_Module_Class* ) * 
+    if ( FT_ALLOC( classes, sizeof ( FT_Module_Class* ) *
                               ( FT_NUM_MODULE_CLASSES + 1 ) ) )
       return error;
 
@@ -242,7 +242,7 @@
     if ( !memory )
     {
       FT_ERROR(( "FT_Init_FreeType: cannot find memory manager\n" ));
-      return FT_Err_Unimplemented_Feature;
+      return FT_THROW( Unimplemented_Feature );
     }
 
     /* build a library out of it, then fill it with the set of */
diff --git a/src/base/ftlcdfil.c b/src/base/ftlcdfil.c
index 0da4ba1..852fb32 100644
--- a/src/base/ftlcdfil.c
+++ b/src/base/ftlcdfil.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType API for color filtering of subpixel bitmap glyphs (body).   */
 /*                                                                         */
-/*  Copyright 2006, 2008, 2009, 2010 by                                    */
+/*  Copyright 2006, 2008-2010, 2013 by                                     */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -17,6 +17,8 @@
 
 
 #include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+
 #include FT_LCD_FILTER_H
 #include FT_IMAGE_H
 #include FT_INTERNAL_OBJECTS_H
@@ -271,7 +273,7 @@
                                   unsigned char  *weights )
   {
     if ( !library || !weights )
-      return FT_Err_Invalid_Argument;
+      return FT_THROW( Invalid_Argument );
 
     ft_memcpy( library->lcd_weights, weights, 5 );
 
@@ -292,7 +294,7 @@
 
 
     if ( !library )
-      return FT_Err_Invalid_Argument;
+      return FT_THROW( Invalid_Argument );
 
     switch ( filter )
     {
@@ -339,7 +341,7 @@
 #endif
 
     default:
-      return FT_Err_Invalid_Argument;
+      return FT_THROW( Invalid_Argument );
     }
 
     library->lcd_filter = filter;
@@ -356,7 +358,7 @@
     FT_UNUSED( library );
     FT_UNUSED( weights );
 
-    return FT_Err_Unimplemented_Feature;
+    return FT_THROW( Unimplemented_Feature );
   }
 
 
@@ -367,7 +369,7 @@
     FT_UNUSED( library );
     FT_UNUSED( filter );
 
-    return FT_Err_Unimplemented_Feature;
+    return FT_THROW( Unimplemented_Feature );
   }
 
 #endif /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
diff --git a/src/base/ftmm.c b/src/base/ftmm.c
index 0307729..18ff879 100644
--- a/src/base/ftmm.c
+++ b/src/base/ftmm.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Multiple Master font support (body).                                 */
 /*                                                                         */
-/*  Copyright 1996-2001, 2003, 2004, 2009 by                               */
+/*  Copyright 1996-2001, 2003, 2004, 2009, 2013 by                         */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -17,6 +17,8 @@
 
 
 #include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+
 #include FT_MULTIPLE_MASTERS_H
 #include FT_INTERNAL_OBJECTS_H
 #include FT_SERVICE_MULTIPLE_MASTERS_H
@@ -42,9 +44,9 @@
     *aservice = NULL;
 
     if ( !face )
-      return FT_Err_Invalid_Face_Handle;
+      return FT_THROW( Invalid_Face_Handle );
 
-    error = FT_Err_Invalid_Argument;
+    error = FT_ERR( Invalid_Argument );
 
     if ( FT_HAS_MULTIPLE_MASTERS( face ) )
     {
@@ -73,7 +75,7 @@
     error = ft_face_get_mm_service( face, &service );
     if ( !error )
     {
-      error = FT_Err_Invalid_Argument;
+      error = FT_ERR( Invalid_Argument );
       if ( service->get_mm )
         error = service->get_mm( face, amaster );
     }
@@ -95,7 +97,7 @@
     error = ft_face_get_mm_service( face, &service );
     if ( !error )
     {
-      error = FT_Err_Invalid_Argument;
+      error = FT_ERR( Invalid_Argument );
       if ( service->get_mm_var )
         error = service->get_mm_var( face, amaster );
     }
@@ -118,7 +120,7 @@
     error = ft_face_get_mm_service( face, &service );
     if ( !error )
     {
-      error = FT_Err_Invalid_Argument;
+      error = FT_ERR( Invalid_Argument );
       if ( service->set_mm_design )
         error = service->set_mm_design( face, num_coords, coords );
     }
@@ -141,7 +143,7 @@
     error = ft_face_get_mm_service( face, &service );
     if ( !error )
     {
-      error = FT_Err_Invalid_Argument;
+      error = FT_ERR( Invalid_Argument );
       if ( service->set_var_design )
         error = service->set_var_design( face, num_coords, coords );
     }
@@ -164,7 +166,7 @@
     error = ft_face_get_mm_service( face, &service );
     if ( !error )
     {
-      error = FT_Err_Invalid_Argument;
+      error = FT_ERR( Invalid_Argument );
       if ( service->set_mm_blend )
          error = service->set_mm_blend( face, num_coords, coords );
     }
@@ -190,7 +192,7 @@
     error = ft_face_get_mm_service( face, &service );
     if ( !error )
     {
-      error = FT_Err_Invalid_Argument;
+      error = FT_ERR( Invalid_Argument );
       if ( service->set_mm_blend )
          error = service->set_mm_blend( face, num_coords, coords );
     }
diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c
index 36ee797..ac2a39c 100644
--- a/src/base/ftobjs.c
+++ b/src/base/ftobjs.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType private base classes (body).                            */
 /*                                                                         */
-/*  Copyright 1996-2012 by                                                 */
+/*  Copyright 1996-2013 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -29,6 +29,7 @@
 #include FT_TRUETYPE_TAGS_H
 #include FT_TRUETYPE_IDS_H
 
+#include FT_SERVICE_PROPERTIES_H
 #include FT_SERVICE_SFNT_H
 #include FT_SERVICE_POSTSCRIPT_NAME_H
 #include FT_SERVICE_GLYPH_DICT_H
@@ -40,6 +41,32 @@
 #include "ftbase.h"
 #endif
 
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+
+#include FT_BITMAP_H
+
+#if defined( _MSC_VER )      /* Visual C++ (and Intel C++)   */
+  /* We disable the warning `conversion from XXX to YYY,     */
+  /* possible loss of data' in order to compile cleanly with */
+  /* the maximum level of warnings: `md5.c' is non-FreeType  */
+  /* code, and it gets used during development builds only.  */
+#pragma warning( push )
+#pragma warning( disable : 4244 )
+#endif /* _MSC_VER */
+
+  /* it's easiest to include `md5.c' directly */
+#define free  md5_free /* suppress a shadow warning */
+#include "md5.c"
+#undef free
+
+#if defined( _MSC_VER )
+#pragma warning( pop )
+#endif
+
+#endif /* FT_DEBUG_LEVEL_TRACE */
+
+
 #define GRID_FIT_METRICS
 
 
@@ -136,10 +163,10 @@
     *astream = 0;
 
     if ( !library )
-      return FT_Err_Invalid_Library_Handle;
+      return FT_THROW( Invalid_Library_Handle );
 
     if ( !args )
-      return FT_Err_Invalid_Argument;
+      return FT_THROW( Invalid_Argument );
 
     memory = library->memory;
 
@@ -177,7 +204,7 @@
 #endif
 
     else
-      error = FT_Err_Invalid_Argument;
+      error = FT_THROW( Invalid_Argument );
 
     if ( error )
       FT_FREE( stream );
@@ -384,7 +411,7 @@
 
 
     if ( !face || !face->driver )
-      return FT_Err_Invalid_Argument;
+      return FT_THROW( Invalid_Argument );
 
     driver = face->driver;
     clazz  = driver->clazz;
@@ -574,7 +601,7 @@
 
 
     if ( !face || !face->size || !face->glyph )
-      return FT_Err_Invalid_Face_Handle;
+      return FT_THROW( Invalid_Face_Handle );
 
     /* The validity test for `glyph_index' is performed by the */
     /* font drivers.                                           */
@@ -651,7 +678,7 @@
 
     if ( autohint )
     {
-      FT_AutoHinter_Service  hinting;
+      FT_AutoHinter_Interface  hinting;
 
 
       /* try to load embedded bitmaps first if available            */
@@ -680,7 +707,7 @@
         internal->transform_flags = 0;
 
         /* load auto-hinted outline */
-        hinting = (FT_AutoHinter_Service)hinter->clazz->module_interface;
+        hinting = (FT_AutoHinter_Interface)hinter->clazz->module_interface;
 
         error   = hinting->load_glyph( (FT_AutoHinter)hinter,
                                        slot, face->size,
@@ -814,7 +841,7 @@
 
 
     if ( !face )
-      return FT_Err_Invalid_Face_Handle;
+      return FT_THROW( Invalid_Face_Handle );
 
     glyph_index = (FT_UInt)char_code;
     if ( face->charmap )
@@ -965,7 +992,7 @@
     first = face->charmaps;
 
     if ( !first )
-      return FT_Err_Invalid_CharMap_Handle;
+      return FT_THROW( Invalid_CharMap_Handle );
 
     /*
      *  The original TrueType specification(s) only specified charmap
@@ -1043,7 +1070,7 @@
       }
     }
 
-    return FT_Err_Invalid_CharMap_Handle;
+    return FT_THROW( Invalid_CharMap_Handle );
   }
 
 
@@ -1165,7 +1192,7 @@
     /* is returned.                                                      */
 
     /* no error should happen, but we want to play safe */
-    if ( error2 && error2 != FT_Err_Invalid_CharMap_Handle )
+    if ( error2 && FT_ERR_NEQ( error2, Invalid_CharMap_Handle ) )
     {
       error = error2;
       goto Fail;
@@ -1206,7 +1233,7 @@
 
     /* test for valid `library' and `aface' delayed to FT_Open_Face() */
     if ( !pathname )
-      return FT_Err_Invalid_Argument;
+      return FT_THROW( Invalid_Argument );
 
     args.flags    = FT_OPEN_PATHNAME;
     args.pathname = (char*)pathname;
@@ -1232,7 +1259,7 @@
 
     /* test for valid `library' and `face' delayed to FT_Open_Face() */
     if ( !file_base )
-      return FT_Err_Invalid_Argument;
+      return FT_THROW( Invalid_Argument );
 
     args.flags       = FT_OPEN_MEMORY;
     args.memory_base = file_base;
@@ -1304,10 +1331,10 @@
 
 
     if ( !library )
-      return FT_Err_Invalid_Library_Handle;
+      return FT_THROW( Invalid_Library_Handle );
 
     if ( !base )
-      return FT_Err_Invalid_Argument;
+      return FT_THROW( Invalid_Argument );
 
     *astream = 0;
     memory = library->memory;
@@ -1421,7 +1448,7 @@
     if ( FT_READ_ULONG( tag ) )
       return error;
     if ( tag != TTAG_typ1 )
-      return FT_Err_Unknown_File_Format;
+      return FT_THROW( Unknown_File_Format );
 
     if ( FT_READ_USHORT( numTables ) )
       return error;
@@ -1458,7 +1485,7 @@
       if ( face_index >= 0 && pstable_index == face_index )
         return FT_Err_Ok;
     }
-    return FT_Err_Table_Missing;
+    return FT_THROW( Table_Missing );
   }
 
 
@@ -1504,7 +1531,7 @@
     error = open_face_from_buffer( library,
                                    sfnt_ps,
                                    length,
-                                   face_index < 0 ? face_index : 0,
+                                   FT_MIN( face_index, 0 ),
                                    is_sfnt_cid ? "cid" : "type1",
                                    aface );
   Exit:
@@ -1512,7 +1539,7 @@
       FT_Error  error1;
 
 
-      if ( error == FT_Err_Unknown_File_Format )
+      if ( FT_ERR_EQ( error, Unknown_File_Format ) )
       {
         error1 = FT_Stream_Seek( stream, pos );
         if ( error1 )
@@ -1540,7 +1567,7 @@
                           FT_Long     face_index,
                           FT_Face    *aface )
   {
-    FT_Error   error  = FT_Err_Cannot_Open_Resource;
+    FT_Error   error  = FT_ERR( Cannot_Open_Resource );
     FT_Memory  memory = library->memory;
     FT_Byte*   pfb_data = NULL;
     int        i, type, flags;
@@ -1633,7 +1660,7 @@
         pfb_data[pfb_pos++] = 0;
       }
 
-      error = FT_Err_Cannot_Open_Resource;
+      error = FT_ERR( Cannot_Open_Resource );
       if ( pfb_pos > pfb_len || pfb_pos + rlen > pfb_len )
         goto Exit2;
 
@@ -1695,7 +1722,7 @@
     if ( face_index == -1 )
       face_index = 0;
     if ( face_index >= resource_cnt )
-      return FT_Err_Cannot_Open_Resource;
+      return FT_THROW( Cannot_Open_Resource );
 
     flag_offset = offsets[face_index];
     error = FT_Stream_Seek( stream, flag_offset );
@@ -1705,7 +1732,7 @@
     if ( FT_READ_LONG( rlen ) )
       goto Exit;
     if ( rlen == -1 )
-      return FT_Err_Cannot_Open_Resource;
+      return FT_THROW( Cannot_Open_Resource );
 
     error = open_face_PS_from_sfnt_stream( library,
                                            stream,
@@ -1812,7 +1839,7 @@
 
 
     if ( NULL == stream )
-      return FT_Err_Invalid_Stream_Operation;
+      return FT_THROW( Invalid_Stream_Operation );
 
     error = FT_Stream_Seek( stream, 0 );
     if ( error )
@@ -1829,7 +1856,7 @@
                     header[ 1] >  33 ||
                     header[63] !=  0 ||
          header[2 + header[1]] !=  0 )
-      return FT_Err_Unknown_File_Format;
+      return FT_THROW( Unknown_File_Format );
 
     dlen = ( header[0x53] << 24 ) |
            ( header[0x54] << 16 ) |
@@ -1862,7 +1889,7 @@
 #define FT_COMPONENT  trace_raccess
 
     FT_Memory  memory = library->memory;
-    FT_Error   error  = FT_Err_Unknown_File_Format;
+    FT_Error   error  = FT_ERR( Unknown_File_Format );
     int        i;
 
     char *     file_names[FT_RACCESS_N_RULES];
@@ -1901,7 +1928,7 @@
                   i, args2.pathname, offsets[i] ));
 
       error = FT_Stream_New( library, &args2, &stream2 );
-      if ( is_darwin_vfs && error == FT_Err_Cannot_Open_Stream )
+      if ( is_darwin_vfs && FT_ERR_EQ( error, Cannot_Open_Stream ) )
         vfs_rfork_has_no_font = TRUE;
 
       if ( error )
@@ -1930,7 +1957,7 @@
 
     /* Caller (load_mac_face) requires FT_Err_Unknown_File_Format. */
     if ( error )
-      error = FT_Err_Unknown_File_Format;
+      error = FT_ERR( Unknown_File_Format );
 
     return error;
 
@@ -1959,7 +1986,7 @@
 
 
     error = IsMacBinary( library, stream, face_index, aface );
-    if ( FT_ERROR_BASE( error ) == FT_Err_Unknown_File_Format )
+    if ( FT_ERR_EQ( error, Unknown_File_Format ) )
     {
 
 #undef  FT_COMPONENT
@@ -1976,9 +2003,9 @@
 
     }
 
-    if ( ( FT_ERROR_BASE( error ) == FT_Err_Unknown_File_Format      ||
-           FT_ERROR_BASE( error ) == FT_Err_Invalid_Stream_Operation ) &&
-         ( args->flags & FT_OPEN_PATHNAME )                            )
+    if ( ( FT_ERR_EQ( error, Unknown_File_Format )      ||
+           FT_ERR_EQ( error, Invalid_Stream_Operation ) ) &&
+         ( args->flags & FT_OPEN_PATHNAME )               )
       error = load_face_in_embedded_rfork( library, stream,
                                            face_index, aface, args );
     return error;
@@ -2011,7 +2038,7 @@
     /* FT_Stream_New()                     */
 
     if ( ( !aface && face_index >= 0 ) || !args )
-      return FT_Err_Invalid_Argument;
+      return FT_THROW( Invalid_Argument );
 
     external_stream = FT_BOOL( ( args->flags & FT_OPEN_STREAM ) &&
                                args->stream                     );
@@ -2048,18 +2075,19 @@
           goto Success;
       }
       else
-        error = FT_Err_Invalid_Handle;
+        error = FT_THROW( Invalid_Handle );
 
       FT_Stream_Free( stream, external_stream );
       goto Fail;
     }
     else
     {
+      error = FT_ERR( Missing_Module );
+
       /* check each font driver for an appropriate format */
       cur   = library->modules;
       limit = cur + library->num_modules;
 
-
       for ( ; cur < limit; cur++ )
       {
         /* not all modules are font drivers, so check... */
@@ -2084,7 +2112,7 @@
 
 #ifdef FT_CONFIG_OPTION_MAC_FONTS
           if ( ft_strcmp( cur[0]->clazz->module_name, "truetype" ) == 0 &&
-               FT_ERROR_BASE( error ) == FT_Err_Table_Missing           )
+               FT_ERR_EQ( error, Table_Missing )                        )
           {
             /* TrueType but essential tables are missing */
             if ( FT_Stream_Seek( stream, 0 ) )
@@ -2104,39 +2132,39 @@
           }
 #endif
 
-          if ( FT_ERROR_BASE( error ) != FT_Err_Unknown_File_Format )
+          if ( FT_ERR_NEQ( error, Unknown_File_Format ) )
             goto Fail3;
         }
       }
 
-  Fail3:
-    /* If we are on the mac, and we get an FT_Err_Invalid_Stream_Operation */
-    /* it may be because we have an empty data fork, so we need to check   */
-    /* the resource fork.                                                  */
-    if ( FT_ERROR_BASE( error ) != FT_Err_Cannot_Open_Stream       &&
-         FT_ERROR_BASE( error ) != FT_Err_Unknown_File_Format      &&
-         FT_ERROR_BASE( error ) != FT_Err_Invalid_Stream_Operation )
-      goto Fail2;
+    Fail3:
+      /* If we are on the mac, and we get an                          */
+      /* FT_Err_Invalid_Stream_Operation it may be because we have an */
+      /* empty data fork, so we need to check the resource fork.      */
+      if ( FT_ERR_NEQ( error, Cannot_Open_Stream )       &&
+           FT_ERR_NEQ( error, Unknown_File_Format )      &&
+           FT_ERR_NEQ( error, Invalid_Stream_Operation ) )
+        goto Fail2;
 
 #if !defined( FT_MACINTOSH ) && defined( FT_CONFIG_OPTION_MAC_FONTS )
-    error = load_mac_face( library, stream, face_index, aface, args );
-    if ( !error )
-    {
-      /* We don't want to go to Success here.  We've already done that. */
-      /* On the other hand, if we succeeded we still need to close this */
-      /* stream (we opened a different stream which extracted the       */
-      /* interesting information out of this stream here.  That stream  */
-      /* will still be open and the face will point to it).             */
-      FT_Stream_Free( stream, external_stream );
-      return error;
-    }
+      error = load_mac_face( library, stream, face_index, aface, args );
+      if ( !error )
+      {
+        /* We don't want to go to Success here.  We've already done that. */
+        /* On the other hand, if we succeeded we still need to close this */
+        /* stream (we opened a different stream which extracted the       */
+        /* interesting information out of this stream here.  That stream  */
+        /* will still be open and the face will point to it).             */
+        FT_Stream_Free( stream, external_stream );
+        return error;
+      }
 
-    if ( FT_ERROR_BASE( error ) != FT_Err_Unknown_File_Format )
-      goto Fail2;
+      if ( FT_ERR_NEQ( error, Unknown_File_Format ) )
+        goto Fail2;
 #endif  /* !FT_MACINTOSH && FT_CONFIG_OPTION_MAC_FONTS */
 
       /* no driver is able to handle this format */
-      error = FT_Err_Unknown_File_Format;
+      error = FT_THROW( Unknown_File_Format );
 
   Fail2:
       FT_Stream_Free( stream, external_stream );
@@ -2258,7 +2286,7 @@
     /* test for valid `face' delayed to FT_Attach_Stream() */
 
     if ( !filepathname )
-      return FT_Err_Invalid_Argument;
+      return FT_THROW( Invalid_Argument );
 
     open.stream   = NULL;
     open.flags    = FT_OPEN_PATHNAME;
@@ -2284,11 +2312,11 @@
     /* test for valid `parameters' delayed to FT_Stream_New() */
 
     if ( !face )
-      return FT_Err_Invalid_Face_Handle;
+      return FT_THROW( Invalid_Face_Handle );
 
     driver = face->driver;
     if ( !driver )
-      return FT_Err_Invalid_Driver_Handle;
+      return FT_THROW( Invalid_Driver_Handle );
 
     error = FT_Stream_New( driver->root.library, parameters, &stream );
     if ( error )
@@ -2297,7 +2325,7 @@
     /* we implement FT_Attach_Stream in each driver through the */
     /* `attach_file' interface                                  */
 
-    error = FT_Err_Unimplemented_Feature;
+    error = FT_ERR( Unimplemented_Feature );
     clazz = driver->clazz;
     if ( clazz->attach_file )
       error = clazz->attach_file( face, stream );
@@ -2334,7 +2362,7 @@
     FT_ListNode  node;
 
 
-    error = FT_Err_Invalid_Face_Handle;
+    error = FT_ERR( Invalid_Face_Handle );
     if ( face && face->driver )
     {
       face->internal->refcount--;
@@ -2380,13 +2408,13 @@
 
 
     if ( !face )
-      return FT_Err_Invalid_Face_Handle;
+      return FT_THROW( Invalid_Face_Handle );
 
     if ( !asize )
-      return FT_Err_Invalid_Size_Handle;
+      return FT_THROW( Invalid_Size_Handle );
 
     if ( !face->driver )
-      return FT_Err_Invalid_Driver_Handle;
+      return FT_THROW( Invalid_Driver_Handle );
 
     *asize = 0;
 
@@ -2438,15 +2466,15 @@
 
 
     if ( !size )
-      return FT_Err_Invalid_Size_Handle;
+      return FT_THROW( Invalid_Size_Handle );
 
     face = size->face;
     if ( !face )
-      return FT_Err_Invalid_Face_Handle;
+      return FT_THROW( Invalid_Face_Handle );
 
     driver = face->driver;
     if ( !driver )
-      return FT_Err_Invalid_Driver_Handle;
+      return FT_THROW( Invalid_Driver_Handle );
 
     memory = driver->root.memory;
 
@@ -2467,7 +2495,7 @@
       destroy_size( memory, size, driver );
     }
     else
-      error = FT_Err_Invalid_Size_Handle;
+      error = FT_THROW( Invalid_Size_Handle );
 
     return error;
   }
@@ -2486,11 +2514,11 @@
 
 
     if ( !FT_HAS_FIXED_SIZES( face ) )
-      return FT_Err_Invalid_Face_Handle;
+      return FT_THROW( Invalid_Face_Handle );
 
     /* FT_Bitmap_Size doesn't provide enough info... */
     if ( req->type != FT_SIZE_REQUEST_TYPE_NOMINAL )
-      return FT_Err_Unimplemented_Feature;
+      return FT_THROW( Unimplemented_Feature );
 
     w = FT_REQUEST_WIDTH ( req );
     h = FT_REQUEST_HEIGHT( req );
@@ -2513,6 +2541,8 @@
 
       if ( w == FT_PIX_ROUND( bsize->x_ppem ) || ignore_width )
       {
+        FT_TRACE3(( "FT_Match_Size: bitmap strike %d matches\n", i ));
+
         if ( size_index )
           *size_index = (FT_ULong)i;
 
@@ -2520,7 +2550,7 @@
       }
     }
 
-    return FT_Err_Invalid_Pixel_Size;
+    return FT_THROW( Invalid_Pixel_Size );
   }
 
 
@@ -2763,10 +2793,10 @@
 
 
     if ( !face || !FT_HAS_FIXED_SIZES( face ) )
-      return FT_Err_Invalid_Face_Handle;
+      return FT_THROW( Invalid_Face_Handle );
 
     if ( strike_index < 0 || strike_index >= face->num_fixed_sizes )
-      return FT_Err_Invalid_Argument;
+      return FT_THROW( Invalid_Argument );
 
     clazz = face->driver->clazz;
 
@@ -2816,11 +2846,11 @@
 
 
     if ( !face )
-      return FT_Err_Invalid_Face_Handle;
+      return FT_THROW( Invalid_Face_Handle );
 
     if ( !req || req->width < 0 || req->height < 0 ||
          req->type >= FT_SIZE_REQUEST_TYPE_MAX )
-      return FT_Err_Invalid_Argument;
+      return FT_THROW( Invalid_Argument );
 
     clazz = face->driver->clazz;
 
@@ -2869,9 +2899,6 @@
       if ( error )
         return error;
 
-      FT_TRACE3(( "FT_Request_Size: bitmap strike %lu matched\n",
-                  strike_index ));
-
       return FT_Select_Size( face, (FT_Int)strike_index );
     }
 
@@ -2971,10 +2998,10 @@
 
 
     if ( !face )
-      return FT_Err_Invalid_Face_Handle;
+      return FT_THROW( Invalid_Face_Handle );
 
     if ( !akerning )
-      return FT_Err_Invalid_Argument;
+      return FT_THROW( Invalid_Argument );
 
     driver = face->driver;
 
@@ -3030,14 +3057,14 @@
 
 
     if ( !face )
-      return FT_Err_Invalid_Face_Handle;
+      return FT_THROW( Invalid_Face_Handle );
 
     if ( !akerning )
-      return FT_Err_Invalid_Argument;
+      return FT_THROW( Invalid_Argument );
 
     FT_FACE_FIND_SERVICE( face, service, KERNING );
     if ( !service )
-      return FT_Err_Unimplemented_Feature;
+      return FT_THROW( Unimplemented_Feature );
 
     error = service->get_track( face,
                                 point_size,
@@ -3059,10 +3086,10 @@
 
 
     if ( !face )
-      return FT_Err_Invalid_Face_Handle;
+      return FT_THROW( Invalid_Face_Handle );
 
     if ( encoding == FT_ENCODING_NONE )
-      return FT_Err_Invalid_Argument;
+      return FT_THROW( Invalid_Argument );
 
     /* FT_ENCODING_UNICODE is special.  We try to find the `best' Unicode */
     /* charmap available, i.e., one with UCS-4 characters, if possible.   */
@@ -3073,7 +3100,7 @@
 
     cur = face->charmaps;
     if ( !cur )
-      return FT_Err_Invalid_CharMap_Handle;
+      return FT_THROW( Invalid_CharMap_Handle );
 
     limit = cur + face->num_charmaps;
 
@@ -3095,7 +3122,7 @@
       }
     }
 
-    return FT_Err_Invalid_Argument;
+    return FT_THROW( Invalid_Argument );
   }
 
 
@@ -3110,13 +3137,13 @@
 
 
     if ( !face )
-      return FT_Err_Invalid_Face_Handle;
+      return FT_THROW( Invalid_Face_Handle );
 
     cur = face->charmaps;
     if ( !cur )
-      return FT_Err_Invalid_CharMap_Handle;
+      return FT_THROW( Invalid_CharMap_Handle );
     if ( FT_Get_CMap_Format( charmap ) == 14 )
-      return FT_Err_Invalid_Argument;
+      return FT_THROW( Invalid_Argument );
 
     limit = cur + face->num_charmaps;
 
@@ -3137,7 +3164,7 @@
         return 0;
       }
     }
-    return FT_Err_Invalid_Argument;
+    return FT_THROW( Invalid_Argument );
   }
 
 
@@ -3176,7 +3203,7 @@
   {
     FT_CMap_Class  clazz  = cmap->clazz;
     FT_Face        face   = cmap->charmap.face;
-    FT_Memory      memory = FT_FACE_MEMORY(face);
+    FT_Memory      memory = FT_FACE_MEMORY( face );
 
 
     if ( clazz->done )
@@ -3245,7 +3272,7 @@
 
 
     if ( clazz == NULL || charmap == NULL || charmap->face == NULL )
-      return FT_Err_Invalid_Argument;
+      return FT_THROW( Invalid_Argument );
 
     face   = charmap->face;
     memory = FT_FACE_MEMORY( face );
@@ -3578,7 +3605,7 @@
                      FT_Pointer  buffer,
                      FT_UInt     buffer_max )
   {
-    FT_Error  error = FT_Err_Invalid_Argument;
+    FT_Error  error = FT_ERR( Invalid_Argument );
 
 
     /* clean up buffer */
@@ -3667,11 +3694,11 @@
 
 
     if ( !face || !FT_IS_SFNT( face ) )
-      return FT_Err_Invalid_Face_Handle;
+      return FT_THROW( Invalid_Face_Handle );
 
     FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE );
     if ( service == NULL )
-      return FT_Err_Unimplemented_Feature;
+      return FT_THROW( Unimplemented_Feature );
 
     return service->load_table( face, tag, offset, buffer, length );
   }
@@ -3690,11 +3717,11 @@
 
 
     if ( !face || !FT_IS_SFNT( face ) )
-      return FT_Err_Invalid_Face_Handle;
+      return FT_THROW( Invalid_Face_Handle );
 
     FT_FACE_FIND_SERVICE( face, service, SFNT_TABLE );
     if ( service == NULL )
-      return FT_Err_Unimplemented_Feature;
+      return FT_THROW( Unimplemented_Feature );
 
     return service->table_info( face, table_index, tag, &offset, length );
   }
@@ -3757,11 +3784,11 @@
 
 
     if ( size == NULL )
-      return FT_Err_Invalid_Argument;
+      return FT_THROW( Invalid_Argument );
 
     face = size->face;
     if ( face == NULL || face->driver == NULL )
-      return FT_Err_Invalid_Argument;
+      return FT_THROW( Invalid_Argument );
 
     /* we don't need anything more complex than that; all size objects */
     /* are already listed by the face                                  */
@@ -3953,15 +3980,15 @@
 
 
     if ( !library )
-      return FT_Err_Invalid_Library_Handle;
+      return FT_THROW( Invalid_Library_Handle );
 
     if ( !renderer )
-      return FT_Err_Invalid_Argument;
+      return FT_THROW( Invalid_Argument );
 
     node = FT_List_Find( &library->renderers, renderer );
     if ( !node )
     {
-      error = FT_Err_Invalid_Argument;
+      error = FT_THROW( Invalid_Argument );
       goto Exit;
     }
 
@@ -4019,12 +4046,12 @@
         else
           renderer = FT_Lookup_Renderer( library, slot->format, &node );
 
-        error = FT_Err_Unimplemented_Feature;
+        error = FT_ERR( Unimplemented_Feature );
         while ( renderer )
         {
           error = renderer->render( renderer, slot, render_mode, NULL );
-          if ( !error                                               ||
-               FT_ERROR_BASE( error ) != FT_Err_Cannot_Render_Glyph )
+          if ( !error                                   ||
+               FT_ERR_NEQ( error, Cannot_Render_Glyph ) )
             break;
 
           /* FT_Err_Cannot_Render_Glyph is returned if the render mode   */
@@ -4044,6 +4071,47 @@
       }
     }
 
+#ifdef FT_DEBUG_LEVEL_TRACE
+
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_bitmap
+
+    /* we convert to a single bitmap format for computing the checksum */
+    {
+      FT_Bitmap  bitmap;
+      FT_Error   err;
+
+
+      FT_Bitmap_New( &bitmap );
+
+      err = FT_Bitmap_Convert( library, &slot->bitmap, &bitmap, 1 );
+      if ( !err )
+      {
+        MD5_CTX        ctx;
+        unsigned char  md5[16];
+        int            i;
+
+
+        MD5_Init( &ctx);
+        MD5_Update( &ctx, bitmap.buffer, bitmap.rows * bitmap.pitch );
+        MD5_Final( md5, &ctx );
+
+        FT_TRACE3(( "MD5 checksum for %dx%d bitmap:\n"
+                    "  ",
+                    bitmap.rows, bitmap.pitch ));
+        for ( i = 0; i < 16; i++ )
+          FT_TRACE3(( "%02X", md5[i] ));
+        FT_TRACE3(( "\n" ));
+      }
+
+      FT_Bitmap_Done( library, &bitmap );
+    }
+
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_objs
+
+#endif /* FT_DEBUG_LEVEL_TRACE */
+
     return error;
   }
 
@@ -4058,7 +4126,7 @@
 
 
     if ( !slot || !slot->face )
-      return FT_Err_Invalid_Argument;
+      return FT_THROW( Invalid_Argument );
 
     library = FT_FACE_LIBRARY( slot->face );
 
@@ -4138,14 +4206,14 @@
                                 FREETYPE_MINOR                  )
 
     if ( !library )
-      return FT_Err_Invalid_Library_Handle;
+      return FT_THROW( Invalid_Library_Handle );
 
     if ( !clazz )
-      return FT_Err_Invalid_Argument;
+      return FT_THROW( Invalid_Argument );
 
     /* check freetype version */
     if ( clazz->module_requires > FREETYPE_VER_FIXED )
-      return FT_Err_Invalid_Version;
+      return FT_THROW( Invalid_Version );
 
     /* look for a module with the same name in the library's table */
     for ( nn = 0; nn < library->num_modules; nn++ )
@@ -4155,7 +4223,7 @@
       {
         /* this installed module has the same name, compare their versions */
         if ( clazz->module_version <= module->clazz->module_version )
-          return FT_Err_Lower_Module_Version;
+          return FT_THROW( Lower_Module_Version );
 
         /* remove the module from our list, then exit the loop to replace */
         /* it by our new version..                                        */
@@ -4169,7 +4237,7 @@
 
     if ( library->num_modules >= FT_MAX_MODULES )
     {
-      error = FT_Err_Too_Many_Drivers;
+      error = FT_THROW( Too_Many_Drivers );
       goto Exit;
     }
 
@@ -4301,19 +4369,18 @@
   {
     FT_Pointer  result = NULL;
 
+
     if ( module )
     {
       FT_ASSERT( module->clazz && module->clazz->get_interface );
 
-     /* first, look for the service in the module
-      */
+      /* first, look for the service in the module */
       if ( module->clazz->get_interface )
         result = module->clazz->get_interface( module, service_id );
 
       if ( result == NULL )
       {
-       /* we didn't find it, look in all other modules then
-        */
+        /* we didn't find it, look in all other modules then */
         FT_Library  library = module->library;
         FT_Module*  cur     = library->modules;
         FT_Module*  limit   = cur + library->num_modules;
@@ -4349,7 +4416,7 @@
     /* try to find the module from the table, then remove it from there */
 
     if ( !library )
-      return FT_Err_Invalid_Library_Handle;
+      return FT_THROW( Invalid_Library_Handle );
 
     if ( module )
     {
@@ -4378,7 +4445,119 @@
         }
       }
     }
-    return FT_Err_Invalid_Driver_Handle;
+    return FT_THROW( Invalid_Driver_Handle );
+  }
+
+
+  FT_Error
+  ft_property_do( FT_Library        library,
+                  const FT_String*  module_name,
+                  const FT_String*  property_name,
+                  void*             value,
+                  FT_Bool           set )
+  {
+    FT_Module*           cur;
+    FT_Module*           limit;
+    FT_Module_Interface  interface;
+
+    FT_Service_Properties  service;
+
+#ifdef FT_DEBUG_LEVEL_ERROR
+    const FT_String*  set_name  = "FT_Property_Set";
+    const FT_String*  get_name  = "FT_Property_Get";
+    const FT_String*  func_name = set ? set_name : get_name;
+#endif
+
+    FT_Bool  missing_func;
+
+
+    if ( !library )
+      return FT_THROW( Invalid_Library_Handle );
+
+    if ( !module_name || !property_name || !value )
+      return FT_THROW( Invalid_Argument );
+
+    cur   = library->modules;
+    limit = cur + library->num_modules;
+
+    /* search module */
+    for ( ; cur < limit; cur++ )
+      if ( !ft_strcmp( cur[0]->clazz->module_name, module_name ) )
+        break;
+
+    if ( cur == limit )
+    {
+      FT_ERROR(( "%s: can't find module `%s'\n",
+                 func_name, module_name ));
+      return FT_THROW( Missing_Module );
+    }
+
+    /* check whether we have a service interface */
+    if ( !cur[0]->clazz->get_interface )
+    {
+      FT_ERROR(( "%s: module `%s' doesn't support properties\n",
+                 func_name, module_name ));
+      return FT_THROW( Unimplemented_Feature );
+    }
+
+    /* search property service */
+    interface = cur[0]->clazz->get_interface( cur[0],
+                                              FT_SERVICE_ID_PROPERTIES );
+    if ( !interface )
+    {
+      FT_ERROR(( "%s: module `%s' doesn't support properties\n",
+                 func_name, module_name ));
+      return FT_THROW( Unimplemented_Feature );
+    }
+
+    service = (FT_Service_Properties)interface;
+
+    if ( set )
+      missing_func = !service->set_property;
+    else
+      missing_func = !service->get_property;
+
+    if ( missing_func )
+    {
+      FT_ERROR(( "%s: property service of module `%s' is broken\n",
+                 func_name, module_name ));
+      return FT_THROW( Unimplemented_Feature );
+    }
+
+    return set ? service->set_property( cur[0], property_name, value )
+               : service->get_property( cur[0], property_name, value );
+  }
+
+
+  /* documentation is in ftmodapi.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Property_Set( FT_Library        library,
+                   const FT_String*  module_name,
+                   const FT_String*  property_name,
+                   const void*       value )
+  {
+    return ft_property_do( library,
+                           module_name,
+                           property_name,
+                           (void*)value,
+                           TRUE );
+  }
+
+
+  /* documentation is in ftmodapi.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Property_Get( FT_Library        library,
+                   const FT_String*  module_name,
+                   const FT_String*  property_name,
+                   void*             value )
+  {
+    return ft_property_do( library,
+                           module_name,
+                           property_name,
+                           value,
+                           FALSE );
   }
 
 
@@ -4417,7 +4596,7 @@
 
 
     if ( !memory )
-      return FT_Err_Invalid_Argument;
+      return FT_THROW( Invalid_Argument );
 
 #ifdef FT_DEBUG_LEVEL_ERROR
     /* init debugging support */
@@ -4504,7 +4683,7 @@
 
 
     if ( !library )
-      return FT_Err_Invalid_Library_Handle;
+      return FT_THROW( Invalid_Library_Handle );
 
     library->refcount--;
     if ( library->refcount > 0 )
@@ -4651,70 +4830,6 @@
   }
 
 
-#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
-
-  FT_BASE_DEF( FT_Error )
-  ft_stub_set_char_sizes( FT_Size     size,
-                          FT_F26Dot6  width,
-                          FT_F26Dot6  height,
-                          FT_UInt     horz_res,
-                          FT_UInt     vert_res )
-  {
-    FT_Size_RequestRec  req;
-    FT_Driver           driver = size->face->driver;
-
-
-    if ( driver->clazz->request_size )
-    {
-      req.type   = FT_SIZE_REQUEST_TYPE_NOMINAL;
-      req.width  = width;
-      req.height = height;
-
-      if ( horz_res == 0 )
-        horz_res = vert_res;
-
-      if ( vert_res == 0 )
-        vert_res = horz_res;
-
-      if ( horz_res == 0 )
-        horz_res = vert_res = 72;
-
-      req.horiResolution = horz_res;
-      req.vertResolution = vert_res;
-
-      return driver->clazz->request_size( size, &req );
-    }
-
-    return 0;
-  }
-
-
-  FT_BASE_DEF( FT_Error )
-  ft_stub_set_pixel_sizes( FT_Size  size,
-                           FT_UInt  width,
-                           FT_UInt  height )
-  {
-    FT_Size_RequestRec  req;
-    FT_Driver           driver = size->face->driver;
-
-
-    if ( driver->clazz->request_size )
-    {
-      req.type           = FT_SIZE_REQUEST_TYPE_NOMINAL;
-      req.width          = width  << 6;
-      req.height         = height << 6;
-      req.horiResolution = 0;
-      req.vertResolution = 0;
-
-      return driver->clazz->request_size( size, &req );
-    }
-
-    return 0;
-  }
-
-#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
-
-
   /* documentation is in freetype.h */
 
   FT_EXPORT_DEF( FT_Error )
@@ -4726,7 +4841,7 @@
                         FT_Int       *p_arg2,
                         FT_Matrix    *p_transform )
   {
-    FT_Error  error = FT_Err_Invalid_Argument;
+    FT_Error  error = FT_ERR( Invalid_Argument );
 
 
     if ( glyph                                      &&
diff --git a/src/base/ftoutln.c b/src/base/ftoutln.c
index 9ae276d..54ca5cd 100644
--- a/src/base/ftoutln.c
+++ b/src/base/ftoutln.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType outline management (body).                                  */
 /*                                                                         */
-/*  Copyright 1996-2008, 2010, 2012 by                                     */
+/*  Copyright 1996-2008, 2010, 2012-2013 by                                */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -26,6 +26,7 @@
 #include <ft2build.h>
 #include FT_OUTLINE_H
 #include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_CALC_H
 #include FT_INTERNAL_DEBUG_H
 #include FT_TRIGONOMETRY_H
 
@@ -73,7 +74,7 @@
 
 
     if ( !outline || !func_interface )
-      return FT_Err_Invalid_Argument;
+      return FT_THROW( Invalid_Argument );
 
     shift = func_interface->shift;
     delta = func_interface->delta;
@@ -286,7 +287,7 @@
     return error;
 
   Invalid_Outline:
-    return FT_Err_Invalid_Outline;
+    return FT_THROW( Invalid_Outline );
   }
 
 
@@ -300,10 +301,17 @@
 
 
     if ( !anoutline || !memory )
-      return FT_Err_Invalid_Argument;
+      return FT_THROW( Invalid_Argument );
 
     *anoutline = null_outline;
 
+    if ( numContours < 0                  ||
+         (FT_UInt)numContours > numPoints )
+      return FT_THROW( Invalid_Argument );
+
+    if ( numPoints > FT_OUTLINE_POINTS_MAX )
+      return FT_THROW( Array_Too_Large );
+
     if ( FT_NEW_ARRAY( anoutline->points,   numPoints   ) ||
          FT_NEW_ARRAY( anoutline->tags,     numPoints   ) ||
          FT_NEW_ARRAY( anoutline->contours, numContours ) )
@@ -332,7 +340,7 @@
                   FT_Outline  *anoutline )
   {
     if ( !library )
-      return FT_Err_Invalid_Library_Handle;
+      return FT_THROW( Invalid_Library_Handle );
 
     return FT_Outline_New_Internal( library->memory, numPoints,
                                     numContours, anoutline );
@@ -380,7 +388,7 @@
     }
 
   Bad:
-    return FT_Err_Invalid_Argument;
+    return FT_THROW( Invalid_Argument );
   }
 
 
@@ -396,7 +404,7 @@
     if ( !source            || !target            ||
          source->n_points   != target->n_points   ||
          source->n_contours != target->n_contours )
-      return FT_Err_Invalid_Argument;
+      return FT_THROW( Invalid_Argument );
 
     if ( source == target )
       return FT_Err_Ok;
@@ -435,7 +443,7 @@
       return FT_Err_Ok;
     }
     else
-      return FT_Err_Invalid_Argument;
+      return FT_THROW( Invalid_Argument );
   }
 
 
@@ -448,7 +456,7 @@
     /* check for valid `outline' in FT_Outline_Done_Internal() */
 
     if ( !library )
-      return FT_Err_Invalid_Library_Handle;
+      return FT_THROW( Invalid_Library_Handle );
 
     return FT_Outline_Done_Internal( library->memory, outline );
   }
@@ -602,21 +610,21 @@
 
 
     if ( !library )
-      return FT_Err_Invalid_Library_Handle;
+      return FT_THROW( Invalid_Library_Handle );
 
     if ( !outline || !params )
-      return FT_Err_Invalid_Argument;
+      return FT_THROW( Invalid_Argument );
 
     renderer = library->cur_renderer;
     node     = library->renderers.head;
 
     params->source = (void*)outline;
 
-    error = FT_Err_Cannot_Render_Glyph;
+    error = FT_ERR( Cannot_Render_Glyph );
     while ( renderer )
     {
       error = renderer->raster_render( renderer->raster, params );
-      if ( !error || FT_ERROR_BASE( error ) != FT_Err_Cannot_Render_Glyph )
+      if ( !error || FT_ERR_NEQ( error, Cannot_Render_Glyph ) )
         break;
 
       /* FT_Err_Cannot_Render_Glyph is returned if the render mode   */
@@ -650,7 +658,7 @@
 
 
     if ( !abitmap )
-      return FT_Err_Invalid_Argument;
+      return FT_THROW( Invalid_Argument );
 
     /* other checks are delayed to FT_Outline_Render() */
 
@@ -882,85 +890,126 @@
   FT_Outline_Embolden( FT_Outline*  outline,
                        FT_Pos       strength )
   {
+    return FT_Outline_EmboldenXY( outline, strength, strength );
+  }
+
+
+  /* documentation is in ftoutln.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FT_Outline_EmboldenXY( FT_Outline*  outline,
+                         FT_Pos       xstrength,
+                         FT_Pos       ystrength )
+  {
     FT_Vector*  points;
     FT_Vector   v_prev, v_first, v_next, v_cur;
-    FT_Angle    rotate, angle_in, angle_out;
     FT_Int      c, n, first;
     FT_Int      orientation;
 
 
     if ( !outline )
-      return FT_Err_Invalid_Argument;
+      return FT_THROW( Invalid_Argument );
 
-    strength /= 2;
-    if ( strength == 0 )
+    xstrength /= 2;
+    ystrength /= 2;
+    if ( xstrength == 0 && ystrength == 0 )
       return FT_Err_Ok;
 
     orientation = FT_Outline_Get_Orientation( outline );
     if ( orientation == FT_ORIENTATION_NONE )
     {
       if ( outline->n_contours )
-        return FT_Err_Invalid_Argument;
+        return FT_THROW( Invalid_Argument );
       else
         return FT_Err_Ok;
     }
 
-    if ( orientation == FT_ORIENTATION_TRUETYPE )
-      rotate = -FT_ANGLE_PI2;
-    else
-      rotate = FT_ANGLE_PI2;
-
     points = outline->points;
 
     first = 0;
     for ( c = 0; c < outline->n_contours; c++ )
     {
-      int  last = outline->contours[c];
+      FT_Vector  in, out, shift;
+      FT_Fixed   l_in, l_out, l, q, d;
+      int        last = outline->contours[c];
 
 
       v_first = points[first];
       v_prev  = points[last];
       v_cur   = v_first;
 
+      /* compute incoming normalized vector */
+      in.x = v_cur.x - v_prev.x;
+      in.y = v_cur.y - v_prev.y;
+      l_in = FT_Vector_Length( &in );
+      if ( l_in )
+      {
+        in.x = FT_DivFix( in.x, l_in );
+        in.y = FT_DivFix( in.y, l_in );
+      }
+
       for ( n = first; n <= last; n++ )
       {
-        FT_Vector  in, out;
-        FT_Angle   angle_diff;
-        FT_Pos     d;
-        FT_Fixed   scale;
-
-
         if ( n < last )
           v_next = points[n + 1];
         else
           v_next = v_first;
 
-        /* compute the in and out vectors */
-        in.x = v_cur.x - v_prev.x;
-        in.y = v_cur.y - v_prev.y;
-
+        /* compute outgoing normalized vector */
         out.x = v_next.x - v_cur.x;
         out.y = v_next.y - v_cur.y;
-
-        angle_in   = FT_Atan2( in.x, in.y );
-        angle_out  = FT_Atan2( out.x, out.y );
-        angle_diff = FT_Angle_Diff( angle_in, angle_out );
-        scale      = FT_Cos( angle_diff / 2 );
-
-        if ( scale < 0x4000L && scale > -0x4000L )
-          in.x = in.y = 0;
-        else
+        l_out = FT_Vector_Length( &out );
+        if ( l_out )
         {
-          d = FT_DivFix( strength, scale );
-
-          FT_Vector_From_Polar( &in, d, angle_in + angle_diff / 2 - rotate );
+          out.x = FT_DivFix( out.x, l_out );
+          out.y = FT_DivFix( out.y, l_out );
         }
 
-        outline->points[n].x = v_cur.x + strength + in.x;
-        outline->points[n].y = v_cur.y + strength + in.y;
+        d = FT_MulFix( in.x, out.x ) + FT_MulFix( in.y, out.y );
 
-        v_prev = v_cur;
-        v_cur  = v_next;
+        /* shift only if turn is less than ~160 degrees */
+        if ( d > -0xF000L )
+        {
+          d = d + 0x10000L;
+
+          /* shift components are aligned along lateral bisector */
+          /* and directed according to the outline orientation.  */
+          shift.x = in.y + out.y;
+          shift.y = in.x + out.x;
+
+          if ( orientation == FT_ORIENTATION_TRUETYPE )
+            shift.x = -shift.x;
+          else
+            shift.y = -shift.y;
+
+          /* restrict shift magnitude to better handle collapsing segments */
+          q = FT_MulFix( out.x, in.y ) - FT_MulFix( out.y, in.x );
+          if ( orientation == FT_ORIENTATION_TRUETYPE )
+            q = -q;
+
+          l = FT_MIN( l_in, l_out );
+
+          /* non-strict inequalities avoid divide-by-zero when q == l == 0 */
+          if ( FT_MulFix( xstrength, q ) <= FT_MulFix( d, l ) )
+            shift.x = FT_MulDiv( shift.x, xstrength, d );
+          else
+            shift.x = FT_MulDiv( shift.x, l, q );
+
+
+          if ( FT_MulFix( ystrength, q ) <= FT_MulFix( d, l ) )
+            shift.y = FT_MulDiv( shift.y, ystrength, d );
+          else
+            shift.y = FT_MulDiv( shift.y, l, q );
+        }
+        else
+          shift.x = shift.y = 0;
+
+        outline->points[n].x = v_cur.x + xstrength + shift.x;
+        outline->points[n].y = v_cur.y + ystrength + shift.y;
+
+        in    = out;
+        l_in  = l_out;
+        v_cur = v_next;
       }
 
       first = last + 1;
@@ -975,23 +1024,12 @@
   FT_EXPORT_DEF( FT_Orientation )
   FT_Outline_Get_Orientation( FT_Outline*  outline )
   {
-    FT_Pos      xmin       = 32768L;
-    FT_Pos      xmin_ymin  = 32768L;
-    FT_Pos      xmin_ymax  = -32768L;
-    FT_Vector*  xmin_first = NULL;
-    FT_Vector*  xmin_last  = NULL;
-
-    short*      contour;
-
-    FT_Vector*  first;
-    FT_Vector*  last;
-    FT_Vector*  prev;
-    FT_Vector*  point;
-
-    int             i;
-    FT_Pos          ray_y[3];
-    FT_Orientation  result[3] =
-      { FT_ORIENTATION_NONE, FT_ORIENTATION_NONE, FT_ORIENTATION_NONE };
+    FT_BBox     cbox;
+    FT_Int      xshift, yshift;
+    FT_Vector*  points;
+    FT_Vector   v_prev, v_cur;
+    FT_Int      c, n, first;
+    FT_Pos      area = 0;
 
 
     if ( !outline || outline->n_points <= 0 )
@@ -1002,127 +1040,41 @@
     /* cubic or quadratic curves, this test deals with the polygon    */
     /* only which is spanned up by the control points.                */
 
-    first = outline->points;
-    for ( contour = outline->contours;
-          contour < outline->contours + outline->n_contours;
-          contour++, first = last + 1 )
+    FT_Outline_Get_CBox( outline, &cbox );
+
+    xshift = FT_MSB( FT_ABS( cbox.xMax ) | FT_ABS( cbox.xMin ) ) - 14;
+    xshift = FT_MAX( xshift, 0 );
+
+    yshift = FT_MSB( cbox.yMax - cbox.yMin ) - 14;
+    yshift = FT_MAX( yshift, 0 );
+
+    points = outline->points;
+
+    first = 0;
+    for ( c = 0; c < outline->n_contours; c++ )
     {
-      FT_Pos  contour_xmin = 32768L;
-      FT_Pos  contour_xmax = -32768L;
-      FT_Pos  contour_ymin = 32768L;
-      FT_Pos  contour_ymax = -32768L;
+      FT_Int  last = outline->contours[c];
 
 
-      last = outline->points + *contour;
+      v_prev = points[last];
 
-      /* skip degenerate contours */
-      if ( last < first + 2 )
-        continue;
-
-      for ( point = first; point <= last; ++point )
+      for ( n = first; n <= last; n++ )
       {
-        if ( point->x < contour_xmin )
-          contour_xmin = point->x;
-
-        if ( point->x > contour_xmax )
-          contour_xmax = point->x;
-
-        if ( point->y < contour_ymin )
-          contour_ymin = point->y;
-
-        if ( point->y > contour_ymax )
-          contour_ymax = point->y;
+        v_cur = points[n];
+        area += ( ( v_cur.y - v_prev.y ) >> yshift ) *
+                ( ( v_cur.x + v_prev.x ) >> xshift );
+        v_prev = v_cur;
       }
 
-      if ( contour_xmin < xmin          &&
-           contour_xmin != contour_xmax &&
-           contour_ymin != contour_ymax )
-      {
-        xmin       = contour_xmin;
-        xmin_ymin  = contour_ymin;
-        xmin_ymax  = contour_ymax;
-        xmin_first = first;
-        xmin_last  = last;
-      }
+      first = last + 1;
     }
 
-    if ( xmin == 32768L )
+    if ( area > 0 )
+      return FT_ORIENTATION_POSTSCRIPT;
+    else if ( area < 0 )
       return FT_ORIENTATION_TRUETYPE;
-
-    ray_y[0] = ( xmin_ymin * 3 + xmin_ymax     ) >> 2;
-    ray_y[1] = ( xmin_ymin     + xmin_ymax     ) >> 1;
-    ray_y[2] = ( xmin_ymin     + xmin_ymax * 3 ) >> 2;
-
-    for ( i = 0; i < 3; i++ )
-    {
-      FT_Pos      left_x;
-      FT_Pos      right_x;
-      FT_Vector*  left1;
-      FT_Vector*  left2;
-      FT_Vector*  right1;
-      FT_Vector*  right2;
-
-
-    RedoRay:
-      left_x  = 32768L;
-      right_x = -32768L;
-
-      left1 = left2 = right1 = right2 = NULL;
-
-      prev = xmin_last;
-      for ( point = xmin_first; point <= xmin_last; prev = point, ++point )
-      {
-        FT_Pos  tmp_x;
-
-
-        if ( point->y == ray_y[i] || prev->y == ray_y[i] )
-        {
-          ray_y[i]++;
-          goto RedoRay;
-        }
-
-        if ( ( point->y < ray_y[i] && prev->y < ray_y[i] ) ||
-             ( point->y > ray_y[i] && prev->y > ray_y[i] ) )
-          continue;
-
-        tmp_x = FT_MulDiv( point->x - prev->x,
-                           ray_y[i] - prev->y,
-                           point->y - prev->y ) + prev->x;
-
-        if ( tmp_x < left_x )
-        {
-          left_x = tmp_x;
-          left1  = prev;
-          left2  = point;
-        }
-
-        if ( tmp_x > right_x )
-        {
-          right_x = tmp_x;
-          right1  = prev;
-          right2  = point;
-        }
-      }
-
-      if ( left1 && right1 )
-      {
-        if ( left1->y < left2->y && right1->y > right2->y )
-          result[i] = FT_ORIENTATION_TRUETYPE;
-        else if ( left1->y > left2->y && right1->y < right2->y )
-          result[i] = FT_ORIENTATION_POSTSCRIPT;
-        else
-          result[i] = FT_ORIENTATION_NONE;
-      }
-    }
-
-    if ( result[0] != FT_ORIENTATION_NONE                     &&
-         ( result[0] == result[1] || result[0] == result[2] ) )
-      return result[0];
-
-    if ( result[1] != FT_ORIENTATION_NONE && result[1] == result[2] )
-      return result[1];
-
-    return FT_ORIENTATION_TRUETYPE;
+    else
+      return FT_ORIENTATION_NONE;
   }
 
 
diff --git a/src/base/ftpic.c b/src/base/ftpic.c
index b74e90d..1c87101 100644
--- a/src/base/ftpic.c
+++ b/src/base/ftpic.c
@@ -29,7 +29,8 @@
   ft_pic_container_init( FT_Library  library )
   {
     FT_PIC_Container*  pic_container = &library->pic_container;
-    FT_Error  error = FT_Err_Ok;
+    FT_Error           error         = FT_Err_Ok;
+
 
     FT_MEM_SET( pic_container, 0, sizeof ( *pic_container ) );
 
diff --git a/src/base/ftrfork.c b/src/base/ftrfork.c
index 01d8625..8049117 100644
--- a/src/base/ftrfork.c
+++ b/src/base/ftrfork.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Embedded resource forks accessor (body).                             */
 /*                                                                         */
-/*  Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010 by                  */
+/*  Copyright 2004-2010, 2013 by                                           */
 /*  Masatake YAMATO and Redhat K.K.                                        */
 /*                                                                         */
 /*  FT_Raccess_Get_HeaderInfo() and raccess_guess_darwin_hfsplus() are     */
@@ -86,7 +86,7 @@
     /* map_len = head[12] .. head[15] */
 
     if ( *rdata_pos + rdata_len != map_pos || map_pos == rfork_offset )
-      return FT_Err_Unknown_File_Format;
+      return FT_THROW( Unknown_File_Format );
 
     error = FT_Stream_Seek( stream, map_pos );
     if ( error )
@@ -108,7 +108,7 @@
         allmatch = 0;
     }
     if ( !allzeros && !allmatch )
-      return FT_Err_Unknown_File_Format;
+      return FT_THROW( Unknown_File_Format );
 
     /* If we have reached this point then it is probably a mac resource */
     /* file.  Now, does it contain any interesting resources?           */
@@ -121,7 +121,7 @@
     if ( FT_READ_USHORT( type_list ) )
       return error;
     if ( type_list == -1 )
-      return FT_Err_Unknown_File_Format;
+      return FT_THROW( Unknown_File_Format );
 
     error = FT_Stream_Seek( stream, map_pos + type_list );
     if ( error )
@@ -233,7 +233,7 @@
       }
     }
 
-    return FT_Err_Cannot_Open_Resource;
+    return FT_THROW( Cannot_Open_Resource );
   }
 
 
@@ -362,7 +362,7 @@
                     FT_Long    *offsets,
                     FT_Error   *errors )
   {
-    FT_Long  i;
+    FT_Int  i;
 
 
     for ( i = 0; i < FT_RACCESS_N_RULES; i++ )
@@ -435,7 +435,7 @@
 
     *result_file_name = NULL;
     if ( NULL == stream )
-      return FT_Err_Cannot_Open_Stream;
+      return FT_THROW( Cannot_Open_Stream );
 
     return raccess_guess_apple_generic( library, stream, base_file_name,
                                         magic, result_offset );
@@ -457,7 +457,7 @@
 
     *result_file_name = NULL;
     if ( NULL == stream )
-      return FT_Err_Cannot_Open_Stream;
+      return FT_THROW( Cannot_Open_Stream );
 
     return raccess_guess_apple_generic( library, stream, base_file_name,
                                         magic, result_offset );
@@ -481,7 +481,7 @@
     memory  = library->memory;
     newpath = raccess_make_file_name( memory, base_file_name, "._" );
     if ( !newpath )
-      return FT_Err_Out_Of_Memory;
+      return FT_THROW( Out_Of_Memory );
 
     error = raccess_guess_linux_double_from_file_name( library, newpath,
                                                        result_offset );
@@ -507,7 +507,7 @@
     FT_Error   error;
     char*      newpath = NULL;
     FT_Memory  memory;
-    FT_Long    base_file_len = ft_strlen( base_file_name );
+    FT_Long    base_file_len = (FT_Long)ft_strlen( base_file_name );
 
     FT_UNUSED( stream );
 
@@ -515,7 +515,7 @@
     memory = library->memory;
 
     if ( base_file_len + 6 > FT_INT_MAX )
-      return FT_Err_Array_Too_Large;
+      return FT_THROW( Array_Too_Large );
 
     if ( FT_ALLOC( newpath, base_file_len + 6 ) )
       return error;
@@ -543,7 +543,7 @@
     FT_Error   error;
     char*      newpath = NULL;
     FT_Memory  memory;
-    FT_Long    base_file_len = ft_strlen( base_file_name );
+    FT_Long    base_file_len = (FT_Long)ft_strlen( base_file_name );
 
     FT_UNUSED( stream );
 
@@ -551,7 +551,7 @@
     memory = library->memory;
 
     if ( base_file_len + 18 > FT_INT_MAX )
-      return FT_Err_Array_Too_Large;
+      return FT_THROW( Array_Too_Large );
 
     if ( FT_ALLOC( newpath, base_file_len + 18 ) )
       return error;
@@ -584,7 +584,7 @@
     newpath = raccess_make_file_name( memory, base_file_name,
                                       "resource.frk/" );
     if ( !newpath )
-      return FT_Err_Out_Of_Memory;
+      return FT_THROW( Out_Of_Memory );
 
     *result_file_name = newpath;
     *result_offset    = 0;
@@ -610,7 +610,7 @@
 
     newpath = raccess_make_file_name( memory, base_file_name, ".resource/" );
     if ( !newpath )
-      return FT_Err_Out_Of_Memory;
+      return FT_THROW( Out_Of_Memory );
 
     *result_file_name = newpath;
     *result_offset    = 0;
@@ -637,7 +637,7 @@
 
     newpath = raccess_make_file_name( memory, base_file_name, "%" );
     if ( !newpath )
-      return FT_Err_Out_Of_Memory;
+      return FT_THROW( Out_Of_Memory );
 
     error = raccess_guess_linux_double_from_file_name( library, newpath,
                                                        result_offset );
@@ -669,7 +669,7 @@
     newpath = raccess_make_file_name( memory, base_file_name,
                                       ".AppleDouble/" );
     if ( !newpath )
-      return FT_Err_Out_Of_Memory;
+      return FT_THROW( Out_Of_Memory );
 
     error = raccess_guess_linux_double_from_file_name( library, newpath,
                                                        result_offset );
@@ -708,7 +708,7 @@
     if ( FT_READ_LONG( magic_from_stream ) )
       return error;
     if ( magic_from_stream != magic )
-      return FT_Err_Unknown_File_Format;
+      return FT_THROW( Unknown_File_Format );
 
     if ( FT_READ_LONG( version_number ) )
       return error;
@@ -721,7 +721,7 @@
     if ( FT_READ_USHORT( n_of_entries ) )
       return error;
     if ( n_of_entries == 0 )
-      return FT_Err_Unknown_File_Format;
+      return FT_THROW( Unknown_File_Format );
 
     for ( i = 0; i < n_of_entries; i++ )
     {
@@ -744,7 +744,7 @@
       }
     }
 
-    return FT_Err_Unknown_File_Format;
+    return FT_THROW( Unknown_File_Format );
   }
 
 
@@ -827,7 +827,7 @@
                     FT_Long    *offsets,
                     FT_Error   *errors )
   {
-    int  i;
+    FT_Int  i;
 
     FT_UNUSED( library );
     FT_UNUSED( stream );
@@ -838,7 +838,7 @@
     {
       new_names[i] = NULL;
       offsets[i]   = 0;
-      errors[i]    = FT_Err_Unimplemented_Feature;
+      errors[i]    = FT_ERR( Unimplemented_Feature );
     }
   }
 
diff --git a/src/base/ftsnames.c b/src/base/ftsnames.c
index 3447888..260e91c 100644
--- a/src/base/ftsnames.c
+++ b/src/base/ftsnames.c
@@ -44,7 +44,7 @@
                     FT_UInt       idx,
                     FT_SfntName  *aname )
   {
-    FT_Error  error = FT_Err_Invalid_Argument;
+    FT_Error  error = FT_ERR( Invalid_Argument );
 
 
     if ( aname && face && FT_IS_SFNT( face ) )
diff --git a/src/base/ftstream.c b/src/base/ftstream.c
index fc2868e..d965333 100644
--- a/src/base/ftstream.c
+++ b/src/base/ftstream.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    I/O stream support (body).                                           */
 /*                                                                         */
-/*  Copyright 2000-2002, 2004-2006, 2008-2011 by                           */
+/*  Copyright 2000-2002, 2004-2006, 2008-2011, 2013 by                     */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -68,7 +68,7 @@
                    " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
                    pos, stream->size ));
 
-        error = FT_Err_Invalid_Stream_Operation;
+        error = FT_THROW( Invalid_Stream_Operation );
       }
     }
     /* note that seeking to the first position after the file is valid */
@@ -78,7 +78,7 @@
                  " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
                  pos, stream->size ));
 
-      error = FT_Err_Invalid_Stream_Operation;
+      error = FT_THROW( Invalid_Stream_Operation );
     }
 
     if ( !error )
@@ -93,7 +93,7 @@
                   FT_Long    distance )
   {
     if ( distance < 0 )
-      return FT_Err_Invalid_Stream_Operation;
+      return FT_THROW( Invalid_Stream_Operation );
 
     return FT_Stream_Seek( stream, (FT_ULong)( stream->pos + distance ) );
   }
@@ -131,7 +131,7 @@
                  " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
                  pos, stream->size ));
 
-      return FT_Err_Invalid_Stream_Operation;
+      return FT_THROW( Invalid_Stream_Operation );
     }
 
     if ( stream->read )
@@ -153,7 +153,7 @@
                  " invalid read; expected %lu bytes, got %lu\n",
                  count, read_bytes ));
 
-      error = FT_Err_Invalid_Stream_Operation;
+      error = FT_THROW( Invalid_Stream_Operation );
     }
 
     return error;
@@ -254,7 +254,7 @@
                    " frame size (%lu) larger than stream size (%lu)\n",
                    count, stream->size ));
 
-        error = FT_Err_Invalid_Stream_Operation;
+        error = FT_THROW( Invalid_Stream_Operation );
         goto Exit;
       }
 
@@ -277,7 +277,7 @@
                    count, read_bytes ));
 
         FT_FREE( stream->base );
-        error = FT_Err_Invalid_Stream_Operation;
+        error = FT_THROW( Invalid_Stream_Operation );
       }
       stream->cursor = stream->base;
       stream->limit  = stream->cursor + count;
@@ -293,7 +293,7 @@
                    " invalid i/o; pos = 0x%lx, count = %lu, size = 0x%lx\n",
                    stream->pos, count, stream->size ));
 
-        error = FT_Err_Invalid_Stream_Operation;
+        error = FT_THROW( Invalid_Stream_Operation );
         goto Exit;
       }
 
@@ -474,7 +474,7 @@
     return result;
 
   Fail:
-    *error = FT_Err_Invalid_Stream_Operation;
+    *error = FT_THROW( Invalid_Stream_Operation );
     FT_ERROR(( "FT_Stream_ReadChar:"
                " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
                stream->pos, stream->size ));
@@ -521,7 +521,7 @@
     return result;
 
   Fail:
-    *error = FT_Err_Invalid_Stream_Operation;
+    *error = FT_THROW( Invalid_Stream_Operation );
     FT_ERROR(( "FT_Stream_ReadUShort:"
                " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
                stream->pos, stream->size ));
@@ -568,7 +568,7 @@
     return result;
 
   Fail:
-    *error = FT_Err_Invalid_Stream_Operation;
+    *error = FT_THROW( Invalid_Stream_Operation );
     FT_ERROR(( "FT_Stream_ReadUShortLE:"
                " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
                stream->pos, stream->size ));
@@ -615,7 +615,7 @@
     return result;
 
   Fail:
-    *error = FT_Err_Invalid_Stream_Operation;
+    *error = FT_THROW( Invalid_Stream_Operation );
     FT_ERROR(( "FT_Stream_ReadUOffset:"
                " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
                stream->pos, stream->size ));
@@ -662,7 +662,7 @@
     return result;
 
   Fail:
-    *error = FT_Err_Invalid_Stream_Operation;
+    *error = FT_THROW( Invalid_Stream_Operation );
     FT_ERROR(( "FT_Stream_ReadULong:"
                " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
                stream->pos, stream->size ));
@@ -709,7 +709,7 @@
     return result;
 
   Fail:
-    *error = FT_Err_Invalid_Stream_Operation;
+    *error = FT_THROW( Invalid_Stream_Operation );
     FT_ERROR(( "FT_Stream_ReadULongLE:"
                " invalid i/o; pos = 0x%lx, size = 0x%lx\n",
                stream->pos, stream->size ));
@@ -727,8 +727,9 @@
     FT_Bool   frame_accessed = 0;
     FT_Byte*  cursor;
 
+
     if ( !fields || !stream )
-      return FT_Err_Invalid_Argument;
+      return FT_THROW( Invalid_Argument );
 
     cursor = stream->cursor;
 
@@ -760,7 +761,7 @@
 
           if ( cursor + len > stream->limit )
           {
-            error = FT_Err_Invalid_Stream_Operation;
+            error = FT_THROW( Invalid_Stream_Operation );
             goto Exit;
           }
 
@@ -776,43 +777,43 @@
 
       case ft_frame_byte:
       case ft_frame_schar:  /* read a single byte */
-        value = FT_NEXT_BYTE(cursor);
+        value = FT_NEXT_BYTE( cursor );
         sign_shift = 24;
         break;
 
       case ft_frame_short_be:
       case ft_frame_ushort_be:  /* read a 2-byte big-endian short */
-        value = FT_NEXT_USHORT(cursor);
+        value = FT_NEXT_USHORT( cursor) ;
         sign_shift = 16;
         break;
 
       case ft_frame_short_le:
       case ft_frame_ushort_le:  /* read a 2-byte little-endian short */
-        value = FT_NEXT_USHORT_LE(cursor);
+        value = FT_NEXT_USHORT_LE( cursor );
         sign_shift = 16;
         break;
 
       case ft_frame_long_be:
       case ft_frame_ulong_be:  /* read a 4-byte big-endian long */
-        value = FT_NEXT_ULONG(cursor);
+        value = FT_NEXT_ULONG( cursor );
         sign_shift = 0;
         break;
 
       case ft_frame_long_le:
       case ft_frame_ulong_le:  /* read a 4-byte little-endian long */
-        value = FT_NEXT_ULONG_LE(cursor);
+        value = FT_NEXT_ULONG_LE( cursor );
         sign_shift = 0;
         break;
 
       case ft_frame_off3_be:
       case ft_frame_uoff3_be:  /* read a 3-byte big-endian long */
-        value = FT_NEXT_UOFF3(cursor);
+        value = FT_NEXT_UOFF3( cursor );
         sign_shift = 8;
         break;
 
       case ft_frame_off3_le:
       case ft_frame_uoff3_le:  /* read a 3-byte little-endian long */
-        value = FT_NEXT_UOFF3_LE(cursor);
+        value = FT_NEXT_UOFF3_LE( cursor );
         sign_shift = 8;
         break;
 
@@ -831,15 +832,15 @@
       p = (FT_Byte*)structure + fields->offset;
       switch ( fields->size )
       {
-      case (8 / FT_CHAR_BIT):
+      case ( 8 / FT_CHAR_BIT ):
         *(FT_Byte*)p = (FT_Byte)value;
         break;
 
-      case (16 / FT_CHAR_BIT):
+      case ( 16 / FT_CHAR_BIT ):
         *(FT_UShort*)p = (FT_UShort)value;
         break;
 
-      case (32 / FT_CHAR_BIT):
+      case ( 32 / FT_CHAR_BIT ):
         *(FT_UInt32*)p = (FT_UInt32)value;
         break;
 
diff --git a/src/base/ftstroke.c b/src/base/ftstroke.c
index 5399efe..ee61cec 100644
--- a/src/base/ftstroke.c
+++ b/src/base/ftstroke.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType path stroker (body).                                        */
 /*                                                                         */
-/*  Copyright 2002-2006, 2008-2011 by                                      */
+/*  Copyright 2002-2006, 2008-2011, 2013 by                                */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -789,13 +789,13 @@
   FT_Stroker_New( FT_Library   library,
                   FT_Stroker  *astroker )
   {
-    FT_Error    error;
+    FT_Error    error;           /* assigned in FT_NEW */
     FT_Memory   memory;
     FT_Stroker  stroker = NULL;
 
 
     if ( !library )
-      return FT_Err_Invalid_Argument;
+      return FT_THROW( Invalid_Argument );
 
     memory = library->memory;
 
@@ -1126,9 +1126,8 @@
           middle.y += stroker->center.y;
 
           /* compute first angle point */
-          length = FT_MulFix( radius,
-                              FT_DivFix( 0x10000L - sigma,
-                                         ft_pos_abs( FT_Sin( theta ) ) ) );
+          length = FT_MulDiv( radius, 0x10000L - sigma,
+                              ft_pos_abs( FT_Sin( theta ) ) );
 
           FT_Vector_From_Polar( &delta, length, phi + rotate );
           delta.x += middle.x;
@@ -1495,7 +1494,7 @@
               sinA = ft_pos_abs( FT_Sin( alpha1 - gamma ) );
               sinB = ft_pos_abs( FT_Sin( beta - gamma ) );
 
-              alen = FT_DivFix( FT_MulFix( blen, sinA ), sinB );
+              alen = FT_MulDiv( blen, sinA, sinB );
 
               FT_Vector_From_Polar( &delta, alen, beta );
               delta.x += start.x;
@@ -1702,7 +1701,7 @@
               sinA = ft_pos_abs( FT_Sin( alpha1 - gamma ) );
               sinB = ft_pos_abs( FT_Sin( beta - gamma ) );
 
-              alen = FT_DivFix( FT_MulFix( blen, sinA ), sinB );
+              alen = FT_MulDiv( blen, sinA, sinB );
 
               FT_Vector_From_Polar( &delta, alen, beta );
               delta.x += start.x;
@@ -1955,7 +1954,7 @@
 
     if ( !stroker || border > 1 )
     {
-      error = FT_Err_Invalid_Argument;
+      error = FT_THROW( Invalid_Argument );
       goto Exit;
     }
 
@@ -2061,7 +2060,7 @@
 
 
     if ( !outline || !stroker )
-      return FT_Err_Invalid_Argument;
+      return FT_THROW( Invalid_Argument );
 
     FT_Stroker_Rewind( stroker );
 
@@ -2239,7 +2238,7 @@
     return error;
 
   Invalid_Outline:
-    return FT_Err_Invalid_Outline;
+    return FT_THROW( Invalid_Outline );
   }
 
 
@@ -2259,7 +2258,7 @@
                    FT_Stroker   stroker,
                    FT_Bool      destroy )
   {
-    FT_Error    error   = FT_Err_Invalid_Argument;
+    FT_Error    error   = FT_ERR( Invalid_Argument );
     FT_Glyph    glyph   = NULL;
     FT_Library  library = stroker->library;
 
@@ -2335,7 +2334,7 @@
                          FT_Bool      inside,
                          FT_Bool      destroy )
   {
-    FT_Error    error   = FT_Err_Invalid_Argument;
+    FT_Error    error   = FT_ERR( Invalid_Argument );
     FT_Glyph    glyph   = NULL;
     FT_Library  library = stroker->library;
 
diff --git a/src/base/ftsynth.c b/src/base/ftsynth.c
index d4ec0da..241d37f 100644
--- a/src/base/ftsynth.c
+++ b/src/base/ftsynth.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType synthesizing code for emboldening and slanting (body).      */
 /*                                                                         */
-/*  Copyright 2000-2001, 2002, 2003, 2004, 2005, 2006, 2010 by             */
+/*  Copyright 2000-2006, 2010, 2012 by                                     */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -33,6 +33,7 @@
 #undef  FT_COMPONENT
 #define FT_COMPONENT  trace_synth
 
+
   /*************************************************************************/
   /*************************************************************************/
   /****                                                                 ****/
@@ -62,7 +63,7 @@
     transform.xx = 0x10000L;
     transform.yx = 0x00000L;
 
-    transform.xy = 0x06000L;
+    transform.xy = 0x0366AL;
     transform.yy = 0x10000L;
 
     FT_Outline_Transform( outline, &transform );
@@ -72,7 +73,7 @@
   /*************************************************************************/
   /*************************************************************************/
   /****                                                                 ****/
-  /****   EXPERIMENTAL EMBOLDENING/OUTLINING SUPPORT                    ****/
+  /****   EXPERIMENTAL EMBOLDENING SUPPORT                              ****/
   /****                                                                 ****/
   /*************************************************************************/
   /*************************************************************************/
@@ -101,12 +102,7 @@
     if ( slot->format == FT_GLYPH_FORMAT_OUTLINE )
     {
       /* ignore error */
-      (void)FT_Outline_Embolden( &slot->outline, xstr );
-
-      /* this is more than enough for most glyphs; if you need accurate */
-      /* values, you have to call FT_Outline_Get_CBox                   */
-      xstr = xstr * 2;
-      ystr = xstr;
+      (void)FT_Outline_EmboldenXY( &slot->outline, xstr, ystr );
     }
     else /* slot->format == FT_GLYPH_FORMAT_BITMAP */
     {
@@ -143,13 +139,10 @@
     if ( slot->advance.y )
       slot->advance.y += ystr;
 
-    slot->metrics.width        += xstr;
-    slot->metrics.height       += ystr;
-    slot->metrics.horiBearingY += ystr;
-    slot->metrics.horiAdvance  += xstr;
-    slot->metrics.vertBearingX -= xstr / 2;
-    slot->metrics.vertBearingY += ystr;
-    slot->metrics.vertAdvance  += ystr;
+    slot->metrics.width       += xstr;
+    slot->metrics.height      += ystr;
+    slot->metrics.horiAdvance += xstr;
+    slot->metrics.vertAdvance += ystr;
 
     /* XXX: 16-bit overflow case must be excluded before here */
     if ( slot->format == FT_GLYPH_FORMAT_BITMAP )
diff --git a/src/base/ftsystem.c b/src/base/ftsystem.c
index 7e203be..2c6ddac 100644
--- a/src/base/ftsystem.c
+++ b/src/base/ftsystem.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    ANSI-specific FreeType low-level system interface (body).            */
 /*                                                                         */
-/*  Copyright 1996-2002, 2006, 2008-2011 by                                */
+/*  Copyright 1996-2002, 2006, 2008-2011, 2013 by                          */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -228,7 +228,7 @@
 
 
     if ( !stream )
-      return FT_Err_Invalid_Stream_Handle;
+      return FT_THROW( Invalid_Stream_Handle );
 
     stream->descriptor.pointer = NULL;
     stream->pathname.pointer   = (char*)filepathname;
@@ -243,7 +243,7 @@
       FT_ERROR(( "FT_Stream_Open:"
                  " could not open `%s'\n", filepathname ));
 
-      return FT_Err_Cannot_Open_Resource;
+      return FT_THROW( Cannot_Open_Resource );
     }
 
     ft_fseek( file, 0, SEEK_END );
@@ -253,7 +253,7 @@
       FT_ERROR(( "FT_Stream_Open:" ));
       FT_ERROR(( " opened `%s' but zero-sized\n", filepathname ));
       ft_fclose( file );
-      return FT_Err_Cannot_Open_Stream;
+      return FT_THROW( Cannot_Open_Stream );
     }
     ft_fseek( file, 0, SEEK_SET );
 
diff --git a/src/base/fttrigon.c b/src/base/fttrigon.c
index fdf433a..4ffdcb7 100644
--- a/src/base/fttrigon.c
+++ b/src/base/fttrigon.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType trigonometric functions (body).                             */
 /*                                                                         */
-/*  Copyright 2001, 2002, 2003, 2004, 2005 by                              */
+/*  Copyright 2001-2005, 2012-2013 by                                      */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -15,31 +15,46 @@
 /*                                                                         */
 /***************************************************************************/
 
+  /*************************************************************************/
+  /*                                                                       */
+  /* This is a fixed-point CORDIC implementation of trigonometric          */
+  /* functions as well as transformations between Cartesian and polar      */
+  /* coordinates.  The angles are represented as 16.16 fixed-point values  */
+  /* in degrees, i.e., the angular resolution is 2^-16 degrees.  Note that */
+  /* only vectors longer than 2^16*180/pi (or at least 22 bits) on a       */
+  /* discrete Cartesian grid can have the same or better angular           */
+  /* resolution.  Therefore, to maintain this precision, some functions    */
+  /* require an interim upscaling of the vectors, whereas others operate   */
+  /* with 24-bit long vectors directly.                                    */
+  /*                                                                       */
+  /*************************************************************************/
 
 #include <ft2build.h>
 #include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_CALC_H
 #include FT_TRIGONOMETRY_H
 
 
-  /* the following is 0.2715717684432231 * 2^30 */
-#define FT_TRIG_COSCALE  0x11616E8EUL
+  /* the Cordic shrink factor 0.858785336480436 * 2^32 */
+#define FT_TRIG_SCALE      0xDBD95B16UL
+
+  /* the highest bit in overflow-safe vector components, */
+  /* MSB of 0.858785336480436 * sqrt(0.5) * 2^30         */
+#define FT_TRIG_SAFE_MSB   29
 
   /* this table was generated for FT_PI = 180L << 16, i.e. degrees */
 #define FT_TRIG_MAX_ITERS  23
 
   static const FT_Fixed
-  ft_trig_arctan_table[24] =
+  ft_trig_arctan_table[] =
   {
-    4157273L, 2949120L, 1740967L, 919879L, 466945L, 234379L, 117304L,
-    58666L, 29335L, 14668L, 7334L, 3667L, 1833L, 917L, 458L, 229L, 115L,
+    1740967L, 919879L, 466945L, 234379L, 117304L, 58666L, 29335L,
+    14668L, 7334L, 3667L, 1833L, 917L, 458L, 229L, 115L,
     57L, 29L, 14L, 7L, 4L, 2L, 1L
   };
 
-  /* the Cordic shrink factor, multiplied by 2^32 */
-#define FT_TRIG_SCALE    1166391785UL  /* 0x4585BA38UL */
 
-
-#ifdef FT_CONFIG_HAS_INT64
+#ifdef FT_LONG64
 
   /* multiply a given value by the CORDIC shrink factor */
   static FT_Fixed
@@ -50,7 +65,7 @@
 
 
     s   = val;
-    val = ( val >= 0 ) ? val : -val;
+    val = FT_ABS( val );
 
     v   = ( val * (FT_Int64)FT_TRIG_SCALE ) + 0x100000000UL;
     val = (FT_Fixed)( v >> 32 );
@@ -58,7 +73,7 @@
     return ( s >= 0 ) ? val : -val;
   }
 
-#else /* !FT_CONFIG_HAS_INT64 */
+#else /* !FT_LONG64 */
 
   /* multiply a given value by the CORDIC shrink factor */
   static FT_Fixed
@@ -69,19 +84,19 @@
 
 
     s   = val;
-    val = ( val >= 0 ) ? val : -val;
+    val = FT_ABS( val );
 
     v1 = (FT_UInt32)val >> 16;
-    v2 = (FT_UInt32)(val & 0xFFFFL);
+    v2 = (FT_UInt32)( val & 0xFFFFL );
 
-    k1 = (FT_UInt32)FT_TRIG_SCALE >> 16;       /* constant */
-    k2 = (FT_UInt32)(FT_TRIG_SCALE & 0xFFFFL);   /* constant */
+    k1 = (FT_UInt32)FT_TRIG_SCALE >> 16;           /* constant */
+    k2 = (FT_UInt32)( FT_TRIG_SCALE & 0xFFFFL );   /* constant */
 
     hi   = k1 * v1;
     lo1  = k1 * v2 + k2 * v1;       /* can't overflow */
 
     lo2  = ( k2 * v2 ) >> 16;
-    lo3  = ( lo1 >= lo2 ) ? lo1 : lo2;
+    lo3  = FT_MAX( lo1, lo2 );
     lo1 += lo2;
 
     hi  += lo1 >> 16;
@@ -93,91 +108,35 @@
     return ( s >= 0 ) ? val : -val;
   }
 
-#endif /* !FT_CONFIG_HAS_INT64 */
+#endif /* !FT_LONG64 */
 
 
   static FT_Int
   ft_trig_prenorm( FT_Vector*  vec )
   {
-    FT_Fixed  x, y, z;
-    FT_Int    shift;
+    FT_Pos  x, y;
+    FT_Int  shift;
 
 
     x = vec->x;
     y = vec->y;
 
-    z     = ( ( x >= 0 ) ? x : - x ) | ( (y >= 0) ? y : -y );
-    shift = 0;
+    shift = FT_MSB( FT_ABS( x ) | FT_ABS( y ) );
 
-#if 1
-    /* determine msb bit index in `shift' */
-    if ( z >= ( 1L << 16 ) )
+    if ( shift <= FT_TRIG_SAFE_MSB )
     {
-      z     >>= 16;
-      shift  += 16;
-    }
-    if ( z >= ( 1L << 8 ) )
-    {
-      z     >>= 8;
-      shift  += 8;
-    }
-    if ( z >= ( 1L << 4 ) )
-    {
-      z     >>= 4;
-      shift  += 4;
-    }
-    if ( z >= ( 1L << 2 ) )
-    {
-      z     >>= 2;
-      shift  += 2;
-    }
-    if ( z >= ( 1L << 1 ) )
-    {
-      z    >>= 1;
-      shift += 1;
-    }
-
-    if ( shift <= 27 )
-    {
-      shift  = 27 - shift;
-      vec->x = x << shift;
-      vec->y = y << shift;
+      shift  = FT_TRIG_SAFE_MSB - shift;
+      vec->x = (FT_Pos)( (FT_ULong)x << shift );
+      vec->y = (FT_Pos)( (FT_ULong)y << shift );
     }
     else
     {
-      shift -= 27;
+      shift -= FT_TRIG_SAFE_MSB;
       vec->x = x >> shift;
       vec->y = y >> shift;
       shift  = -shift;
     }
 
-#else /* 0 */
-
-    if ( z < ( 1L << 27 ) )
-    {
-      do
-      {
-        shift++;
-        z <<= 1;
-      } while ( z < ( 1L << 27 ) );
-      vec->x = x << shift;
-      vec->y = y << shift;
-    }
-    else if ( z > ( 1L << 28 ) )
-    {
-      do
-      {
-        shift++;
-        z >>= 1;
-      } while ( z > ( 1L << 28 ) );
-
-      vec->x = x >> shift;
-      vec->y = y >> shift;
-      shift  = -shift;
-    }
-
-#endif /* 0 */
-
     return shift;
   }
 
@@ -187,65 +146,50 @@
                          FT_Angle    theta )
   {
     FT_Int           i;
-    FT_Fixed         x, y, xtemp;
+    FT_Fixed         x, y, xtemp, b;
     const FT_Fixed  *arctanptr;
 
 
     x = vec->x;
     y = vec->y;
 
-    /* Get angle between -90 and 90 degrees */
-    while ( theta <= -FT_ANGLE_PI2 )
+    /* Rotate inside [-PI/4,PI/4] sector */
+    while ( theta < -FT_ANGLE_PI4 )
     {
-      x = -x;
-      y = -y;
-      theta += FT_ANGLE_PI;
+      xtemp  =  y;
+      y      = -x;
+      x      =  xtemp;
+      theta +=  FT_ANGLE_PI2;
     }
 
-    while ( theta > FT_ANGLE_PI2 )
+    while ( theta > FT_ANGLE_PI4 )
     {
-      x = -x;
-      y = -y;
-      theta -= FT_ANGLE_PI;
+      xtemp  = -y;
+      y      =  x;
+      x      =  xtemp;
+      theta -=  FT_ANGLE_PI2;
     }
 
-    /* Initial pseudorotation, with left shift */
     arctanptr = ft_trig_arctan_table;
 
-    if ( theta < 0 )
-    {
-      xtemp  = x + ( y << 1 );
-      y      = y - ( x << 1 );
-      x      = xtemp;
-      theta += *arctanptr++;
-    }
-    else
-    {
-      xtemp  = x - ( y << 1 );
-      y      = y + ( x << 1 );
-      x      = xtemp;
-      theta -= *arctanptr++;
-    }
-
-    /* Subsequent pseudorotations, with right shifts */
-    i = 0;
-    do
+    /* Pseudorotations, with right shifts */
+    for ( i = 1, b = 1; i < FT_TRIG_MAX_ITERS; b <<= 1, i++ )
     {
       if ( theta < 0 )
       {
-        xtemp  = x + ( y >> i );
-        y      = y - ( x >> i );
+        xtemp  = x + ( ( y + b ) >> i );
+        y      = y - ( ( x + b ) >> i );
         x      = xtemp;
         theta += *arctanptr++;
       }
       else
       {
-        xtemp  = x - ( y >> i );
-        y      = y + ( x >> i );
+        xtemp  = x - ( ( y + b ) >> i );
+        y      = y + ( ( x + b ) >> i );
         x      = xtemp;
         theta -= *arctanptr++;
       }
-    } while ( ++i < FT_TRIG_MAX_ITERS );
+    }
 
     vec->x = x;
     vec->y = y;
@@ -255,66 +199,67 @@
   static void
   ft_trig_pseudo_polarize( FT_Vector*  vec )
   {
-    FT_Fixed         theta;
-    FT_Fixed         yi, i;
-    FT_Fixed         x, y;
+    FT_Angle         theta;
+    FT_Int           i;
+    FT_Fixed         x, y, xtemp, b;
     const FT_Fixed  *arctanptr;
 
 
     x = vec->x;
     y = vec->y;
 
-    /* Get the vector into the right half plane */
-    theta = 0;
-    if ( x < 0 )
+    /* Get the vector into [-PI/4,PI/4] sector */
+    if ( y > x )
     {
-      x = -x;
-      y = -y;
-      theta = 2 * FT_ANGLE_PI2;
-    }
-
-    if ( y > 0 )
-      theta = - theta;
-
-    arctanptr = ft_trig_arctan_table;
-
-    if ( y < 0 )
-    {
-      /* Rotate positive */
-      yi     = y + ( x << 1 );
-      x      = x - ( y << 1 );
-      y      = yi;
-      theta -= *arctanptr++;  /* Subtract angle */
-    }
-    else
-    {
-      /* Rotate negative */
-      yi     = y - ( x << 1 );
-      x      = x + ( y << 1 );
-      y      = yi;
-      theta += *arctanptr++;  /* Add angle */
-    }
-
-    i = 0;
-    do
-    {
-      if ( y < 0 )
+      if ( y > -x )
       {
-        /* Rotate positive */
-        yi     = y + ( x >> i );
-        x      = x - ( y >> i );
-        y      = yi;
-        theta -= *arctanptr++;
+        theta =  FT_ANGLE_PI2;
+        xtemp =  y;
+        y     = -x;
+        x     =  xtemp;
       }
       else
       {
-        /* Rotate negative */
-        yi     = y - ( x >> i );
-        x      = x + ( y >> i );
-        y      = yi;
+        theta =  y > 0 ? FT_ANGLE_PI : -FT_ANGLE_PI;
+        x     = -x;
+        y     = -y;
+      }
+    }
+    else
+    {
+      if ( y < -x )
+      {
+        theta = -FT_ANGLE_PI2;
+        xtemp = -y;
+        y     =  x;
+        x     =  xtemp;
+      }
+      else
+      {
+        theta = 0;
+      }
+    }
+
+    arctanptr = ft_trig_arctan_table;
+
+    /* Pseudorotations, with right shifts */
+    for ( i = 1, b = 1; i < FT_TRIG_MAX_ITERS; b <<= 1, i++ )
+    {
+      if ( y > 0 )
+      {
+        xtemp  = x + ( ( y + b ) >> i );
+        y      = y - ( ( x + b ) >> i );
+        x      = xtemp;
         theta += *arctanptr++;
       }
-    } while ( ++i < FT_TRIG_MAX_ITERS );
+      else
+      {
+        xtemp  = x - ( ( y + b ) >> i );
+        y      = y + ( ( x + b ) >> i );
+        x      = xtemp;
+        theta -= *arctanptr++;
+      }
+    }
 
     /* round theta */
     if ( theta >= 0 )
@@ -335,11 +280,11 @@
     FT_Vector  v;
 
 
-    v.x = FT_TRIG_COSCALE >> 2;
+    v.x = FT_TRIG_SCALE >> 8;
     v.y = 0;
     ft_trig_pseudo_rotate( &v, angle );
 
-    return v.x / ( 1 << 12 );
+    return ( v.x + 0x80L ) >> 8;
   }
 
 
@@ -360,7 +305,7 @@
     FT_Vector  v;
 
 
-    v.x = FT_TRIG_COSCALE >> 2;
+    v.x = FT_TRIG_SCALE >> 8;
     v.y = 0;
     ft_trig_pseudo_rotate( &v, angle );
 
@@ -395,11 +340,11 @@
   FT_Vector_Unit( FT_Vector*  vec,
                   FT_Angle    angle )
   {
-    vec->x = FT_TRIG_COSCALE >> 2;
+    vec->x = FT_TRIG_SCALE >> 8;
     vec->y = 0;
     ft_trig_pseudo_rotate( vec, angle );
-    vec->x >>= 12;
-    vec->y >>= 12;
+    vec->x = ( vec->x + 0x80L ) >> 8;
+    vec->y = ( vec->y + 0x80L ) >> 8;
   }
 
 
@@ -442,8 +387,8 @@
       else
       {
         shift  = -shift;
-        vec->x = v.x << shift;
-        vec->y = v.y << shift;
+        vec->x = (FT_Pos)( (FT_ULong)v.x << shift );
+        vec->y = (FT_Pos)( (FT_ULong)v.y << shift );
       }
     }
   }
@@ -463,11 +408,11 @@
     /* handle trivial cases */
     if ( v.x == 0 )
     {
-      return ( v.y >= 0 ) ? v.y : -v.y;
+      return FT_ABS( v.y );
     }
     else if ( v.y == 0 )
     {
-      return ( v.x >= 0 ) ? v.x : -v.x;
+      return FT_ABS( v.x );
     }
 
     /* general case */
@@ -479,7 +424,7 @@
     if ( shift > 0 )
       return ( v.x + ( 1 << ( shift - 1 ) ) ) >> shift;
 
-    return v.x << -shift;
+    return (FT_Fixed)( (FT_UInt32)v.x << -shift );
   }
 
 
@@ -504,7 +449,8 @@
 
     v.x = ft_trig_downscale( v.x );
 
-    *length = ( shift >= 0 ) ? ( v.x >> shift ) : ( v.x << -shift );
+    *length = ( shift >= 0 ) ?                      ( v.x >>  shift )
+                             : (FT_Fixed)( (FT_UInt32)v.x << -shift );
     *angle  = v.y;
   }
 
diff --git a/src/base/fttype1.c b/src/base/fttype1.c
index c30124f..1d17402 100644
--- a/src/base/fttype1.c
+++ b/src/base/fttype1.c
@@ -28,7 +28,7 @@
   FT_Get_PS_Font_Info( FT_Face          face,

                        PS_FontInfoRec*  afont_info )

   {

-    FT_Error  error = FT_Err_Invalid_Argument;

+    FT_Error  error = FT_ERR( Invalid_Argument );

 

 

     if ( face )

@@ -73,7 +73,7 @@
   FT_Get_PS_Font_Private( FT_Face         face,

                           PS_PrivateRec*  afont_private )

   {

-    FT_Error  error = FT_Err_Invalid_Argument;

+    FT_Error  error = FT_ERR( Invalid_Argument );

 

 

     if ( face )

diff --git a/src/base/ftutil.c b/src/base/ftutil.c
index 5f77be5..879d027 100644
--- a/src/base/ftutil.c
+++ b/src/base/ftutil.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType utility file for memory and list management (body).         */
 /*                                                                         */
-/*  Copyright 2002, 2004, 2005, 2006, 2007 by                              */
+/*  Copyright 2002, 2004-2007, 2013 by                                     */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -75,12 +75,12 @@
     {
       block = memory->alloc( memory, size );
       if ( block == NULL )
-        error = FT_Err_Out_Of_Memory;
+        error = FT_THROW( Out_Of_Memory );
     }
     else if ( size < 0 )
     {
       /* may help catch/prevent security issues */
-      error = FT_Err_Invalid_Argument;
+      error = FT_THROW( Invalid_Argument );
     }
 
     *p_error = error;
@@ -98,6 +98,7 @@
   {
     FT_Error  error = FT_Err_Ok;
 
+
     block = ft_mem_qrealloc( memory, item_size,
                              cur_count, new_count, block, &error );
     if ( !error && new_count > cur_count )
@@ -127,7 +128,7 @@
     if ( cur_count < 0 || new_count < 0 || item_size < 0 )
     {
       /* may help catch/prevent nasty security issues */
-      error = FT_Err_Invalid_Argument;
+      error = FT_THROW( Invalid_Argument );
     }
     else if ( new_count == 0 || item_size == 0 )
     {
@@ -136,7 +137,7 @@
     }
     else if ( new_count > FT_INT_MAX/item_size )
     {
-      error = FT_Err_Array_Too_Large;
+      error = FT_THROW( Array_Too_Large );
     }
     else if ( cur_count == 0 )
     {
@@ -153,7 +154,7 @@
 
       block2 = memory->realloc( memory, cur_size, new_size, block );
       if ( block2 == NULL )
-        error = FT_Err_Out_Of_Memory;
+        error = FT_THROW( Out_Of_Memory );
       else
         block = block2;
     }
@@ -432,70 +433,4 @@
   }
 
 
-#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
-
-  FT_BASE_DEF( FT_Error )
-  FT_Alloc( FT_Memory  memory,
-            FT_Long    size,
-            void*     *P )
-  {
-    FT_Error  error;
-
-
-    (void)FT_ALLOC( *P, size );
-    return error;
-  }
-
-
-  FT_BASE_DEF( FT_Error )
-  FT_QAlloc( FT_Memory  memory,
-             FT_Long    size,
-             void*     *p )
-  {
-    FT_Error  error;
-
-
-    (void)FT_QALLOC( *p, size );
-    return error;
-  }
-
-
-  FT_BASE_DEF( FT_Error )
-  FT_Realloc( FT_Memory  memory,
-              FT_Long    current,
-              FT_Long    size,
-              void*     *P )
-  {
-    FT_Error  error;
-
-
-    (void)FT_REALLOC( *P, current, size );
-    return error;
-  }
-
-
-  FT_BASE_DEF( FT_Error )
-  FT_QRealloc( FT_Memory  memory,
-               FT_Long    current,
-               FT_Long    size,
-               void*     *p )
-  {
-    FT_Error  error;
-
-
-    (void)FT_QREALLOC( *p, current, size );
-    return error;
-  }
-
-
-  FT_BASE_DEF( void )
-  FT_Free( FT_Memory  memory,
-           void*     *P )
-  {
-    if ( *P )
-      FT_MEM_FREE( *P );
-  }
-
-#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
-
 /* END */
diff --git a/src/base/ftwinfnt.c b/src/base/ftwinfnt.c
index bc2e90e..463ae76 100644
--- a/src/base/ftwinfnt.c
+++ b/src/base/ftwinfnt.c
@@ -32,7 +32,7 @@
     FT_Error           error;
 
 
-    error = FT_Err_Invalid_Argument;
+    error = FT_ERR( Invalid_Argument );
 
     if ( face != NULL )
     {
diff --git a/src/base/md5.c b/src/base/md5.c
new file mode 100644
index 0000000..2f01c93
--- /dev/null
+++ b/src/base/md5.c
@@ -0,0 +1,295 @@
+/*
+ * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
+ * MD5 Message-Digest Algorithm (RFC 1321).
+ *
+ * Homepage:
+ * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
+ *
+ * Author:
+ * Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
+ *
+ * This software was written by Alexander Peslyak in 2001.  No copyright is
+ * claimed, and the software is hereby placed in the public domain.
+ * In case this attempt to disclaim copyright and place the software in the
+ * public domain is deemed null and void, then the software is
+ * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
+ * general public under the following terms:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted.
+ *
+ * There's ABSOLUTELY NO WARRANTY, express or implied.
+ *
+ * (This is a heavily cut-down "BSD license".)
+ *
+ * This differs from Colin Plumb's older public domain implementation in that
+ * no exactly 32-bit integer data type is required (any 32-bit or wider
+ * unsigned integer data type will do), there's no compile-time endianness
+ * configuration, and the function prototypes match OpenSSL's.  No code from
+ * Colin Plumb's implementation has been reused; this comment merely compares
+ * the properties of the two independent implementations.
+ *
+ * The primary goals of this implementation are portability and ease of use.
+ * It is meant to be fast, but not as fast as possible.  Some known
+ * optimizations are not included to reduce source code size and avoid
+ * compile-time configuration.
+ */
+
+#ifndef HAVE_OPENSSL
+
+#include <string.h>
+
+#include "md5.h"
+
+/*
+ * The basic MD5 functions.
+ *
+ * F and G are optimized compared to their RFC 1321 definitions for
+ * architectures that lack an AND-NOT instruction, just like in Colin Plumb's
+ * implementation.
+ */
+#define F(x, y, z)			((z) ^ ((x) & ((y) ^ (z))))
+#define G(x, y, z)			((y) ^ ((z) & ((x) ^ (y))))
+#define H(x, y, z)			((x) ^ (y) ^ (z))
+#define I(x, y, z)			((y) ^ ((x) | ~(z)))
+
+/*
+ * The MD5 transformation for all four rounds.
+ */
+#define STEP(f, a, b, c, d, x, t, s) \
+	(a) += f((b), (c), (d)) + (x) + (t); \
+	(a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
+	(a) += (b);
+
+/*
+ * SET reads 4 input bytes in little-endian byte order and stores them
+ * in a properly aligned word in host byte order.
+ *
+ * The check for little-endian architectures that tolerate unaligned
+ * memory accesses is just an optimization.  Nothing will break if it
+ * doesn't work.
+ */
+#if defined(__i386__) || defined(__x86_64__) || defined(__vax__)
+#define SET(n) \
+	(*(MD5_u32plus *)&ptr[(n) * 4])
+#define GET(n) \
+	SET(n)
+#else
+#define SET(n) \
+	(ctx->block[(n)] = \
+	(MD5_u32plus)ptr[(n) * 4] | \
+	((MD5_u32plus)ptr[(n) * 4 + 1] << 8) | \
+	((MD5_u32plus)ptr[(n) * 4 + 2] << 16) | \
+	((MD5_u32plus)ptr[(n) * 4 + 3] << 24))
+#define GET(n) \
+	(ctx->block[(n)])
+#endif
+
+/*
+ * This processes one or more 64-byte data blocks, but does NOT update
+ * the bit counters.  There are no alignment requirements.
+ */
+static void *body(MD5_CTX *ctx, void *data, unsigned long size)
+{
+	unsigned char *ptr;
+	MD5_u32plus a, b, c, d;
+	MD5_u32plus saved_a, saved_b, saved_c, saved_d;
+
+	ptr = (unsigned char *)data;
+
+	a = ctx->a;
+	b = ctx->b;
+	c = ctx->c;
+	d = ctx->d;
+
+	do {
+		saved_a = a;
+		saved_b = b;
+		saved_c = c;
+		saved_d = d;
+
+/* Round 1 */
+		STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
+		STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
+		STEP(F, c, d, a, b, SET(2), 0x242070db, 17)
+		STEP(F, b, c, d, a, SET(3), 0xc1bdceee, 22)
+		STEP(F, a, b, c, d, SET(4), 0xf57c0faf, 7)
+		STEP(F, d, a, b, c, SET(5), 0x4787c62a, 12)
+		STEP(F, c, d, a, b, SET(6), 0xa8304613, 17)
+		STEP(F, b, c, d, a, SET(7), 0xfd469501, 22)
+		STEP(F, a, b, c, d, SET(8), 0x698098d8, 7)
+		STEP(F, d, a, b, c, SET(9), 0x8b44f7af, 12)
+		STEP(F, c, d, a, b, SET(10), 0xffff5bb1, 17)
+		STEP(F, b, c, d, a, SET(11), 0x895cd7be, 22)
+		STEP(F, a, b, c, d, SET(12), 0x6b901122, 7)
+		STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
+		STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
+		STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
+
+/* Round 2 */
+		STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
+		STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
+		STEP(G, c, d, a, b, GET(11), 0x265e5a51, 14)
+		STEP(G, b, c, d, a, GET(0), 0xe9b6c7aa, 20)
+		STEP(G, a, b, c, d, GET(5), 0xd62f105d, 5)
+		STEP(G, d, a, b, c, GET(10), 0x02441453, 9)
+		STEP(G, c, d, a, b, GET(15), 0xd8a1e681, 14)
+		STEP(G, b, c, d, a, GET(4), 0xe7d3fbc8, 20)
+		STEP(G, a, b, c, d, GET(9), 0x21e1cde6, 5)
+		STEP(G, d, a, b, c, GET(14), 0xc33707d6, 9)
+		STEP(G, c, d, a, b, GET(3), 0xf4d50d87, 14)
+		STEP(G, b, c, d, a, GET(8), 0x455a14ed, 20)
+		STEP(G, a, b, c, d, GET(13), 0xa9e3e905, 5)
+		STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
+		STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
+		STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
+
+/* Round 3 */
+		STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
+		STEP(H, d, a, b, c, GET(8), 0x8771f681, 11)
+		STEP(H, c, d, a, b, GET(11), 0x6d9d6122, 16)
+		STEP(H, b, c, d, a, GET(14), 0xfde5380c, 23)
+		STEP(H, a, b, c, d, GET(1), 0xa4beea44, 4)
+		STEP(H, d, a, b, c, GET(4), 0x4bdecfa9, 11)
+		STEP(H, c, d, a, b, GET(7), 0xf6bb4b60, 16)
+		STEP(H, b, c, d, a, GET(10), 0xbebfbc70, 23)
+		STEP(H, a, b, c, d, GET(13), 0x289b7ec6, 4)
+		STEP(H, d, a, b, c, GET(0), 0xeaa127fa, 11)
+		STEP(H, c, d, a, b, GET(3), 0xd4ef3085, 16)
+		STEP(H, b, c, d, a, GET(6), 0x04881d05, 23)
+		STEP(H, a, b, c, d, GET(9), 0xd9d4d039, 4)
+		STEP(H, d, a, b, c, GET(12), 0xe6db99e5, 11)
+		STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
+		STEP(H, b, c, d, a, GET(2), 0xc4ac5665, 23)
+
+/* Round 4 */
+		STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
+		STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
+		STEP(I, c, d, a, b, GET(14), 0xab9423a7, 15)
+		STEP(I, b, c, d, a, GET(5), 0xfc93a039, 21)
+		STEP(I, a, b, c, d, GET(12), 0x655b59c3, 6)
+		STEP(I, d, a, b, c, GET(3), 0x8f0ccc92, 10)
+		STEP(I, c, d, a, b, GET(10), 0xffeff47d, 15)
+		STEP(I, b, c, d, a, GET(1), 0x85845dd1, 21)
+		STEP(I, a, b, c, d, GET(8), 0x6fa87e4f, 6)
+		STEP(I, d, a, b, c, GET(15), 0xfe2ce6e0, 10)
+		STEP(I, c, d, a, b, GET(6), 0xa3014314, 15)
+		STEP(I, b, c, d, a, GET(13), 0x4e0811a1, 21)
+		STEP(I, a, b, c, d, GET(4), 0xf7537e82, 6)
+		STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
+		STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
+		STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
+
+		a += saved_a;
+		b += saved_b;
+		c += saved_c;
+		d += saved_d;
+
+		ptr += 64;
+	} while (size -= 64);
+
+	ctx->a = a;
+	ctx->b = b;
+	ctx->c = c;
+	ctx->d = d;
+
+	return ptr;
+}
+
+void MD5_Init(MD5_CTX *ctx)
+{
+	ctx->a = 0x67452301;
+	ctx->b = 0xefcdab89;
+	ctx->c = 0x98badcfe;
+	ctx->d = 0x10325476;
+
+	ctx->lo = 0;
+	ctx->hi = 0;
+}
+
+void MD5_Update(MD5_CTX *ctx, void *data, unsigned long size)
+{
+	MD5_u32plus saved_lo;
+	unsigned long used, free;
+
+	saved_lo = ctx->lo;
+	if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
+		ctx->hi++;
+	ctx->hi += size >> 29;
+
+	used = saved_lo & 0x3f;
+
+	if (used) {
+		free = 64 - used;
+
+		if (size < free) {
+			memcpy(&ctx->buffer[used], data, size);
+			return;
+		}
+
+		memcpy(&ctx->buffer[used], data, free);
+		data = (unsigned char *)data + free;
+		size -= free;
+		body(ctx, ctx->buffer, 64);
+	}
+
+	if (size >= 64) {
+		data = body(ctx, data, size & ~(unsigned long)0x3f);
+		size &= 0x3f;
+	}
+
+	memcpy(ctx->buffer, data, size);
+}
+
+void MD5_Final(unsigned char *result, MD5_CTX *ctx)
+{
+	unsigned long used, free;
+
+	used = ctx->lo & 0x3f;
+
+	ctx->buffer[used++] = 0x80;
+
+	free = 64 - used;
+
+	if (free < 8) {
+		memset(&ctx->buffer[used], 0, free);
+		body(ctx, ctx->buffer, 64);
+		used = 0;
+		free = 64;
+	}
+
+	memset(&ctx->buffer[used], 0, free - 8);
+
+	ctx->lo <<= 3;
+	ctx->buffer[56] = ctx->lo;
+	ctx->buffer[57] = ctx->lo >> 8;
+	ctx->buffer[58] = ctx->lo >> 16;
+	ctx->buffer[59] = ctx->lo >> 24;
+	ctx->buffer[60] = ctx->hi;
+	ctx->buffer[61] = ctx->hi >> 8;
+	ctx->buffer[62] = ctx->hi >> 16;
+	ctx->buffer[63] = ctx->hi >> 24;
+
+	body(ctx, ctx->buffer, 64);
+
+	result[0] = ctx->a;
+	result[1] = ctx->a >> 8;
+	result[2] = ctx->a >> 16;
+	result[3] = ctx->a >> 24;
+	result[4] = ctx->b;
+	result[5] = ctx->b >> 8;
+	result[6] = ctx->b >> 16;
+	result[7] = ctx->b >> 24;
+	result[8] = ctx->c;
+	result[9] = ctx->c >> 8;
+	result[10] = ctx->c >> 16;
+	result[11] = ctx->c >> 24;
+	result[12] = ctx->d;
+	result[13] = ctx->d >> 8;
+	result[14] = ctx->d >> 16;
+	result[15] = ctx->d >> 24;
+
+	memset(ctx, 0, sizeof(*ctx));
+}
+
+#endif
diff --git a/src/base/md5.h b/src/base/md5.h
new file mode 100644
index 0000000..f1a6857
--- /dev/null
+++ b/src/base/md5.h
@@ -0,0 +1,45 @@
+/*
+ * This is an OpenSSL-compatible implementation of the RSA Data Security, Inc.
+ * MD5 Message-Digest Algorithm (RFC 1321).
+ *
+ * Homepage:
+ * http://openwall.info/wiki/people/solar/software/public-domain-source-code/md5
+ *
+ * Author:
+ * Alexander Peslyak, better known as Solar Designer <solar at openwall.com>
+ *
+ * This software was written by Alexander Peslyak in 2001.  No copyright is
+ * claimed, and the software is hereby placed in the public domain.
+ * In case this attempt to disclaim copyright and place the software in the
+ * public domain is deemed null and void, then the software is
+ * Copyright (c) 2001 Alexander Peslyak and it is hereby released to the
+ * general public under the following terms:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted.
+ *
+ * There's ABSOLUTELY NO WARRANTY, express or implied.
+ *
+ * See md5.c for more information.
+ */
+
+#ifdef HAVE_OPENSSL
+#include <openssl/md5.h>
+#elif !defined(_MD5_H)
+#define _MD5_H
+
+/* Any 32-bit or wider unsigned integer data type will do */
+typedef unsigned int MD5_u32plus;
+
+typedef struct {
+	MD5_u32plus lo, hi;
+	MD5_u32plus a, b, c, d;
+	unsigned char buffer[64];
+	MD5_u32plus block[16];
+} MD5_CTX;
+
+extern void MD5_Init(MD5_CTX *ctx);
+extern void MD5_Update(MD5_CTX *ctx, void *data, unsigned long size);
+extern void MD5_Final(unsigned char *result, MD5_CTX *ctx);
+
+#endif
diff --git a/src/cache/ftcbasic.c b/src/cache/ftcbasic.c
new file mode 100644
index 0000000..84d336d
--- /dev/null
+++ b/src/cache/ftcbasic.c
@@ -0,0 +1,602 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftcbasic.c                                                             */
+/*                                                                         */
+/*    The FreeType basic cache interface (body).                           */
+/*                                                                         */
+/*  Copyright 2003-2007, 2009-2011, 2013 by                                */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_DEBUG_H
+#include FT_CACHE_H
+#include "ftcglyph.h"
+#include "ftcimage.h"
+#include "ftcsbits.h"
+
+#include "ftccback.h"
+#include "ftcerror.h"
+
+#define FT_COMPONENT  trace_cache
+
+
+  /*
+   *  Basic Families
+   *
+   */
+  typedef struct  FTC_BasicAttrRec_
+  {
+    FTC_ScalerRec  scaler;
+    FT_UInt        load_flags;
+
+  } FTC_BasicAttrRec, *FTC_BasicAttrs;
+
+#define FTC_BASIC_ATTR_COMPARE( a, b )                                 \
+          FT_BOOL( FTC_SCALER_COMPARE( &(a)->scaler, &(b)->scaler ) && \
+                   (a)->load_flags == (b)->load_flags               )
+
+#define FTC_BASIC_ATTR_HASH( a )                                   \
+          ( FTC_SCALER_HASH( &(a)->scaler ) + 31*(a)->load_flags )
+
+
+  typedef struct  FTC_BasicQueryRec_
+  {
+    FTC_GQueryRec     gquery;
+    FTC_BasicAttrRec  attrs;
+
+  } FTC_BasicQueryRec, *FTC_BasicQuery;
+
+
+  typedef struct  FTC_BasicFamilyRec_
+  {
+    FTC_FamilyRec     family;
+    FTC_BasicAttrRec  attrs;
+
+  } FTC_BasicFamilyRec, *FTC_BasicFamily;
+
+
+  FT_CALLBACK_DEF( FT_Bool )
+  ftc_basic_family_compare( FTC_MruNode  ftcfamily,
+                            FT_Pointer   ftcquery )
+  {
+    FTC_BasicFamily  family = (FTC_BasicFamily)ftcfamily;
+    FTC_BasicQuery   query  = (FTC_BasicQuery)ftcquery;
+
+
+    return FTC_BASIC_ATTR_COMPARE( &family->attrs, &query->attrs );
+  }
+
+
+  FT_CALLBACK_DEF( FT_Error )
+  ftc_basic_family_init( FTC_MruNode  ftcfamily,
+                         FT_Pointer   ftcquery,
+                         FT_Pointer   ftccache )
+  {
+    FTC_BasicFamily  family = (FTC_BasicFamily)ftcfamily;
+    FTC_BasicQuery   query  = (FTC_BasicQuery)ftcquery;
+    FTC_Cache        cache  = (FTC_Cache)ftccache;
+
+
+    FTC_Family_Init( FTC_FAMILY( family ), cache );
+    family->attrs = query->attrs;
+    return 0;
+  }
+
+
+  FT_CALLBACK_DEF( FT_UInt )
+  ftc_basic_family_get_count( FTC_Family   ftcfamily,
+                              FTC_Manager  manager )
+  {
+    FTC_BasicFamily  family = (FTC_BasicFamily)ftcfamily;
+    FT_Error         error;
+    FT_Face          face;
+    FT_UInt          result = 0;
+
+
+    error = FTC_Manager_LookupFace( manager, family->attrs.scaler.face_id,
+                                    &face );
+
+    if ( error || !face )
+      return result;
+
+    if ( (FT_ULong)face->num_glyphs > FT_UINT_MAX || 0 > face->num_glyphs )
+    {
+      FT_TRACE1(( "ftc_basic_family_get_count: too large number of glyphs " ));
+      FT_TRACE1(( "in this face, truncated\n", face->num_glyphs ));
+    }
+
+    if ( !error )
+      result = (FT_UInt)face->num_glyphs;
+
+    return result;
+  }
+
+
+  FT_CALLBACK_DEF( FT_Error )
+  ftc_basic_family_load_bitmap( FTC_Family   ftcfamily,
+                                FT_UInt      gindex,
+                                FTC_Manager  manager,
+                                FT_Face     *aface )
+  {
+    FTC_BasicFamily  family = (FTC_BasicFamily)ftcfamily;
+    FT_Error         error;
+    FT_Size          size;
+
+
+    error = FTC_Manager_LookupSize( manager, &family->attrs.scaler, &size );
+    if ( !error )
+    {
+      FT_Face  face = size->face;
+
+
+      error = FT_Load_Glyph( face, gindex,
+                             family->attrs.load_flags | FT_LOAD_RENDER );
+      if ( !error )
+        *aface = face;
+    }
+
+    return error;
+  }
+
+
+  FT_CALLBACK_DEF( FT_Error )
+  ftc_basic_family_load_glyph( FTC_Family  ftcfamily,
+                               FT_UInt     gindex,
+                               FTC_Cache   cache,
+                               FT_Glyph   *aglyph )
+  {
+    FTC_BasicFamily  family = (FTC_BasicFamily)ftcfamily;
+    FT_Error         error;
+    FTC_Scaler       scaler = &family->attrs.scaler;
+    FT_Face          face;
+    FT_Size          size;
+
+
+    /* we will now load the glyph image */
+    error = FTC_Manager_LookupSize( cache->manager,
+                                    scaler,
+                                    &size );
+    if ( !error )
+    {
+      face = size->face;
+
+      error = FT_Load_Glyph( face, gindex, family->attrs.load_flags );
+      if ( !error )
+      {
+        if ( face->glyph->format == FT_GLYPH_FORMAT_BITMAP  ||
+             face->glyph->format == FT_GLYPH_FORMAT_OUTLINE )
+        {
+          /* ok, copy it */
+          FT_Glyph  glyph;
+
+
+          error = FT_Get_Glyph( face->glyph, &glyph );
+          if ( !error )
+          {
+            *aglyph = glyph;
+            goto Exit;
+          }
+        }
+        else
+          error = FT_THROW( Invalid_Argument );
+      }
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  FT_CALLBACK_DEF( FT_Bool )
+  ftc_basic_gnode_compare_faceid( FTC_Node    ftcgnode,
+                                  FT_Pointer  ftcface_id,
+                                  FTC_Cache   cache,
+                                  FT_Bool*    list_changed )
+  {
+    FTC_GNode        gnode   = (FTC_GNode)ftcgnode;
+    FTC_FaceID       face_id = (FTC_FaceID)ftcface_id;
+    FTC_BasicFamily  family  = (FTC_BasicFamily)gnode->family;
+    FT_Bool          result;
+
+
+    if ( list_changed )
+      *list_changed = FALSE;
+    result = FT_BOOL( family->attrs.scaler.face_id == face_id );
+    if ( result )
+    {
+      /* we must call this function to avoid this node from appearing
+       * in later lookups with the same face_id!
+       */
+      FTC_GNode_UnselectFamily( gnode, cache );
+    }
+    return result;
+  }
+
+
+ /*
+  *
+  * basic image cache
+  *
+  */
+
+  FT_CALLBACK_TABLE_DEF
+  const FTC_IFamilyClassRec  ftc_basic_image_family_class =
+  {
+    {
+      sizeof ( FTC_BasicFamilyRec ),
+      ftc_basic_family_compare,
+      ftc_basic_family_init,
+      0,                        /* FTC_MruNode_ResetFunc */
+      0                         /* FTC_MruNode_DoneFunc  */
+    },
+    ftc_basic_family_load_glyph
+  };
+
+
+  FT_CALLBACK_TABLE_DEF
+  const FTC_GCacheClassRec  ftc_basic_image_cache_class =
+  {
+    {
+      ftc_inode_new,
+      ftc_inode_weight,
+      ftc_gnode_compare,
+      ftc_basic_gnode_compare_faceid,
+      ftc_inode_free,
+
+      sizeof ( FTC_GCacheRec ),
+      ftc_gcache_init,
+      ftc_gcache_done
+    },
+    (FTC_MruListClass)&ftc_basic_image_family_class
+  };
+
+
+  /* documentation is in ftcache.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FTC_ImageCache_New( FTC_Manager      manager,
+                      FTC_ImageCache  *acache )
+  {
+    return FTC_GCache_New( manager, &ftc_basic_image_cache_class,
+                           (FTC_GCache*)acache );
+  }
+
+
+  /* documentation is in ftcache.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FTC_ImageCache_Lookup( FTC_ImageCache  cache,
+                         FTC_ImageType   type,
+                         FT_UInt         gindex,
+                         FT_Glyph       *aglyph,
+                         FTC_Node       *anode )
+  {
+    FTC_BasicQueryRec  query;
+    FTC_Node           node = 0; /* make compiler happy */
+    FT_Error           error;
+    FT_PtrDist         hash;
+
+
+    /* some argument checks are delayed to FTC_Cache_Lookup */
+    if ( !aglyph )
+    {
+      error = FT_THROW( Invalid_Argument );
+      goto Exit;
+    }
+
+    *aglyph = NULL;
+    if ( anode )
+      *anode  = NULL;
+
+    {
+      if ( (FT_ULong)(type->flags - FT_INT_MIN) > FT_UINT_MAX )
+      {
+        FT_TRACE1(( "FTC_ImageCache_Lookup: higher bits in load_flags" ));
+        FT_TRACE1(( "0x%x are dropped\n", (type->flags & ~((FT_ULong)FT_UINT_MAX)) ));
+      }
+
+      query.attrs.scaler.face_id = type->face_id;
+      query.attrs.scaler.width   = type->width;
+      query.attrs.scaler.height  = type->height;
+      query.attrs.load_flags     = (FT_UInt)type->flags;
+    }
+
+    query.attrs.scaler.pixel = 1;
+    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! */
+    FTC_GCACHE_LOOKUP_CMP( cache,
+                           ftc_basic_family_compare,
+                           FTC_GNode_Compare,
+                           hash, gindex,
+                           &query,
+                           node,
+                           error );
+#else
+    error = FTC_GCache_Lookup( FTC_GCACHE( cache ),
+                               hash, gindex,
+                               FTC_GQUERY( &query ),
+                               &node );
+#endif
+    if ( !error )
+    {
+      *aglyph = FTC_INODE( node )->glyph;
+
+      if ( anode )
+      {
+        *anode = node;
+        node->ref_count++;
+      }
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  /* documentation is in ftcache.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FTC_ImageCache_LookupScaler( FTC_ImageCache  cache,
+                               FTC_Scaler      scaler,
+                               FT_ULong        load_flags,
+                               FT_UInt         gindex,
+                               FT_Glyph       *aglyph,
+                               FTC_Node       *anode )
+  {
+    FTC_BasicQueryRec  query;
+    FTC_Node           node = 0; /* make compiler happy */
+    FT_Error           error;
+    FT_PtrDist         hash;
+
+
+    /* some argument checks are delayed to FTC_Cache_Lookup */
+    if ( !aglyph || !scaler )
+    {
+      error = FT_THROW( Invalid_Argument );
+      goto Exit;
+    }
+
+    *aglyph = NULL;
+    if ( anode )
+      *anode  = NULL;
+
+    /* FT_Load_Glyph(), FT_Load_Char() take FT_UInt flags */
+    if ( load_flags > FT_UINT_MAX )
+    {
+      FT_TRACE1(( "FTC_ImageCache_LookupScaler: higher bits in load_flags" ));
+      FT_TRACE1(( "0x%x are dropped\n", (load_flags & ~((FT_ULong)FT_UINT_MAX)) ));
+    }
+
+    query.attrs.scaler     = scaler[0];
+    query.attrs.load_flags = (FT_UInt)load_flags;
+
+    hash = FTC_BASIC_ATTR_HASH( &query.attrs ) + gindex;
+
+    FTC_GCACHE_LOOKUP_CMP( cache,
+                           ftc_basic_family_compare,
+                           FTC_GNode_Compare,
+                           hash, gindex,
+                           &query,
+                           node,
+                           error );
+    if ( !error )
+    {
+      *aglyph = FTC_INODE( node )->glyph;
+
+      if ( anode )
+      {
+        *anode = node;
+        node->ref_count++;
+      }
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  /*
+   *
+   * basic small bitmap cache
+   *
+   */
+
+  FT_CALLBACK_TABLE_DEF
+  const FTC_SFamilyClassRec  ftc_basic_sbit_family_class =
+  {
+    {
+      sizeof ( FTC_BasicFamilyRec ),
+      ftc_basic_family_compare,
+      ftc_basic_family_init,
+      0,                            /* FTC_MruNode_ResetFunc */
+      0                             /* FTC_MruNode_DoneFunc  */
+    },
+    ftc_basic_family_get_count,
+    ftc_basic_family_load_bitmap
+  };
+
+
+  FT_CALLBACK_TABLE_DEF
+  const FTC_GCacheClassRec  ftc_basic_sbit_cache_class =
+  {
+    {
+      ftc_snode_new,
+      ftc_snode_weight,
+      ftc_snode_compare,
+      ftc_basic_gnode_compare_faceid,
+      ftc_snode_free,
+
+      sizeof ( FTC_GCacheRec ),
+      ftc_gcache_init,
+      ftc_gcache_done
+    },
+    (FTC_MruListClass)&ftc_basic_sbit_family_class
+  };
+
+
+  /* documentation is in ftcache.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FTC_SBitCache_New( FTC_Manager     manager,
+                     FTC_SBitCache  *acache )
+  {
+    return FTC_GCache_New( manager, &ftc_basic_sbit_cache_class,
+                           (FTC_GCache*)acache );
+  }
+
+
+  /* documentation is in ftcache.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FTC_SBitCache_Lookup( FTC_SBitCache  cache,
+                        FTC_ImageType  type,
+                        FT_UInt        gindex,
+                        FTC_SBit      *ansbit,
+                        FTC_Node      *anode )
+  {
+    FT_Error           error;
+    FTC_BasicQueryRec  query;
+    FTC_Node           node = 0; /* make compiler happy */
+    FT_PtrDist         hash;
+
+
+    if ( anode )
+      *anode = NULL;
+
+    /* other argument checks delayed to FTC_Cache_Lookup */
+    if ( !ansbit )
+      return FT_THROW( Invalid_Argument );
+
+    *ansbit = NULL;
+
+    {
+      if ( (FT_ULong)(type->flags - FT_INT_MIN) > FT_UINT_MAX )
+      {
+        FT_TRACE1(( "FTC_ImageCache_Lookup: higher bits in load_flags" ));
+        FT_TRACE1(( "0x%x are dropped\n", (type->flags & ~((FT_ULong)FT_UINT_MAX)) ));
+      }
+
+      query.attrs.scaler.face_id = type->face_id;
+      query.attrs.scaler.width   = type->width;
+      query.attrs.scaler.height  = type->height;
+      query.attrs.load_flags     = (FT_UInt)type->flags;
+    }
+
+    query.attrs.scaler.pixel = 1;
+    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! */
+    FTC_GCACHE_LOOKUP_CMP( cache,
+                           ftc_basic_family_compare,
+                           FTC_SNode_Compare,
+                           hash, gindex,
+                           &query,
+                           node,
+                           error );
+#else
+    error = FTC_GCache_Lookup( FTC_GCACHE( cache ),
+                               hash,
+                               gindex,
+                               FTC_GQUERY( &query ),
+                               &node );
+#endif
+    if ( error )
+      goto Exit;
+
+    *ansbit = FTC_SNODE( node )->sbits +
+              ( gindex - FTC_GNODE( node )->gindex );
+
+    if ( anode )
+    {
+      *anode = node;
+      node->ref_count++;
+    }
+
+  Exit:
+    return error;
+  }
+
+
+  /* documentation is in ftcache.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FTC_SBitCache_LookupScaler( FTC_SBitCache  cache,
+                              FTC_Scaler     scaler,
+                              FT_ULong       load_flags,
+                              FT_UInt        gindex,
+                              FTC_SBit      *ansbit,
+                              FTC_Node      *anode )
+  {
+    FT_Error           error;
+    FTC_BasicQueryRec  query;
+    FTC_Node           node = 0; /* make compiler happy */
+    FT_PtrDist         hash;
+
+
+    if ( anode )
+        *anode = NULL;
+
+    /* other argument checks delayed to FTC_Cache_Lookup */
+    if ( !ansbit || !scaler )
+        return FT_THROW( Invalid_Argument );
+
+    *ansbit = NULL;
+
+    /* FT_Load_Glyph(), FT_Load_Char() take FT_UInt flags */
+    if ( load_flags > FT_UINT_MAX )
+    {
+      FT_TRACE1(( "FTC_ImageCache_LookupScaler: higher bits in load_flags" ));
+      FT_TRACE1(( "0x%x are dropped\n", (load_flags & ~((FT_ULong)FT_UINT_MAX)) ));
+    }
+
+    query.attrs.scaler     = scaler[0];
+    query.attrs.load_flags = (FT_UInt)load_flags;
+
+    /* beware, the hash must be the same for all glyph ranges! */
+    hash = FTC_BASIC_ATTR_HASH( &query.attrs ) +
+             gindex / FTC_SBIT_ITEMS_PER_NODE;
+
+    FTC_GCACHE_LOOKUP_CMP( cache,
+                           ftc_basic_family_compare,
+                           FTC_SNode_Compare,
+                           hash, gindex,
+                           &query,
+                           node,
+                           error );
+    if ( error )
+      goto Exit;
+
+    *ansbit = FTC_SNODE( node )->sbits +
+              ( gindex - FTC_GNODE( node )->gindex );
+
+    if ( anode )
+    {
+      *anode = node;
+      node->ref_count++;
+    }
+
+  Exit:
+    return error;
+  }
+
+
+/* END */
diff --git a/src/cache/ftccache.c b/src/cache/ftccache.c
new file mode 100644
index 0000000..f20dd45
--- /dev/null
+++ b/src/cache/ftccache.c
@@ -0,0 +1,621 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftccache.c                                                             */
+/*                                                                         */
+/*    The FreeType internal cache interface (body).                        */
+/*                                                                         */
+/*  Copyright 2000-2007, 2009-2011, 2013 by                                */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include "ftcmanag.h"
+#include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_DEBUG_H
+
+#include "ftccback.h"
+#include "ftcerror.h"
+
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_cache
+
+
+#define FTC_HASH_MAX_LOAD  2
+#define FTC_HASH_MIN_LOAD  1
+#define FTC_HASH_SUB_LOAD  ( FTC_HASH_MAX_LOAD - FTC_HASH_MIN_LOAD )
+
+  /* this one _must_ be a power of 2! */
+#define FTC_HASH_INITIAL_SIZE  8
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                   CACHE NODE DEFINITIONS                      *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  /* add a new node to the head of the manager's circular MRU list */
+  static void
+  ftc_node_mru_link( FTC_Node     node,
+                     FTC_Manager  manager )
+  {
+    void  *nl = &manager->nodes_list;
+
+
+    FTC_MruNode_Prepend( (FTC_MruNode*)nl,
+                         (FTC_MruNode)node );
+    manager->num_nodes++;
+  }
+
+
+  /* remove a node from the manager's MRU list */
+  static void
+  ftc_node_mru_unlink( FTC_Node     node,
+                       FTC_Manager  manager )
+  {
+    void  *nl = &manager->nodes_list;
+
+
+    FTC_MruNode_Remove( (FTC_MruNode*)nl,
+                        (FTC_MruNode)node );
+    manager->num_nodes--;
+  }
+
+
+#ifndef FTC_INLINE
+
+  /* move a node to the head of the manager's MRU list */
+  static void
+  ftc_node_mru_up( FTC_Node     node,
+                   FTC_Manager  manager )
+  {
+    FTC_MruNode_Up( (FTC_MruNode*)&manager->nodes_list,
+                    (FTC_MruNode)node );
+  }
+
+
+  /* get a top bucket for specified hash from cache,
+   * body for FTC_NODE__TOP_FOR_HASH( cache, hash )
+   */
+  FT_LOCAL_DEF( FTC_Node* )
+  ftc_get_top_node_for_hash( FTC_Cache   cache,
+                             FT_PtrDist  hash )
+  {
+    FTC_Node*  pnode;
+    FT_UInt    idx;
+
+
+    idx = (FT_UInt)( hash & cache->mask );
+    if ( idx < cache->p )
+      idx = (FT_UInt)( hash & ( 2 * cache->mask + 1 ) );
+    pnode = cache->buckets + idx;
+    return pnode;
+  }
+
+#endif /* !FTC_INLINE */
+
+
+  /* Note that this function cannot fail.  If we cannot re-size the
+   * buckets array appropriately, we simply degrade the hash table's
+   * performance!
+   */
+  static void
+  ftc_cache_resize( FTC_Cache  cache )
+  {
+    for (;;)
+    {
+      FTC_Node  node, *pnode;
+      FT_UFast  p     = cache->p;
+      FT_UFast  mask  = cache->mask;
+      FT_UFast  count = mask + p + 1;    /* number of buckets */
+
+
+      /* do we need to shrink the buckets array? */
+      if ( cache->slack < 0 )
+      {
+        FTC_Node  new_list = NULL;
+
+
+        /* try to expand the buckets array _before_ splitting
+         * the bucket lists
+         */
+        if ( p >= mask )
+        {
+          FT_Memory  memory = cache->memory;
+          FT_Error   error;
+
+
+          /* if we can't expand the array, leave immediately */
+          if ( FT_RENEW_ARRAY( cache->buckets,
+                               ( mask + 1 ) * 2, ( mask + 1 ) * 4 ) )
+            break;
+        }
+
+        /* split a single bucket */
+        pnode = cache->buckets + p;
+
+        for (;;)
+        {
+          node = *pnode;
+          if ( node == NULL )
+            break;
+
+          if ( node->hash & ( mask + 1 ) )
+          {
+            *pnode     = node->link;
+            node->link = new_list;
+            new_list   = node;
+          }
+          else
+            pnode = &node->link;
+        }
+
+        cache->buckets[p + mask + 1] = new_list;
+
+        cache->slack += FTC_HASH_MAX_LOAD;
+
+        if ( p >= mask )
+        {
+          cache->mask = 2 * mask + 1;
+          cache->p    = 0;
+        }
+        else
+          cache->p = p + 1;
+      }
+
+      /* do we need to expand the buckets array? */
+      else if ( cache->slack > (FT_Long)count * FTC_HASH_SUB_LOAD )
+      {
+        FT_UFast   old_index = p + mask;
+        FTC_Node*  pold;
+
+
+        if ( old_index + 1 <= FTC_HASH_INITIAL_SIZE )
+          break;
+
+        if ( p == 0 )
+        {
+          FT_Memory  memory = cache->memory;
+          FT_Error   error;
+
+
+          /* if we can't shrink the array, leave immediately */
+          if ( FT_RENEW_ARRAY( cache->buckets,
+                               ( mask + 1 ) * 2, mask + 1 ) )
+            break;
+
+          cache->mask >>= 1;
+          p             = cache->mask;
+        }
+        else
+          p--;
+
+        pnode = cache->buckets + p;
+        while ( *pnode )
+          pnode = &(*pnode)->link;
+
+        pold   = cache->buckets + old_index;
+        *pnode = *pold;
+        *pold  = NULL;
+
+        cache->slack -= FTC_HASH_MAX_LOAD;
+        cache->p      = p;
+      }
+
+      /* otherwise, the hash table is balanced */
+      else
+        break;
+    }
+  }
+
+
+  /* remove a node from its cache's hash table */
+  static void
+  ftc_node_hash_unlink( FTC_Node   node0,
+                        FTC_Cache  cache )
+  {
+    FTC_Node  *pnode = FTC_NODE__TOP_FOR_HASH( cache, node0->hash );
+
+
+    for (;;)
+    {
+      FTC_Node  node = *pnode;
+
+
+      if ( node == NULL )
+      {
+        FT_TRACE0(( "ftc_node_hash_unlink: unknown node\n" ));
+        return;
+      }
+
+      if ( node == node0 )
+        break;
+
+      pnode = &(*pnode)->link;
+    }
+
+    *pnode      = node0->link;
+    node0->link = NULL;
+
+    cache->slack++;
+    ftc_cache_resize( cache );
+  }
+
+
+  /* add a node to the `top' of its cache's hash table */
+  static void
+  ftc_node_hash_link( FTC_Node   node,
+                      FTC_Cache  cache )
+  {
+    FTC_Node  *pnode = FTC_NODE__TOP_FOR_HASH( cache, node->hash );
+
+
+    node->link = *pnode;
+    *pnode     = node;
+
+    cache->slack--;
+    ftc_cache_resize( cache );
+  }
+
+
+  /* remove a node from the cache manager */
+  FT_LOCAL_DEF( void )
+  ftc_node_destroy( FTC_Node     node,
+                    FTC_Manager  manager )
+  {
+    FTC_Cache  cache;
+
+
+#ifdef FT_DEBUG_ERROR
+    /* find node's cache */
+    if ( node->cache_index >= manager->num_caches )
+    {
+      FT_TRACE0(( "ftc_node_destroy: invalid node handle\n" ));
+      return;
+    }
+#endif
+
+    cache = manager->caches[node->cache_index];
+
+#ifdef FT_DEBUG_ERROR
+    if ( cache == NULL )
+    {
+      FT_TRACE0(( "ftc_node_destroy: invalid node handle\n" ));
+      return;
+    }
+#endif
+
+    manager->cur_weight -= cache->clazz.node_weight( node, cache );
+
+    /* remove node from mru list */
+    ftc_node_mru_unlink( node, manager );
+
+    /* remove node from cache's hash table */
+    ftc_node_hash_unlink( node, cache );
+
+    /* now finalize it */
+    cache->clazz.node_free( node, cache );
+
+#if 0
+    /* check, just in case of general corruption :-) */
+    if ( manager->num_nodes == 0 )
+      FT_TRACE0(( "ftc_node_destroy: invalid cache node count (%d)\n",
+                  manager->num_nodes ));
+#endif
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                    ABSTRACT CACHE CLASS                       *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  FT_LOCAL_DEF( FT_Error )
+  FTC_Cache_Init( FTC_Cache  cache )
+  {
+    return ftc_cache_init( cache );
+  }
+
+
+  FT_LOCAL_DEF( FT_Error )
+  ftc_cache_init( FTC_Cache  cache )
+  {
+    FT_Memory  memory = cache->memory;
+    FT_Error   error;
+
+
+    cache->p     = 0;
+    cache->mask  = FTC_HASH_INITIAL_SIZE - 1;
+    cache->slack = FTC_HASH_INITIAL_SIZE * FTC_HASH_MAX_LOAD;
+
+    (void)FT_NEW_ARRAY( cache->buckets, FTC_HASH_INITIAL_SIZE * 2 );
+    return error;
+  }
+
+
+  static void
+  FTC_Cache_Clear( FTC_Cache  cache )
+  {
+    if ( cache && cache->buckets )
+    {
+      FTC_Manager  manager = cache->manager;
+      FT_UFast     i;
+      FT_UFast     count;
+
+
+      count = cache->p + cache->mask + 1;
+
+      for ( i = 0; i < count; i++ )
+      {
+        FTC_Node  *pnode = cache->buckets + i, next, node = *pnode;
+
+
+        while ( node )
+        {
+          next        = node->link;
+          node->link  = NULL;
+
+          /* remove node from mru list */
+          ftc_node_mru_unlink( node, manager );
+
+          /* now finalize it */
+          manager->cur_weight -= cache->clazz.node_weight( node, cache );
+
+          cache->clazz.node_free( node, cache );
+          node = next;
+        }
+        cache->buckets[i] = NULL;
+      }
+      ftc_cache_resize( cache );
+    }
+  }
+
+
+  FT_LOCAL_DEF( void )
+  ftc_cache_done( FTC_Cache  cache )
+  {
+    if ( cache->memory )
+    {
+      FT_Memory  memory = cache->memory;
+
+
+      FTC_Cache_Clear( cache );
+
+      FT_FREE( cache->buckets );
+      cache->mask  = 0;
+      cache->p     = 0;
+      cache->slack = 0;
+
+      cache->memory = NULL;
+    }
+  }
+
+
+  FT_LOCAL_DEF( void )
+  FTC_Cache_Done( FTC_Cache  cache )
+  {
+    ftc_cache_done( cache );
+  }
+
+
+  static void
+  ftc_cache_add( FTC_Cache  cache,
+                 FT_PtrDist hash,
+                 FTC_Node   node )
+  {
+    node->hash        = hash;
+    node->cache_index = (FT_UInt16)cache->index;
+    node->ref_count   = 0;
+
+    ftc_node_hash_link( node, cache );
+    ftc_node_mru_link( node, cache->manager );
+
+    {
+      FTC_Manager  manager = cache->manager;
+
+
+      manager->cur_weight += cache->clazz.node_weight( node, cache );
+
+      if ( manager->cur_weight >= manager->max_weight )
+      {
+        node->ref_count++;
+        FTC_Manager_Compress( manager );
+        node->ref_count--;
+      }
+    }
+  }
+
+
+  FT_LOCAL_DEF( FT_Error )
+  FTC_Cache_NewNode( FTC_Cache   cache,
+                     FT_PtrDist  hash,
+                     FT_Pointer  query,
+                     FTC_Node   *anode )
+  {
+    FT_Error  error;
+    FTC_Node  node;
+
+
+    /*
+     * We use the FTC_CACHE_TRYLOOP macros to support out-of-memory
+     * errors (OOM) correctly, i.e., by flushing the cache progressively
+     * in order to make more room.
+     */
+
+    FTC_CACHE_TRYLOOP( cache )
+    {
+      error = cache->clazz.node_new( &node, query, cache );
+    }
+    FTC_CACHE_TRYLOOP_END( NULL );
+
+    if ( error )
+      node = NULL;
+    else
+    {
+     /* don't assume that the cache has the same number of buckets, since
+      * our allocation request might have triggered global cache flushing
+      */
+      ftc_cache_add( cache, hash, node );
+    }
+
+    *anode = node;
+    return error;
+  }
+
+
+#ifndef FTC_INLINE
+
+  FT_LOCAL_DEF( FT_Error )
+  FTC_Cache_Lookup( FTC_Cache   cache,
+                    FT_PtrDist  hash,
+                    FT_Pointer  query,
+                    FTC_Node   *anode )
+  {
+    FTC_Node*  bucket;
+    FTC_Node*  pnode;
+    FTC_Node   node;
+    FT_Error   error        = FT_Err_Ok;
+    FT_Bool    list_changed = FALSE;
+
+    FTC_Node_CompareFunc  compare = cache->clazz.node_compare;
+
+
+    if ( cache == NULL || anode == NULL )
+      return FT_THROW( Invalid_Argument );
+
+    /* Go to the `top' node of the list sharing same masked hash */
+    bucket = pnode = FTC_NODE__TOP_FOR_HASH( cache, hash );
+
+    /* Lookup a node with exactly same hash and queried properties.  */
+    /* NOTE: _nodcomp() may change the linked list to reduce memory. */
+    for (;;)
+    {
+      node = *pnode;
+      if ( node == NULL )
+        goto NewNode;
+
+      if ( node->hash == hash                           &&
+           compare( node, query, cache, &list_changed ) )
+        break;
+
+      pnode = &node->link;
+    }
+
+    if ( list_changed )
+    {
+      /* Update bucket by modified linked list */
+      bucket = pnode = FTC_NODE__TOP_FOR_HASH( cache, hash );
+
+      /* Update pnode by modified linked list */
+      while ( *pnode != node )
+      {
+        if ( *pnode == NULL )
+        {
+          FT_ERROR(( "FTC_Cache_Lookup: oops!!!  node missing\n" ));
+          goto NewNode;
+        }
+        else
+          pnode = &((*pnode)->link);
+      }
+    }
+
+    /* Reorder the list to move the found node to the `top' */
+    if ( node != *bucket )
+    {
+      *pnode     = node->link;
+      node->link = *bucket;
+      *bucket    = node;
+    }
+
+    /* move to head of MRU list */
+    {
+      FTC_Manager  manager = cache->manager;
+
+
+      if ( node != manager->nodes_list )
+        ftc_node_mru_up( node, manager );
+    }
+    *anode = node;
+
+    return error;
+
+  NewNode:
+    return FTC_Cache_NewNode( cache, hash, query, anode );
+  }
+
+#endif /* !FTC_INLINE */
+
+
+  FT_LOCAL_DEF( void )
+  FTC_Cache_RemoveFaceID( FTC_Cache   cache,
+                          FTC_FaceID  face_id )
+  {
+    FT_UFast     i, count;
+    FTC_Manager  manager = cache->manager;
+    FTC_Node     frees   = NULL;
+
+
+    count = cache->p + cache->mask + 1;
+    for ( i = 0; i < count; i++ )
+    {
+      FTC_Node*  bucket = cache->buckets + i;
+      FTC_Node*  pnode  = bucket;
+
+
+      for ( ;; )
+      {
+        FTC_Node  node = *pnode;
+        FT_Bool   list_changed = FALSE;
+
+
+        if ( node == NULL )
+          break;
+
+        if ( cache->clazz.node_remove_faceid( node, face_id,
+                                              cache, &list_changed ) )
+        {
+          *pnode     = node->link;
+          node->link = frees;
+          frees      = node;
+        }
+        else
+          pnode = &node->link;
+      }
+    }
+
+    /* remove all nodes in the free list */
+    while ( frees )
+    {
+      FTC_Node  node;
+
+
+      node  = frees;
+      frees = node->link;
+
+      manager->cur_weight -= cache->clazz.node_weight( node, cache );
+      ftc_node_mru_unlink( node, manager );
+
+      cache->clazz.node_free( node, cache );
+
+      cache->slack++;
+    }
+
+    ftc_cache_resize( cache );
+  }
+
+
+/* END */
diff --git a/src/cache/ftccache.h b/src/cache/ftccache.h
new file mode 100644
index 0000000..4155f32
--- /dev/null
+++ b/src/cache/ftccache.h
@@ -0,0 +1,352 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftccache.h                                                             */
+/*                                                                         */
+/*    FreeType internal cache interface (specification).                   */
+/*                                                                         */
+/*  Copyright 2000-2007, 2009-2011, 2013 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 "ftcmru.h"
+
+FT_BEGIN_HEADER
+
+#define _FTC_FACE_ID_HASH( i )                                                \
+          ((FT_PtrDist)(( (FT_PtrDist)(i) >> 3 ) ^ ( (FT_PtrDist)(i) << 7 )))
+
+  /* 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_PtrDist      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 )
+
+#ifdef FTC_INLINE
+#define FTC_NODE__TOP_FOR_HASH( cache, hash )                     \
+        ( ( cache )->buckets +                                    \
+            ( ( ( ( hash ) &   ( cache )->mask ) < ( cache )->p ) \
+              ? ( ( hash ) & ( ( cache )->mask * 2 + 1 ) )        \
+              : ( ( hash ) &   ( cache )->mask ) ) )
+#else
+  FT_LOCAL( FTC_Node* )
+  ftc_get_top_node_for_hash( FTC_Cache   cache,
+                             FT_PtrDist  hash );
+#define FTC_NODE__TOP_FOR_HASH( cache, hash )            \
+        ftc_get_top_node_for_hash( ( cache ), ( hash ) )
+#endif
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                       CACHE DEFINITIONS                       *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  /* initialize a new cache node */
+  typedef FT_Error
+  (*FTC_Node_NewFunc)( FTC_Node    *pnode,
+                       FT_Pointer   query,
+                       FTC_Cache    cache );
+
+  typedef FT_Offset
+  (*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,
+                           FT_Bool*    list_changed );
+
+
+  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_Offset             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_LOCAL( FT_Error )
+  FTC_Cache_Init( FTC_Cache  cache );
+
+  /* default cache finalizer */
+  FT_LOCAL( void )
+  FTC_Cache_Done( FTC_Cache  cache );
+
+  /* Call this function to look up 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.
+   */
+
+#ifndef FTC_INLINE
+  FT_LOCAL( FT_Error )
+  FTC_Cache_Lookup( FTC_Cache   cache,
+                    FT_PtrDist  hash,
+                    FT_Pointer  query,
+                    FTC_Node   *anode );
+#endif
+
+  FT_LOCAL( FT_Error )
+  FTC_Cache_NewNode( FTC_Cache   cache,
+                     FT_PtrDist  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_LOCAL( 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_PtrDist            _hash    = (FT_PtrDist)(hash);                 \
+    FTC_Node_CompareFunc  _nodcomp = (FTC_Node_CompareFunc)(nodecmp);    \
+    FT_Bool               _list_changed = FALSE;                         \
+                                                                         \
+                                                                         \
+    error = FT_Err_Ok;                                                   \
+    node  = NULL;                                                        \
+                                                                         \
+    /* Go to the `top' node of the list sharing same masked hash */      \
+    _bucket = _pnode = FTC_NODE__TOP_FOR_HASH( _cache, _hash );          \
+                                                                         \
+    /* Look up a node with identical hash and queried properties.    */  \
+    /* NOTE: _nodcomp() may change the linked list to reduce memory. */  \
+    for (;;)                                                             \
+    {                                                                    \
+      _node = *_pnode;                                                   \
+      if ( _node == NULL )                                               \
+        goto _NewNode;                                                   \
+                                                                         \
+      if ( _node->hash == _hash                             &&           \
+           _nodcomp( _node, query, _cache, &_list_changed ) )            \
+        break;                                                           \
+                                                                         \
+      _pnode = &_node->link;                                             \
+    }                                                                    \
+                                                                         \
+    if ( _list_changed )                                                 \
+    {                                                                    \
+      /* Update _bucket by possibly modified linked list */              \
+      _bucket = _pnode = FTC_NODE__TOP_FOR_HASH( _cache, _hash );        \
+                                                                         \
+      /* Update _pnode by possibly modified linked list */               \
+      while ( *_pnode != _node )                                         \
+      {                                                                  \
+        if ( *_pnode == NULL )                                           \
+        {                                                                \
+          FT_ERROR(( "FTC_CACHE_LOOKUP_CMP: oops!!! node missing\n" ));  \
+          goto _NewNode;                                                 \
+        }                                                                \
+        else                                                             \
+          _pnode = &((*_pnode)->link);                                   \
+      }                                                                  \
+    }                                                                    \
+                                                                         \
+    /* Reorder the list to move the found node to the `top' */           \
+    if ( _node != *_bucket )                                             \
+    {                                                                    \
+      *_pnode     = _node->link;                                         \
+      _node->link = *_bucket;                                            \
+      *_bucket    = _node;                                               \
+    }                                                                    \
+                                                                         \
+    /* Update MRU list */                                                \
+    {                                                                    \
+      FTC_Manager  _manager = _cache->manager;                           \
+      void*        _nl      = &_manager->nodes_list;                     \
+                                                                         \
+                                                                         \
+      if ( _node != _manager->nodes_list )                               \
+        FTC_MruNode_Up( (FTC_MruNode*)_nl,                               \
+                        (FTC_MruNode)_node );                            \
+    }                                                                    \
+    goto _Ok;                                                            \
+                                                                         \
+  _NewNode:                                                              \
+    error = FTC_Cache_NewNode( _cache, _hash, query, &_node );           \
+                                                                         \
+  _Ok:                                                                   \
+    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 */
+
+
+  /*
+   * This macro, together with FTC_CACHE_TRYLOOP_END, defines a retry
+   * loop to flush the cache repeatedly in case of memory overflows.
+   *
+   * It is used when creating a new cache node, or within a lookup
+   * that needs to allocate data (e.g. the sbit cache lookup).
+   *
+   * Example:
+   *
+   *   {
+   *     FTC_CACHE_TRYLOOP( cache )
+   *       error = load_data( ... );
+   *     FTC_CACHE_TRYLOOP_END()
+   *   }
+   *
+   */
+#define FTC_CACHE_TRYLOOP( cache )                           \
+  {                                                          \
+    FTC_Manager  _try_manager = FTC_CACHE( cache )->manager; \
+    FT_UInt      _try_count   = 4;                           \
+                                                             \
+                                                             \
+    for (;;)                                                 \
+    {                                                        \
+      FT_UInt  _try_done;
+
+
+#define FTC_CACHE_TRYLOOP_END( list_changed )                     \
+      if ( !error || FT_ERR_NEQ( error, Out_Of_Memory ) )         \
+        break;                                                    \
+                                                                  \
+      _try_done = FTC_Manager_FlushN( _try_manager, _try_count ); \
+      if ( _try_done > 0 && ( list_changed ) )                    \
+        *(FT_Bool*)( list_changed ) = TRUE;                       \
+                                                                  \
+      if ( _try_done == 0 )                                       \
+        break;                                                    \
+                                                                  \
+      if ( _try_done == _try_count )                              \
+      {                                                           \
+        _try_count *= 2;                                          \
+        if ( _try_count < _try_done              ||               \
+            _try_count > _try_manager->num_nodes )                \
+          _try_count = _try_manager->num_nodes;                   \
+      }                                                           \
+    }                                                             \
+  }
+
+ /* */
+
+FT_END_HEADER
+
+
+#endif /* __FTCCACHE_H__ */
+
+
+/* END */
diff --git a/src/cache/ftccback.h b/src/cache/ftccback.h
new file mode 100644
index 0000000..9528279
--- /dev/null
+++ b/src/cache/ftccback.h
@@ -0,0 +1,91 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftccback.h                                                             */
+/*                                                                         */
+/*    Callback functions of the caching sub-system (specification only).   */
+/*                                                                         */
+/*  Copyright 2004-2006, 2011, 2013 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 __FTCCBACK_H__
+#define __FTCCBACK_H__
+
+#include <ft2build.h>
+#include FT_CACHE_H
+#include "ftcmru.h"
+#include "ftcimage.h"
+#include "ftcmanag.h"
+#include "ftcglyph.h"
+#include "ftcsbits.h"
+
+
+  FT_LOCAL( void )
+  ftc_inode_free( FTC_Node   inode,
+                  FTC_Cache  cache );
+
+  FT_LOCAL( FT_Error )
+  ftc_inode_new( FTC_Node   *pinode,
+                 FT_Pointer  gquery,
+                 FTC_Cache   cache );
+
+  FT_LOCAL( FT_Offset )
+  ftc_inode_weight( FTC_Node   inode,
+                    FTC_Cache  cache );
+
+
+  FT_LOCAL( void )
+  ftc_snode_free( FTC_Node   snode,
+                  FTC_Cache  cache );
+
+  FT_LOCAL( FT_Error )
+  ftc_snode_new( FTC_Node   *psnode,
+                 FT_Pointer  gquery,
+                 FTC_Cache   cache );
+
+  FT_LOCAL( FT_Offset )
+  ftc_snode_weight( FTC_Node   snode,
+                    FTC_Cache  cache );
+
+  FT_LOCAL( FT_Bool )
+  ftc_snode_compare( FTC_Node    snode,
+                     FT_Pointer  gquery,
+                     FTC_Cache   cache,
+                     FT_Bool*    list_changed );
+
+
+  FT_LOCAL( FT_Bool )
+  ftc_gnode_compare( FTC_Node    gnode,
+                     FT_Pointer  gquery,
+                     FTC_Cache   cache,
+                     FT_Bool*    list_changed );
+
+
+  FT_LOCAL( FT_Error )
+  ftc_gcache_init( FTC_Cache  cache );
+
+  FT_LOCAL( void )
+  ftc_gcache_done( FTC_Cache  cache );
+
+
+  FT_LOCAL( FT_Error )
+  ftc_cache_init( FTC_Cache  cache );
+
+  FT_LOCAL( void )
+  ftc_cache_done( FTC_Cache  cache );
+
+  FT_LOCAL( void )
+  ftc_node_destroy( FTC_Node     node,
+                    FTC_Manager  manager );
+
+
+#endif /* __FTCCBACK_H__ */
+
+/* END */
diff --git a/src/cache/ftccmap.c b/src/cache/ftccmap.c
new file mode 100644
index 0000000..848349b
--- /dev/null
+++ b/src/cache/ftccmap.c
@@ -0,0 +1,337 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftccmap.c                                                              */
+/*                                                                         */
+/*    FreeType CharMap cache (body)                                        */
+/*                                                                         */
+/*  Copyright 2000-2013 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_CACHE_H
+#include "ftcmanag.h"
+#include FT_INTERNAL_MEMORY_H
+#include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_DEBUG_H
+
+#include "ftccback.h"
+#include "ftcerror.h"
+
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_cache
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Each FTC_CMapNode contains a simple array to map a range of character */
+  /* codes to equivalent glyph indices.                                    */
+  /*                                                                       */
+  /* For now, the implementation is very basic: Each node maps a range of  */
+  /* 128 consecutive character codes to their corresponding glyph indices. */
+  /*                                                                       */
+  /* We could do more complex things, but I don't think it is really very  */
+  /* useful.                                                               */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /* number of glyph indices / character code per node */
+#define FTC_CMAP_INDICES_MAX  128
+
+  /* compute a query/node hash */
+#define FTC_CMAP_HASH( faceid, index, charcode )         \
+          ( _FTC_FACE_ID_HASH( faceid ) + 211 * (index) + \
+            ( (charcode) / FTC_CMAP_INDICES_MAX )      )
+
+  /* the charmap query */
+  typedef struct  FTC_CMapQueryRec_
+  {
+    FTC_FaceID  face_id;
+    FT_UInt     cmap_index;
+    FT_UInt32   char_code;
+
+  } FTC_CMapQueryRec, *FTC_CMapQuery;
+
+#define FTC_CMAP_QUERY( x )  ((FTC_CMapQuery)(x))
+#define FTC_CMAP_QUERY_HASH( x )                                         \
+          FTC_CMAP_HASH( (x)->face_id, (x)->cmap_index, (x)->char_code )
+
+  /* the cmap cache node */
+  typedef struct  FTC_CMapNodeRec_
+  {
+    FTC_NodeRec  node;
+    FTC_FaceID   face_id;
+    FT_UInt      cmap_index;
+    FT_UInt32    first;                         /* first character in node */
+    FT_UInt16    indices[FTC_CMAP_INDICES_MAX]; /* array of glyph indices  */
+
+  } FTC_CMapNodeRec, *FTC_CMapNode;
+
+#define FTC_CMAP_NODE( x ) ( (FTC_CMapNode)( x ) )
+#define FTC_CMAP_NODE_HASH( x )                                      \
+          FTC_CMAP_HASH( (x)->face_id, (x)->cmap_index, (x)->first )
+
+  /* if (indices[n] == FTC_CMAP_UNKNOWN), we assume that the corresponding */
+  /* glyph indices haven't been queried through FT_Get_Glyph_Index() yet   */
+#define FTC_CMAP_UNKNOWN  (FT_UInt16)~0
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                        CHARMAP NODES                          *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  FT_CALLBACK_DEF( void )
+  ftc_cmap_node_free( FTC_Node   ftcnode,
+                      FTC_Cache  cache )
+  {
+    FTC_CMapNode  node   = (FTC_CMapNode)ftcnode;
+    FT_Memory     memory = cache->memory;
+
+
+    FT_FREE( node );
+  }
+
+
+  /* initialize a new cmap node */
+  FT_CALLBACK_DEF( FT_Error )
+  ftc_cmap_node_new( FTC_Node   *ftcanode,
+                     FT_Pointer  ftcquery,
+                     FTC_Cache   cache )
+  {
+    FTC_CMapNode  *anode  = (FTC_CMapNode*)ftcanode;
+    FTC_CMapQuery  query  = (FTC_CMapQuery)ftcquery;
+    FT_Error       error;
+    FT_Memory      memory = cache->memory;
+    FTC_CMapNode   node   = NULL;
+    FT_UInt        nn;
+
+
+    if ( !FT_NEW( node ) )
+    {
+      node->face_id    = query->face_id;
+      node->cmap_index = query->cmap_index;
+      node->first      = (query->char_code / FTC_CMAP_INDICES_MAX) *
+                         FTC_CMAP_INDICES_MAX;
+
+      for ( nn = 0; nn < FTC_CMAP_INDICES_MAX; nn++ )
+        node->indices[nn] = FTC_CMAP_UNKNOWN;
+    }
+
+    *anode = node;
+    return error;
+  }
+
+
+  /* compute the weight of a given cmap node */
+  FT_CALLBACK_DEF( FT_Offset )
+  ftc_cmap_node_weight( FTC_Node   cnode,
+                        FTC_Cache  cache )
+  {
+    FT_UNUSED( cnode );
+    FT_UNUSED( cache );
+
+    return sizeof ( *cnode );
+  }
+
+
+  /* compare a cmap node to a given query */
+  FT_CALLBACK_DEF( FT_Bool )
+  ftc_cmap_node_compare( FTC_Node    ftcnode,
+                         FT_Pointer  ftcquery,
+                         FTC_Cache   cache,
+                         FT_Bool*    list_changed )
+  {
+    FTC_CMapNode   node  = (FTC_CMapNode)ftcnode;
+    FTC_CMapQuery  query = (FTC_CMapQuery)ftcquery;
+    FT_UNUSED( cache );
+
+
+    if ( list_changed )
+      *list_changed = FALSE;
+    if ( node->face_id    == query->face_id    &&
+         node->cmap_index == query->cmap_index )
+    {
+      FT_UInt32  offset = (FT_UInt32)( query->char_code - node->first );
+
+
+      return FT_BOOL( offset < FTC_CMAP_INDICES_MAX );
+    }
+
+    return 0;
+  }
+
+
+  FT_CALLBACK_DEF( FT_Bool )
+  ftc_cmap_node_remove_faceid( FTC_Node    ftcnode,
+                               FT_Pointer  ftcface_id,
+                               FTC_Cache   cache,
+                               FT_Bool*    list_changed )
+  {
+    FTC_CMapNode  node    = (FTC_CMapNode)ftcnode;
+    FTC_FaceID    face_id = (FTC_FaceID)ftcface_id;
+    FT_UNUSED( cache );
+
+
+    if ( list_changed )
+      *list_changed = FALSE;
+    return FT_BOOL( node->face_id == face_id );
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                    GLYPH IMAGE CACHE                          *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  FT_CALLBACK_TABLE_DEF
+  const FTC_CacheClassRec  ftc_cmap_cache_class =
+  {
+    ftc_cmap_node_new,
+    ftc_cmap_node_weight,
+    ftc_cmap_node_compare,
+    ftc_cmap_node_remove_faceid,
+    ftc_cmap_node_free,
+
+    sizeof ( FTC_CacheRec ),
+    ftc_cache_init,
+    ftc_cache_done,
+  };
+
+
+  /* documentation is in ftcache.h */
+
+  FT_EXPORT_DEF( FT_Error )
+  FTC_CMapCache_New( FTC_Manager     manager,
+                     FTC_CMapCache  *acache )
+  {
+    return FTC_Manager_RegisterCache( manager,
+                                      &ftc_cmap_cache_class,
+                                      FTC_CACHE_P( acache ) );
+  }
+
+
+  /* documentation is in ftcache.h */
+
+  FT_EXPORT_DEF( FT_UInt )
+  FTC_CMapCache_Lookup( FTC_CMapCache  cmap_cache,
+                        FTC_FaceID     face_id,
+                        FT_Int         cmap_index,
+                        FT_UInt32      char_code )
+  {
+    FTC_Cache         cache = FTC_CACHE( cmap_cache );
+    FTC_CMapQueryRec  query;
+    FTC_Node          node;
+    FT_Error          error;
+    FT_UInt           gindex = 0;
+    FT_PtrDist        hash;
+    FT_Int            no_cmap_change = 0;
+
+
+    if ( cmap_index < 0 )
+    {
+      /* Treat a negative cmap index as a special value, meaning that you */
+      /* don't want to change the FT_Face's character map through this    */
+      /* call.  This can be useful if the face requester callback already */
+      /* sets the face's charmap to the appropriate value.                */
+
+      no_cmap_change = 1;
+      cmap_index     = 0;
+    }
+
+    if ( !cache )
+    {
+      FT_TRACE0(( "FTC_CMapCache_Lookup: bad arguments, returning 0\n" ));
+      return 0;
+    }
+
+    query.face_id    = face_id;
+    query.cmap_index = (FT_UInt)cmap_index;
+    query.char_code  = char_code;
+
+    hash = FTC_CMAP_HASH( face_id, cmap_index, char_code );
+
+#if 1
+    FTC_CACHE_LOOKUP_CMP( cache, ftc_cmap_node_compare, hash, &query,
+                          node, error );
+#else
+    error = FTC_Cache_Lookup( cache, hash, &query, &node );
+#endif
+    if ( error )
+      goto Exit;
+
+    FT_ASSERT( (FT_UInt)( char_code - FTC_CMAP_NODE( node )->first ) <
+                FTC_CMAP_INDICES_MAX );
+
+    /* something rotten can happen with rogue clients */
+    if ( (FT_UInt)( char_code - FTC_CMAP_NODE( node )->first >=
+                    FTC_CMAP_INDICES_MAX ) )
+      return 0; /* XXX: should return appropriate error */
+
+    gindex = FTC_CMAP_NODE( node )->indices[char_code -
+                                            FTC_CMAP_NODE( node )->first];
+    if ( gindex == FTC_CMAP_UNKNOWN )
+    {
+      FT_Face  face;
+
+
+      gindex = 0;
+
+      error = FTC_Manager_LookupFace( cache->manager,
+                                      FTC_CMAP_NODE( node )->face_id,
+                                      &face );
+      if ( error )
+        goto Exit;
+
+#ifdef FT_MAX_CHARMAP_CACHEABLE
+      /* something rotten can happen with rogue clients */
+      if ( cmap_index > FT_MAX_CHARMAP_CACHEABLE )
+        return 0; /* XXX: should return appropriate error */
+#endif
+
+      if ( (FT_UInt)cmap_index < (FT_UInt)face->num_charmaps )
+      {
+        FT_CharMap  old, cmap  = NULL;
+
+
+        old  = face->charmap;
+        cmap = face->charmaps[cmap_index];
+
+        if ( old != cmap && !no_cmap_change )
+          FT_Set_Charmap( face, cmap );
+
+        gindex = FT_Get_Char_Index( face, char_code );
+
+        if ( old != cmap && !no_cmap_change )
+          FT_Set_Charmap( face, old );
+      }
+
+      FTC_CMAP_NODE( node )->indices[char_code -
+                                     FTC_CMAP_NODE( node )->first]
+        = (FT_UShort)gindex;
+    }
+
+  Exit:
+    return gindex;
+  }
+
+
+/* END */
diff --git a/src/cache/ftcglyph.c b/src/cache/ftcglyph.c
new file mode 100644
index 0000000..441e177
--- /dev/null
+++ b/src/cache/ftcglyph.c
@@ -0,0 +1,219 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftcglyph.c                                                             */
+/*                                                                         */
+/*    FreeType Glyph Image (FT_Glyph) cache (body).                        */
+/*                                                                         */
+/*  Copyright 2000-2001, 2003, 2004, 2006, 2009, 2011 by                   */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_OBJECTS_H
+#include FT_CACHE_H
+#include "ftcglyph.h"
+#include FT_ERRORS_H
+
+#include "ftccback.h"
+#include "ftcerror.h"
+
+
+  /* create a new chunk node, setting its cache index and ref count */
+  FT_LOCAL_DEF( void )
+  FTC_GNode_Init( FTC_GNode   gnode,
+                  FT_UInt     gindex,
+                  FTC_Family  family )
+  {
+    gnode->family = family;
+    gnode->gindex = gindex;
+    family->num_nodes++;
+  }
+
+
+  FT_LOCAL_DEF( void )
+  FTC_GNode_UnselectFamily( FTC_GNode  gnode,
+                            FTC_Cache  cache )
+  {
+    FTC_Family  family = gnode->family;
+
+
+    gnode->family = NULL;
+    if ( family && --family->num_nodes == 0 )
+      FTC_FAMILY_FREE( family, cache );
+  }
+
+
+  FT_LOCAL_DEF( void )
+  FTC_GNode_Done( FTC_GNode  gnode,
+                  FTC_Cache  cache )
+  {
+    /* finalize the node */
+    gnode->gindex = 0;
+
+    FTC_GNode_UnselectFamily( gnode, cache );
+  }
+
+
+  FT_LOCAL_DEF( FT_Bool )
+  ftc_gnode_compare( FTC_Node    ftcgnode,
+                     FT_Pointer  ftcgquery,
+                     FTC_Cache   cache,
+                     FT_Bool*    list_changed )
+  {
+    FTC_GNode   gnode  = (FTC_GNode)ftcgnode;
+    FTC_GQuery  gquery = (FTC_GQuery)ftcgquery;
+    FT_UNUSED( cache );
+
+
+    if ( list_changed )
+      *list_changed = FALSE;
+    return FT_BOOL( gnode->family == gquery->family &&
+                    gnode->gindex == gquery->gindex );
+  }
+
+
+#ifdef FTC_INLINE
+
+  FT_LOCAL_DEF( FT_Bool )
+  FTC_GNode_Compare( FTC_GNode   gnode,
+                     FTC_GQuery  gquery,
+                     FTC_Cache   cache,
+                     FT_Bool*    list_changed )
+  {
+    return ftc_gnode_compare( FTC_NODE( gnode ), gquery,
+                              cache, list_changed );
+  }
+
+#endif
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                      CHUNK SETS                               *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  FT_LOCAL_DEF( void )
+  FTC_Family_Init( FTC_Family  family,
+                   FTC_Cache   cache )
+  {
+    FTC_GCacheClass  clazz = FTC_CACHE__GCACHE_CLASS( cache );
+
+
+    family->clazz     = clazz->family_class;
+    family->num_nodes = 0;
+    family->cache     = cache;
+  }
+
+
+  FT_LOCAL_DEF( FT_Error )
+  ftc_gcache_init( FTC_Cache  ftccache )
+  {
+    FTC_GCache  cache = (FTC_GCache)ftccache;
+    FT_Error    error;
+
+
+    error = FTC_Cache_Init( FTC_CACHE( cache ) );
+    if ( !error )
+    {
+      FTC_GCacheClass   clazz = (FTC_GCacheClass)FTC_CACHE( cache )->org_class;
+
+      FTC_MruList_Init( &cache->families,
+                        clazz->family_class,
+                        0,  /* no maximum here! */
+                        cache,
+                        FTC_CACHE( cache )->memory );
+    }
+
+    return error;
+  }
+
+
+#if 0
+
+  FT_LOCAL_DEF( FT_Error )
+  FTC_GCache_Init( FTC_GCache  cache )
+  {
+    return ftc_gcache_init( FTC_CACHE( cache ) );
+  }
+
+#endif /* 0 */
+
+
+  FT_LOCAL_DEF( void )
+  ftc_gcache_done( FTC_Cache  ftccache )
+  {
+    FTC_GCache  cache = (FTC_GCache)ftccache;
+
+
+    FTC_Cache_Done( (FTC_Cache)cache );
+    FTC_MruList_Done( &cache->families );
+  }
+
+
+#if 0
+
+  FT_LOCAL_DEF( void )
+  FTC_GCache_Done( FTC_GCache  cache )
+  {
+    ftc_gcache_done( FTC_CACHE( cache ) );
+  }
+
+#endif /* 0 */
+
+
+  FT_LOCAL_DEF( FT_Error )
+  FTC_GCache_New( FTC_Manager       manager,
+                  FTC_GCacheClass   clazz,
+                  FTC_GCache       *acache )
+  {
+    return FTC_Manager_RegisterCache( manager, (FTC_CacheClass)clazz,
+                                      (FTC_Cache*)acache );
+  }
+
+
+#ifndef FTC_INLINE
+
+  FT_LOCAL_DEF( FT_Error )
+  FTC_GCache_Lookup( FTC_GCache   cache,
+                     FT_PtrDist   hash,
+                     FT_UInt      gindex,
+                     FTC_GQuery   query,
+                     FTC_Node    *anode )
+  {
+    FT_Error  error;
+
+
+    query->gindex = gindex;
+
+    FTC_MRULIST_LOOKUP( &cache->families, query, query->family, error );
+    if ( !error )
+    {
+      FTC_Family  family = query->family;
+
+
+      /* prevent the family from being destroyed too early when an        */
+      /* out-of-memory condition occurs during glyph node initialization. */
+      family->num_nodes++;
+
+      error = FTC_Cache_Lookup( FTC_CACHE( cache ), hash, query, anode );
+
+      if ( --family->num_nodes == 0 )
+        FTC_FAMILY_FREE( family, cache );
+    }
+    return error;
+  }
+
+#endif /* !FTC_INLINE */
+
+
+/* END */
diff --git a/src/cache/ftcglyph.h b/src/cache/ftcglyph.h
new file mode 100644
index 0000000..5fed19c
--- /dev/null
+++ b/src/cache/ftcglyph.h
@@ -0,0 +1,329 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftcglyph.h                                                             */
+/*                                                                         */
+/*    FreeType abstract glyph cache (specification).                       */
+/*                                                                         */
+/*  Copyright 2000-2001, 2003, 2004, 2006, 2007, 2011 by                   */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+  /*
+   *
+   *  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 "ftcmanag.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_LOCAL( void )
+  FTC_GNode_Init( FTC_GNode   node,
+                  FT_UInt     gindex,  /* glyph index for node */
+                  FTC_Family  family );
+
+#ifdef FTC_INLINE
+
+  /* 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_LOCAL( FT_Bool )
+  FTC_GNode_Compare( FTC_GNode   gnode,
+                     FTC_GQuery  gquery,
+                     FTC_Cache   cache,
+                     FT_Bool*    list_changed );
+
+#endif
+
+  /* call this function to clear a node's family -- this is necessary */
+  /* to implement the `node_remove_faceid' cache method correctly     */
+  FT_LOCAL( void )
+  FTC_GNode_UnselectFamily( FTC_GNode  gnode,
+                            FTC_Cache  cache );
+
+  /* must be called by derived FTC_Node_DoneFunc routines */
+  FT_LOCAL( void )
+  FTC_GNode_Done( FTC_GNode  node,
+                  FTC_Cache  cache );
+
+
+  FT_LOCAL( 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))
+
+
+#if 0
+  /* can be used as @FTC_Cache_InitFunc */
+  FT_LOCAL( FT_Error )
+  FTC_GCache_Init( FTC_GCache  cache );
+#endif
+
+
+#if 0
+  /* can be used as @FTC_Cache_DoneFunc */
+  FT_LOCAL( void )
+  FTC_GCache_Done( FTC_GCache  cache );
+#endif
+
+
+  /* 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_LOCAL( FT_Error )
+  FTC_GCache_New( FTC_Manager       manager,
+                  FTC_GCacheClass   clazz,
+                  FTC_GCache       *acache );
+
+#ifndef FTC_INLINE
+  FT_LOCAL( FT_Error )
+  FTC_GCache_Lookup( FTC_GCache   cache,
+                     FT_PtrDist   hash,
+                     FT_UInt      gindex,
+                     FTC_GQuery   query,
+                     FTC_Node    *anode );
+#endif
+
+
+  /* */
+
+
+#define FTC_FAMILY_FREE( family, cache )                      \
+          FTC_MruList_Remove( &FTC_GCACHE((cache))->families, \
+                              (FTC_MruNode)(family) )
+
+
+#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); \
+    FTC_MruNode              _mrunode;                                      \
+                                                                            \
+                                                                            \
+    _gquery->gindex = (gindex);                                             \
+                                                                            \
+    FTC_MRULIST_LOOKUP_CMP( &_gcache->families, _gquery, _fcompare,         \
+                            _mrunode, error );                              \
+    _gquery->family = FTC_FAMILY( _mrunode );                               \
+    if ( !error )                                                           \
+    {                                                                       \
+      FTC_Family  _gqfamily = _gquery->family;                              \
+                                                                            \
+                                                                            \
+      _gqfamily->num_nodes++;                                               \
+                                                                            \
+      FTC_CACHE_LOOKUP_CMP( cache, nodecmp, hash, query, node, error );     \
+                                                                            \
+      if ( --_gqfamily->num_nodes == 0 )                                    \
+        FTC_FAMILY_FREE( _gqfamily, _gcache );                              \
+    }                                                                       \
+  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 ), &node );         \
+                                                                      \
+   FT_END_STMNT
+
+#endif /* !FTC_INLINE */
+
+
+FT_END_HEADER
+
+
+#endif /* __FTCGLYPH_H__ */
+
+
+/* END */
diff --git a/src/cache/ftcmanag.h b/src/cache/ftcmanag.h
new file mode 100644
index 0000000..0aec33c
--- /dev/null
+++ b/src/cache/ftcmanag.h
@@ -0,0 +1,175 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftcmanag.h                                                             */
+/*                                                                         */
+/*    FreeType Cache Manager (specification).                              */
+/*                                                                         */
+/*  Copyright 2000-2001, 2003, 2004, 2006, 2010, 2013 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.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* A cache manager is in charge of the following:                        */
+  /*                                                                       */
+  /*  - Maintain a mapping between generic FTC_FaceIDs and live FT_Face    */
+  /*    objects.  The mapping itself is performed through a user-provided  */
+  /*    callback.  However, the manager maintains a small cache of FT_Face */
+  /*    and FT_Size objects in order to speed up things considerably.      */
+  /*                                                                       */
+  /*  - Manage one or more cache objects.  Each cache is in charge of      */
+  /*    holding a varying number of `cache nodes'.  Each cache node        */
+  /*    represents a minimal amount of individually accessible cached      */
+  /*    data.  For example, a cache node can be an FT_Glyph image          */
+  /*    containing a vector outline, or some glyph metrics, or anything    */
+  /*    else.                                                              */
+  /*                                                                       */
+  /*    Each cache node has a certain size in bytes that is added to the   */
+  /*    total amount of `cache memory' within the manager.                 */
+  /*                                                                       */
+  /*    All cache nodes are located in a global LRU list, where the oldest */
+  /*    node is at the tail of the list.                                   */
+  /*                                                                       */
+  /*    Each node belongs to a single cache, and includes a reference      */
+  /*    count to avoid destroying it (due to caching).                     */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*********                                                       *********/
+  /*********             WARNING, THIS IS BETA CODE.               *********/
+  /*********                                                       *********/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+#ifndef __FTCMANAG_H__
+#define __FTCMANAG_H__
+
+
+#include <ft2build.h>
+#include FT_CACHE_H
+#include "ftcmru.h"
+#include "ftccache.h"
+
+
+FT_BEGIN_HEADER
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Section>                                                             */
+  /*    cache_subsystem                                                    */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+#define FTC_MAX_FACES_DEFAULT  2
+#define FTC_MAX_SIZES_DEFAULT  4
+#define FTC_MAX_BYTES_DEFAULT  200000L  /* ~200kByte by default */
+
+  /* maximum number of caches registered in a single manager */
+#define FTC_MAX_CACHES         16
+
+
+  typedef struct  FTC_ManagerRec_
+  {
+    FT_Library          library;
+    FT_Memory           memory;
+
+    FTC_Node            nodes_list;
+    FT_Offset           max_weight;
+    FT_Offset           cur_weight;
+    FT_UInt             num_nodes;
+
+    FTC_Cache           caches[FTC_MAX_CACHES];
+    FT_UInt             num_caches;
+
+    FTC_MruListRec      faces;
+    FTC_MruListRec      sizes;
+
+    FT_Pointer          request_data;
+    FTC_Face_Requester  request_face;
+
+  } FTC_ManagerRec;
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    FTC_Manager_Compress                                               */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    This function is used to check the state of the cache manager if   */
+  /*    its `num_bytes' field is greater than its `max_bytes' field.  It   */
+  /*    will flush as many old cache nodes as possible (ignoring cache     */
+  /*    nodes with a non-zero reference count).                            */
+  /*                                                                       */
+  /* <InOut>                                                               */
+  /*    manager :: A handle to the cache manager.                          */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Client applications should not call this function directly.  It is */
+  /*    normally invoked by specific cache implementations.                */
+  /*                                                                       */
+  /*    The reason this function is exported is to allow client-specific   */
+  /*    cache classes.                                                     */
+  /*                                                                       */
+  FT_LOCAL( void )
+  FTC_Manager_Compress( FTC_Manager  manager );
+
+
+  /* try to flush `count' old nodes from the cache; return the number
+   * of really flushed nodes
+   */
+  FT_LOCAL( FT_UInt )
+  FTC_Manager_FlushN( FTC_Manager  manager,
+                      FT_UInt      count );
+
+
+  /* this must be used internally for the moment */
+  FT_LOCAL( FT_Error )
+  FTC_Manager_RegisterCache( FTC_Manager      manager,
+                             FTC_CacheClass   clazz,
+                             FTC_Cache       *acache );
+
+ /* */
+
+#define FTC_SCALER_COMPARE( a, b )                \
+    ( (a)->face_id      == (b)->face_id      &&   \
+      (a)->width        == (b)->width        &&   \
+      (a)->height       == (b)->height       &&   \
+      ((a)->pixel != 0) == ((b)->pixel != 0) &&   \
+      ( (a)->pixel ||                             \
+        ( (a)->x_res == (b)->x_res &&             \
+          (a)->y_res == (b)->y_res ) ) )
+
+#define FTC_SCALER_HASH( q )                                 \
+    ( _FTC_FACE_ID_HASH( (q)->face_id ) +                     \
+      (q)->width + (q)->height*7 +                           \
+      ( (q)->pixel ? 0 : ( (q)->x_res*33 ^ (q)->y_res*61 ) ) )
+
+ /* */
+
+FT_END_HEADER
+
+#endif /* __FTCMANAG_H__ */
+
+
+/* END */
diff --git a/src/cache/ftcmru.c b/src/cache/ftcmru.c
new file mode 100644
index 0000000..dc8b4cc
--- /dev/null
+++ b/src/cache/ftcmru.c
@@ -0,0 +1,357 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftcmru.c                                                               */
+/*                                                                         */
+/*    FreeType MRU support (body).                                         */
+/*                                                                         */
+/*  Copyright 2003, 2004, 2006, 2009 by                                    */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_CACHE_H
+#include "ftcmru.h"
+#include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_DEBUG_H
+
+#include "ftcerror.h"
+
+
+  FT_LOCAL_DEF( void )
+  FTC_MruNode_Prepend( FTC_MruNode  *plist,
+                       FTC_MruNode   node )
+  {
+    FTC_MruNode  first = *plist;
+
+
+    if ( first )
+    {
+      FTC_MruNode  last = first->prev;
+
+
+#ifdef FT_DEBUG_ERROR
+      {
+        FTC_MruNode  cnode = first;
+
+
+        do
+        {
+          if ( cnode == node )
+          {
+            fprintf( stderr, "FTC_MruNode_Prepend: invalid action\n" );
+            exit( 2 );
+          }
+          cnode = cnode->next;
+
+        } while ( cnode != first );
+      }
+#endif
+
+      first->prev = node;
+      last->next  = node;
+      node->next  = first;
+      node->prev  = last;
+    }
+    else
+    {
+      node->next = node;
+      node->prev = node;
+    }
+    *plist = node;
+  }
+
+
+  FT_LOCAL_DEF( void )
+  FTC_MruNode_Up( FTC_MruNode  *plist,
+                  FTC_MruNode   node )
+  {
+    FTC_MruNode  first = *plist;
+
+
+    FT_ASSERT( first != NULL );
+
+    if ( first != node )
+    {
+      FTC_MruNode  prev, next, last;
+
+
+#ifdef FT_DEBUG_ERROR
+      {
+        FTC_MruNode  cnode = first;
+        do
+        {
+          if ( cnode == node )
+            goto Ok;
+          cnode = cnode->next;
+
+        } while ( cnode != first );
+
+        fprintf( stderr, "FTC_MruNode_Up: invalid action\n" );
+        exit( 2 );
+      Ok:
+      }
+#endif
+      prev = node->prev;
+      next = node->next;
+
+      prev->next = next;
+      next->prev = prev;
+
+      last = first->prev;
+
+      last->next  = node;
+      first->prev = node;
+
+      node->next = first;
+      node->prev = last;
+
+      *plist = node;
+    }
+  }
+
+
+  FT_LOCAL_DEF( void )
+  FTC_MruNode_Remove( FTC_MruNode  *plist,
+                      FTC_MruNode   node )
+  {
+    FTC_MruNode  first = *plist;
+    FTC_MruNode  prev, next;
+
+
+    FT_ASSERT( first != NULL );
+
+#ifdef FT_DEBUG_ERROR
+      {
+        FTC_MruNode  cnode = first;
+
+
+        do
+        {
+          if ( cnode == node )
+            goto Ok;
+          cnode = cnode->next;
+
+        } while ( cnode != first );
+
+        fprintf( stderr, "FTC_MruNode_Remove: invalid action\n" );
+        exit( 2 );
+      Ok:
+      }
+#endif
+
+    prev = node->prev;
+    next = node->next;
+
+    prev->next = next;
+    next->prev = prev;
+
+    if ( node == next )
+    {
+      FT_ASSERT( first == node );
+      FT_ASSERT( prev  == node );
+
+      *plist = NULL;
+    }
+    else if ( node == first )
+      *plist = next;
+  }
+
+
+  FT_LOCAL_DEF( void )
+  FTC_MruList_Init( FTC_MruList       list,
+                    FTC_MruListClass  clazz,
+                    FT_UInt           max_nodes,
+                    FT_Pointer        data,
+                    FT_Memory         memory )
+  {
+    list->num_nodes = 0;
+    list->max_nodes = max_nodes;
+    list->nodes     = NULL;
+    list->clazz     = *clazz;
+    list->data      = data;
+    list->memory    = memory;
+  }
+
+
+  FT_LOCAL_DEF( void )
+  FTC_MruList_Reset( FTC_MruList  list )
+  {
+    while ( list->nodes )
+      FTC_MruList_Remove( list, list->nodes );
+
+    FT_ASSERT( list->num_nodes == 0 );
+  }
+
+
+  FT_LOCAL_DEF( void )
+  FTC_MruList_Done( FTC_MruList  list )
+  {
+    FTC_MruList_Reset( list );
+  }
+
+
+#ifndef FTC_INLINE
+  FT_LOCAL_DEF( FTC_MruNode )
+  FTC_MruList_Find( FTC_MruList  list,
+                    FT_Pointer   key )
+  {
+    FTC_MruNode_CompareFunc  compare = list->clazz.node_compare;
+    FTC_MruNode              first, node;
+
+
+    first = list->nodes;
+    node  = NULL;
+
+    if ( first )
+    {
+      node = first;
+      do
+      {
+        if ( compare( node, key ) )
+        {
+          if ( node != first )
+            FTC_MruNode_Up( &list->nodes, node );
+
+          return node;
+        }
+
+        node = node->next;
+
+      } while ( node != first);
+    }
+
+    return NULL;
+  }
+#endif
+
+  FT_LOCAL_DEF( FT_Error )
+  FTC_MruList_New( FTC_MruList   list,
+                   FT_Pointer    key,
+                   FTC_MruNode  *anode )
+  {
+    FT_Error     error;
+    FTC_MruNode  node = NULL;
+    FT_Memory    memory = list->memory;
+
+
+    if ( list->num_nodes >= list->max_nodes && list->max_nodes > 0 )
+    {
+      node = list->nodes->prev;
+
+      FT_ASSERT( node );
+
+      if ( list->clazz.node_reset )
+      {
+        FTC_MruNode_Up( &list->nodes, node );
+
+        error = list->clazz.node_reset( node, key, list->data );
+        if ( !error )
+          goto Exit;
+      }
+
+      FTC_MruNode_Remove( &list->nodes, node );
+      list->num_nodes--;
+
+      if ( list->clazz.node_done )
+        list->clazz.node_done( node, list->data );
+    }
+    else if ( FT_ALLOC( node, list->clazz.node_size ) )
+      goto Exit;
+
+    error = list->clazz.node_init( node, key, list->data );
+    if ( error )
+      goto Fail;
+
+    FTC_MruNode_Prepend( &list->nodes, node );
+    list->num_nodes++;
+
+  Exit:
+    *anode = node;
+    return error;
+
+  Fail:
+    if ( list->clazz.node_done )
+      list->clazz.node_done( node, list->data );
+
+    FT_FREE( node );
+    goto Exit;
+  }
+
+
+#ifndef FTC_INLINE
+  FT_LOCAL_DEF( FT_Error )
+  FTC_MruList_Lookup( FTC_MruList   list,
+                      FT_Pointer    key,
+                      FTC_MruNode  *anode )
+  {
+    FTC_MruNode  node;
+
+
+    node = FTC_MruList_Find( list, key );
+    if ( node == NULL )
+      return FTC_MruList_New( list, key, anode );
+
+    *anode = node;
+    return 0;
+  }
+#endif /* FTC_INLINE */
+
+  FT_LOCAL_DEF( void )
+  FTC_MruList_Remove( FTC_MruList  list,
+                      FTC_MruNode  node )
+  {
+    FTC_MruNode_Remove( &list->nodes, node );
+    list->num_nodes--;
+
+    {
+      FT_Memory  memory = list->memory;
+
+
+      if ( list->clazz.node_done )
+        list->clazz.node_done( node, list->data );
+
+      FT_FREE( node );
+    }
+  }
+
+
+  FT_LOCAL_DEF( void )
+  FTC_MruList_RemoveSelection( FTC_MruList              list,
+                               FTC_MruNode_CompareFunc  selection,
+                               FT_Pointer               key )
+  {
+    FTC_MruNode  first, node, next;
+
+
+    first = list->nodes;
+    while ( first && ( selection == NULL || selection( first, key ) ) )
+    {
+      FTC_MruList_Remove( list, first );
+      first = list->nodes;
+    }
+
+    if ( first )
+    {
+      node = first->next;
+      while ( node != first )
+      {
+        next = node->next;
+
+        if ( selection( node, key ) )
+          FTC_MruList_Remove( list, node );
+
+        node = next;
+      }
+    }
+  }
+
+
+/* END */
diff --git a/src/cache/ftcsbits.c b/src/cache/ftcsbits.c
new file mode 100644
index 0000000..6df1c19
--- /dev/null
+++ b/src/cache/ftcsbits.c
@@ -0,0 +1,421 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftcsbits.c                                                             */
+/*                                                                         */
+/*    FreeType sbits manager (body).                                       */
+/*                                                                         */
+/*  Copyright 2000-2006, 2009-2011, 2013 by                                */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_CACHE_H
+#include "ftcsbits.h"
+#include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_DEBUG_H
+#include FT_ERRORS_H
+
+#include "ftccback.h"
+#include "ftcerror.h"
+
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_cache
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                     SBIT CACHE NODES                          *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  static FT_Error
+  ftc_sbit_copy_bitmap( FTC_SBit    sbit,
+                        FT_Bitmap*  bitmap,
+                        FT_Memory   memory )
+  {
+    FT_Error  error;
+    FT_Int    pitch = bitmap->pitch;
+    FT_ULong  size;
+
+
+    if ( pitch < 0 )
+      pitch = -pitch;
+
+    size = (FT_ULong)( pitch * bitmap->rows );
+
+    if ( !FT_ALLOC( sbit->buffer, size ) )
+      FT_MEM_COPY( sbit->buffer, bitmap->buffer, size );
+
+    return error;
+  }
+
+
+  FT_LOCAL_DEF( void )
+  ftc_snode_free( FTC_Node   ftcsnode,
+                  FTC_Cache  cache )
+  {
+    FTC_SNode  snode  = (FTC_SNode)ftcsnode;
+    FTC_SBit   sbit   = snode->sbits;
+    FT_UInt    count  = snode->count;
+    FT_Memory  memory = cache->memory;
+
+
+    for ( ; count > 0; sbit++, count-- )
+      FT_FREE( sbit->buffer );
+
+    FTC_GNode_Done( FTC_GNODE( snode ), cache );
+
+    FT_FREE( snode );
+  }
+
+
+  FT_LOCAL_DEF( void )
+  FTC_SNode_Free( FTC_SNode  snode,
+                  FTC_Cache  cache )
+  {
+    ftc_snode_free( FTC_NODE( snode ), cache );
+  }
+
+
+  /*
+   *  This function tries to load a small bitmap within a given FTC_SNode.
+   *  Note that it returns a non-zero error code _only_ in the case of
+   *  out-of-memory condition.  For all other errors (e.g., corresponding
+   *  to a bad font file), this function will mark the sbit as `unavailable'
+   *  and return a value of 0.
+   *
+   *  You should also read the comment within the @ftc_snode_compare
+   *  function below to see how out-of-memory is handled during a lookup.
+   */
+  static FT_Error
+  ftc_snode_load( FTC_SNode    snode,
+                  FTC_Manager  manager,
+                  FT_UInt      gindex,
+                  FT_ULong    *asize )
+  {
+    FT_Error          error;
+    FTC_GNode         gnode  = FTC_GNODE( snode );
+    FTC_Family        family = gnode->family;
+    FT_Memory         memory = manager->memory;
+    FT_Face           face;
+    FTC_SBit          sbit;
+    FTC_SFamilyClass  clazz;
+
+
+    if ( (FT_UInt)(gindex - gnode->gindex) >= snode->count )
+    {
+      FT_ERROR(( "ftc_snode_load: invalid glyph index" ));
+      return FT_THROW( Invalid_Argument );
+    }
+
+    sbit  = snode->sbits + ( gindex - gnode->gindex );
+    clazz = (FTC_SFamilyClass)family->clazz;
+
+    sbit->buffer = 0;
+
+    error = clazz->family_load_glyph( family, gindex, manager, &face );
+    if ( error )
+      goto BadGlyph;
+
+    {
+      FT_Int        temp;
+      FT_GlyphSlot  slot   = face->glyph;
+      FT_Bitmap*    bitmap = &slot->bitmap;
+      FT_Pos        xadvance, yadvance; /* FT_GlyphSlot->advance.{x|y} */
+
+
+      if ( slot->format != FT_GLYPH_FORMAT_BITMAP )
+      {
+        FT_TRACE0(( "ftc_snode_load:"
+                    " glyph loaded didn't return a bitmap\n" ));
+        goto BadGlyph;
+      }
+
+      /* Check that our values fit into 8-bit containers!       */
+      /* If this is not the case, our bitmap is too large       */
+      /* and we will leave it as `missing' with sbit.buffer = 0 */
+
+#define CHECK_CHAR( d )  ( temp = (FT_Char)d, temp == d )
+#define CHECK_BYTE( d )  ( temp = (FT_Byte)d, temp == d )
+
+      /* horizontal advance in pixels */
+      xadvance = ( slot->advance.x + 32 ) >> 6;
+      yadvance = ( slot->advance.y + 32 ) >> 6;
+
+      if ( !CHECK_BYTE( bitmap->rows  )     ||
+           !CHECK_BYTE( bitmap->width )     ||
+           !CHECK_CHAR( bitmap->pitch )     ||
+           !CHECK_CHAR( slot->bitmap_left ) ||
+           !CHECK_CHAR( slot->bitmap_top  ) ||
+           !CHECK_CHAR( xadvance )          ||
+           !CHECK_CHAR( yadvance )          )
+      {
+        FT_TRACE2(( "ftc_snode_load:"
+                    " glyph too large for small bitmap cache\n"));
+        goto BadGlyph;
+      }
+
+      sbit->width     = (FT_Byte)bitmap->width;
+      sbit->height    = (FT_Byte)bitmap->rows;
+      sbit->pitch     = (FT_Char)bitmap->pitch;
+      sbit->left      = (FT_Char)slot->bitmap_left;
+      sbit->top       = (FT_Char)slot->bitmap_top;
+      sbit->xadvance  = (FT_Char)xadvance;
+      sbit->yadvance  = (FT_Char)yadvance;
+      sbit->format    = (FT_Byte)bitmap->pixel_mode;
+      sbit->max_grays = (FT_Byte)(bitmap->num_grays - 1);
+
+      /* copy the bitmap into a new buffer -- ignore error */
+      error = ftc_sbit_copy_bitmap( sbit, bitmap, memory );
+
+      /* now, compute size */
+      if ( asize )
+        *asize = FT_ABS( sbit->pitch ) * sbit->height;
+
+    } /* glyph loading successful */
+
+    /* ignore the errors that might have occurred --   */
+    /* we mark unloaded glyphs with `sbit.buffer == 0' */
+    /* and `width == 255', `height == 0'               */
+    /*                                                 */
+    if ( error && FT_ERR_NEQ( error, Out_Of_Memory ) )
+    {
+    BadGlyph:
+      sbit->width  = 255;
+      sbit->height = 0;
+      sbit->buffer = NULL;
+      error        = FT_Err_Ok;
+      if ( asize )
+        *asize = 0;
+    }
+
+    return error;
+  }
+
+
+  FT_LOCAL_DEF( FT_Error )
+  FTC_SNode_New( FTC_SNode  *psnode,
+                 FTC_GQuery  gquery,
+                 FTC_Cache   cache )
+  {
+    FT_Memory   memory = cache->memory;
+    FT_Error    error;
+    FTC_SNode   snode  = NULL;
+    FT_UInt     gindex = gquery->gindex;
+    FTC_Family  family = gquery->family;
+
+    FTC_SFamilyClass  clazz = FTC_CACHE__SFAMILY_CLASS( cache );
+    FT_UInt           total;
+    FT_UInt           node_count;
+
+
+    total = clazz->family_get_count( family, cache->manager );
+    if ( total == 0 || gindex >= total )
+    {
+      error = FT_THROW( Invalid_Argument );
+      goto Exit;
+    }
+
+    if ( !FT_NEW( snode ) )
+    {
+      FT_UInt  count, start;
+
+
+      start = gindex - ( gindex % FTC_SBIT_ITEMS_PER_NODE );
+      count = total - start;
+      if ( count > FTC_SBIT_ITEMS_PER_NODE )
+        count = FTC_SBIT_ITEMS_PER_NODE;
+
+      FTC_GNode_Init( FTC_GNODE( snode ), start, family );
+
+      snode->count = count;
+      for ( node_count = 0; node_count < count; node_count++ )
+      {
+        snode->sbits[node_count].width = 255;
+      }
+
+      error = ftc_snode_load( snode,
+                              cache->manager,
+                              gindex,
+                              NULL );
+      if ( error )
+      {
+        FTC_SNode_Free( snode, cache );
+        snode = NULL;
+      }
+    }
+
+  Exit:
+    *psnode = snode;
+    return error;
+  }
+
+
+  FT_LOCAL_DEF( FT_Error )
+  ftc_snode_new( FTC_Node   *ftcpsnode,
+                 FT_Pointer  ftcgquery,
+                 FTC_Cache   cache )
+  {
+    FTC_SNode  *psnode = (FTC_SNode*)ftcpsnode;
+    FTC_GQuery  gquery = (FTC_GQuery)ftcgquery;
+
+
+    return FTC_SNode_New( psnode, gquery, cache );
+  }
+
+
+  FT_LOCAL_DEF( FT_Offset )
+  ftc_snode_weight( FTC_Node   ftcsnode,
+                    FTC_Cache  cache )
+  {
+    FTC_SNode  snode = (FTC_SNode)ftcsnode;
+    FT_UInt    count = snode->count;
+    FTC_SBit   sbit  = snode->sbits;
+    FT_Int     pitch;
+    FT_Offset  size;
+
+    FT_UNUSED( cache );
+
+
+    FT_ASSERT( snode->count <= FTC_SBIT_ITEMS_PER_NODE );
+
+    /* the node itself */
+    size = sizeof ( *snode );
+
+    for ( ; count > 0; count--, sbit++ )
+    {
+      if ( sbit->buffer )
+      {
+        pitch = sbit->pitch;
+        if ( pitch < 0 )
+          pitch = -pitch;
+
+        /* add the size of a given glyph image */
+        size += pitch * sbit->height;
+      }
+    }
+
+    return size;
+  }
+
+
+#if 0
+
+  FT_LOCAL_DEF( FT_Offset )
+  FTC_SNode_Weight( FTC_SNode  snode )
+  {
+    return ftc_snode_weight( FTC_NODE( snode ), NULL );
+  }
+
+#endif /* 0 */
+
+
+  FT_LOCAL_DEF( FT_Bool )
+  ftc_snode_compare( FTC_Node    ftcsnode,
+                     FT_Pointer  ftcgquery,
+                     FTC_Cache   cache,
+                     FT_Bool*    list_changed )
+  {
+    FTC_SNode   snode  = (FTC_SNode)ftcsnode;
+    FTC_GQuery  gquery = (FTC_GQuery)ftcgquery;
+    FTC_GNode   gnode  = FTC_GNODE( snode );
+    FT_UInt     gindex = gquery->gindex;
+    FT_Bool     result;
+
+
+    if (list_changed)
+      *list_changed = FALSE;
+    result = FT_BOOL( gnode->family == gquery->family                    &&
+                      (FT_UInt)( gindex - gnode->gindex ) < snode->count );
+    if ( result )
+    {
+      /* check if we need to load the glyph bitmap now */
+      FTC_SBit  sbit = snode->sbits + ( gindex - gnode->gindex );
+
+
+      /*
+       *  The following code illustrates what to do when you want to
+       *  perform operations that may fail within a lookup function.
+       *
+       *  Here, we want to load a small bitmap on-demand; we thus
+       *  need to call the `ftc_snode_load' function which may return
+       *  a non-zero error code only when we are out of memory (OOM).
+       *
+       *  The correct thing to do is to use @FTC_CACHE_TRYLOOP and
+       *  @FTC_CACHE_TRYLOOP_END in order to implement a retry loop
+       *  that is capable of flushing the cache incrementally when
+       *  an OOM errors occur.
+       *
+       *  However, we need to `lock' the node before this operation to
+       *  prevent it from being flushed within the loop.
+       *
+       *  When we exit the loop, we unlock the node, then check the `error'
+       *  variable.  If it is non-zero, this means that the cache was
+       *  completely flushed and that no usable memory was found to load
+       *  the bitmap.
+       *
+       *  We then prefer to return a value of 0 (i.e., NO MATCH).  This
+       *  ensures that the caller will try to allocate a new node.
+       *  This operation consequently _fail_ and the lookup function
+       *  returns the appropriate OOM error code.
+       *
+       *  Note that `buffer == NULL && width == 255' is a hack used to
+       *  tag `unavailable' bitmaps in the array.  We should never try
+       *  to load these.
+       *
+       */
+
+      if ( sbit->buffer == NULL && sbit->width == 255 )
+      {
+        FT_ULong  size;
+        FT_Error  error;
+
+
+        ftcsnode->ref_count++;  /* lock node to prevent flushing */
+                                /* in retry loop                 */
+
+        FTC_CACHE_TRYLOOP( cache )
+        {
+          error = ftc_snode_load( snode, cache->manager, gindex, &size );
+        }
+        FTC_CACHE_TRYLOOP_END( list_changed );
+
+        ftcsnode->ref_count--;  /* unlock the node */
+
+        if ( error )
+          result = 0;
+        else
+          cache->manager->cur_weight += size;
+      }
+    }
+
+    return result;
+  }
+
+
+#ifdef FTC_INLINE
+
+  FT_LOCAL_DEF( FT_Bool )
+  FTC_SNode_Compare( FTC_SNode   snode,
+                     FTC_GQuery  gquery,
+                     FTC_Cache   cache,
+                     FT_Bool*    list_changed )
+  {
+    return ftc_snode_compare( FTC_NODE( snode ), gquery,
+                              cache, list_changed );
+  }
+
+#endif
+
+/* END */
diff --git a/src/cache/ftcsbits.h b/src/cache/ftcsbits.h
new file mode 100644
index 0000000..df55dca
--- /dev/null
+++ b/src/cache/ftcsbits.h
@@ -0,0 +1,103 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ftcsbits.h                                                             */
+/*                                                                         */
+/*    A small-bitmap cache (specification).                                */
+/*                                                                         */
+/*  Copyright 2000-2001, 2002, 2003, 2006, 2011 by                         */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __FTCSBITS_H__
+#define __FTCSBITS_H__
+
+
+#include <ft2build.h>
+#include FT_CACHE_H
+#include "ftcglyph.h"
+
+
+FT_BEGIN_HEADER
+
+#define FTC_SBIT_ITEMS_PER_NODE  16
+
+  typedef struct  FTC_SNodeRec_
+  {
+    FTC_GNodeRec  gnode;
+    FT_UInt       count;
+    FTC_SBitRec   sbits[FTC_SBIT_ITEMS_PER_NODE];
+
+  } FTC_SNodeRec, *FTC_SNode;
+
+
+#define FTC_SNODE( x )         ( (FTC_SNode)( x ) )
+#define FTC_SNODE_GINDEX( x )  FTC_GNODE( x )->gindex
+#define FTC_SNODE_FAMILY( x )  FTC_GNODE( x )->family
+
+  typedef FT_UInt
+  (*FTC_SFamily_GetCountFunc)( FTC_Family   family,
+                               FTC_Manager  manager );
+
+  typedef FT_Error
+  (*FTC_SFamily_LoadGlyphFunc)( FTC_Family   family,
+                                FT_UInt      gindex,
+                                FTC_Manager  manager,
+                                FT_Face     *aface );
+
+  typedef struct  FTC_SFamilyClassRec_
+  {
+    FTC_MruListClassRec        clazz;
+    FTC_SFamily_GetCountFunc   family_get_count;
+    FTC_SFamily_LoadGlyphFunc  family_load_glyph;
+
+  } FTC_SFamilyClassRec;
+
+  typedef const FTC_SFamilyClassRec*  FTC_SFamilyClass;
+
+#define FTC_SFAMILY_CLASS( x )  ((FTC_SFamilyClass)(x))
+
+#define FTC_CACHE__SFAMILY_CLASS( x )  \
+          FTC_SFAMILY_CLASS( FTC_CACHE__GCACHE_CLASS( x )->family_class )
+
+
+  FT_LOCAL( void )
+  FTC_SNode_Free( FTC_SNode  snode,
+                  FTC_Cache  cache );
+
+  FT_LOCAL( FT_Error )
+  FTC_SNode_New( FTC_SNode   *psnode,
+                 FTC_GQuery   gquery,
+                 FTC_Cache    cache );
+
+#if 0
+  FT_LOCAL( FT_ULong )
+  FTC_SNode_Weight( FTC_SNode  inode );
+#endif
+
+
+#ifdef FTC_INLINE
+
+  FT_LOCAL( FT_Bool )
+  FTC_SNode_Compare( FTC_SNode   snode,
+                     FTC_GQuery  gquery,
+                     FTC_Cache   cache,
+                     FT_Bool*    list_changed);
+
+#endif
+
+  /* */
+
+FT_END_HEADER
+
+#endif /* __FTCSBITS_H__ */
+
+
+/* END */
diff --git a/src/cff/cf2arrst.c b/src/cff/cf2arrst.c
new file mode 100644
index 0000000..c8d6f13
--- /dev/null
+++ b/src/cff/cf2arrst.c
@@ -0,0 +1,241 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cf2arrst.c                                                             */
+/*                                                                         */
+/*    Adobe's code for Array Stacks (body).                                */
+/*                                                                         */
+/*  Copyright 2007-2013 Adobe Systems Incorporated.                        */
+/*                                                                         */
+/*  This software, and all works of authorship, whether in source or       */
+/*  object code form as indicated by the copyright notice(s) included      */
+/*  herein (collectively, the "Work") is made available, and may only be   */
+/*  used, modified, and distributed under the FreeType Project License,    */
+/*  LICENSE.TXT.  Additionally, subject to the terms and conditions of the */
+/*  FreeType Project License, each contributor to the Work hereby grants   */
+/*  to any individual or legal entity exercising permissions granted by    */
+/*  the FreeType Project License and this section (hereafter, "You" or     */
+/*  "Your") a perpetual, worldwide, non-exclusive, no-charge,              */
+/*  royalty-free, irrevocable (except as stated in this section) patent    */
+/*  license to make, have made, use, offer to sell, sell, import, and      */
+/*  otherwise transfer the Work, where such license applies only to those  */
+/*  patent claims licensable by such contributor that are necessarily      */
+/*  infringed by their contribution(s) alone or by combination of their    */
+/*  contribution(s) with the Work to which such contribution(s) was        */
+/*  submitted.  If You institute patent litigation against any entity      */
+/*  (including a cross-claim or counterclaim in a lawsuit) alleging that   */
+/*  the Work or a contribution incorporated within the Work constitutes    */
+/*  direct or contributory patent infringement, then any patent licenses   */
+/*  granted to You under this License for that Work shall terminate as of  */
+/*  the date such litigation is filed.                                     */
+/*                                                                         */
+/*  By using, modifying, or distributing the Work you indicate that you    */
+/*  have read and understood the terms and conditions of the               */
+/*  FreeType Project License as well as those provided in this section,    */
+/*  and you accept them fully.                                             */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include "cf2ft.h"
+#include FT_INTERNAL_DEBUG_H
+
+#include "cf2glue.h"
+#include "cf2arrst.h"
+
+#include "cf2error.h"
+
+
+  /*
+   * CF2_ArrStack uses an error pointer, to enable shared errors.
+   * Shared errors are necessary when multiple objects allow the program
+   * to continue after detecting errors.  Only the first error should be
+   * recorded.
+   */
+
+  FT_LOCAL_DEF( void )
+  cf2_arrstack_init( CF2_ArrStack  arrstack,
+                     FT_Memory     memory,
+                     FT_Error*     error,
+                     size_t        sizeItem )
+  {
+    FT_ASSERT( arrstack != NULL );
+
+    /* initialize the structure */
+    arrstack->memory    = memory;
+    arrstack->error     = error;
+    arrstack->sizeItem  = sizeItem;
+    arrstack->allocated = 0;
+    arrstack->chunk     = 10;    /* chunks of 10 items */
+    arrstack->count     = 0;
+    arrstack->totalSize = 0;
+    arrstack->ptr       = NULL;
+  }
+
+
+  FT_LOCAL_DEF( void )
+  cf2_arrstack_finalize( CF2_ArrStack  arrstack )
+  {
+    FT_Memory  memory = arrstack->memory;     /* for FT_FREE */
+
+
+    FT_ASSERT( arrstack != NULL );
+
+    arrstack->allocated = 0;
+    arrstack->count     = 0;
+    arrstack->totalSize = 0;
+
+    /* free the data buffer */
+    FT_FREE( arrstack->ptr );
+  }
+
+
+  /* allocate or reallocate the buffer size; */
+  /* return false on memory error */
+  static FT_Bool
+  cf2_arrstack_setNumElements( CF2_ArrStack  arrstack,
+                               size_t        numElements )
+  {
+    FT_ASSERT( arrstack != NULL );
+
+    {
+      FT_Error   error  = FT_Err_Ok;        /* for FT_REALLOC */
+      FT_Memory  memory = arrstack->memory; /* for FT_REALLOC */
+
+      FT_Long  newSize = (FT_Long)( numElements * arrstack->sizeItem );
+
+
+      if ( numElements > LONG_MAX / arrstack->sizeItem )
+        goto exit;
+
+
+      FT_ASSERT( newSize > 0 );   /* avoid realloc with zero size */
+
+      if ( !FT_REALLOC( arrstack->ptr, arrstack->totalSize, newSize ) )
+      {
+        arrstack->allocated = numElements;
+        arrstack->totalSize = newSize;
+
+        if ( arrstack->count > numElements )
+        {
+          /* we truncated the list! */
+          CF2_SET_ERROR( arrstack->error, Stack_Overflow );
+          arrstack->count = numElements;
+          return FALSE;
+        }
+
+        return TRUE;     /* success */
+      }
+    }
+
+  exit:
+    /* if there's not already an error, store this one */
+    CF2_SET_ERROR( arrstack->error, Out_Of_Memory );
+
+    return FALSE;
+  }
+
+
+  /* set the count, ensuring allocation is sufficient */
+  FT_LOCAL_DEF( void )
+  cf2_arrstack_setCount( CF2_ArrStack  arrstack,
+                         size_t        numElements )
+  {
+    FT_ASSERT( arrstack != NULL );
+
+    if ( numElements > arrstack->allocated )
+    {
+      /* expand the allocation first */
+      if ( !cf2_arrstack_setNumElements( arrstack, numElements ) )
+        return;
+    }
+
+    arrstack->count = numElements;
+  }
+
+
+  /* clear the count */
+  FT_LOCAL_DEF( void )
+  cf2_arrstack_clear( CF2_ArrStack  arrstack )
+  {
+    FT_ASSERT( arrstack != NULL );
+
+    arrstack->count = 0;
+  }
+
+
+  /* current number of items */
+  FT_LOCAL_DEF( size_t )
+  cf2_arrstack_size( const CF2_ArrStack  arrstack )
+  {
+    FT_ASSERT( arrstack != NULL );
+
+    return arrstack->count;
+  }
+
+
+  FT_LOCAL_DEF( void* )
+  cf2_arrstack_getBuffer( const CF2_ArrStack  arrstack )
+  {
+    FT_ASSERT( arrstack != NULL );
+
+    return arrstack->ptr;
+  }
+
+
+  /* return pointer to the given element */
+  FT_LOCAL_DEF( void* )
+  cf2_arrstack_getPointer( const CF2_ArrStack  arrstack,
+                           size_t              idx )
+  {
+    void*  newPtr;
+
+
+    FT_ASSERT( arrstack != NULL );
+
+    if ( idx >= arrstack->count )
+    {
+      /* overflow */
+      CF2_SET_ERROR( arrstack->error, Stack_Overflow );
+      idx = 0;    /* choose safe default */
+    }
+
+    newPtr = (FT_Byte*)arrstack->ptr + idx * arrstack->sizeItem;
+
+    return newPtr;
+  }
+
+
+  /* push (append) an element at the end of the list;         */
+  /* return false on memory error                             */
+  /* TODO: should there be a length param for extra checking? */
+  FT_LOCAL_DEF( void )
+  cf2_arrstack_push( CF2_ArrStack  arrstack,
+                     const void*   ptr )
+  {
+    FT_ASSERT( arrstack != NULL );
+
+    if ( arrstack->count == arrstack->allocated )
+    {
+      /* grow the buffer by one chunk */
+      if ( !cf2_arrstack_setNumElements(
+             arrstack, arrstack->allocated + arrstack->chunk ) )
+      {
+        /* on error, ignore the push */
+        return;
+      }
+    }
+
+    FT_ASSERT( ptr != NULL );
+
+    {
+      size_t  offset = arrstack->count * arrstack->sizeItem;
+      void*   newPtr = (FT_Byte*)arrstack->ptr + offset;
+
+
+      FT_MEM_COPY( newPtr, ptr, arrstack->sizeItem );
+      arrstack->count += 1;
+    }
+  }
+
+
+/* END */
diff --git a/src/cff/cf2arrst.h b/src/cff/cf2arrst.h
new file mode 100644
index 0000000..ff5ad8b
--- /dev/null
+++ b/src/cff/cf2arrst.h
@@ -0,0 +1,100 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cf2arrst.h                                                             */
+/*                                                                         */
+/*    Adobe's code for Array Stacks (specification).                       */
+/*                                                                         */
+/*  Copyright 2007-2013 Adobe Systems Incorporated.                        */
+/*                                                                         */
+/*  This software, and all works of authorship, whether in source or       */
+/*  object code form as indicated by the copyright notice(s) included      */
+/*  herein (collectively, the "Work") is made available, and may only be   */
+/*  used, modified, and distributed under the FreeType Project License,    */
+/*  LICENSE.TXT.  Additionally, subject to the terms and conditions of the */
+/*  FreeType Project License, each contributor to the Work hereby grants   */
+/*  to any individual or legal entity exercising permissions granted by    */
+/*  the FreeType Project License and this section (hereafter, "You" or     */
+/*  "Your") a perpetual, worldwide, non-exclusive, no-charge,              */
+/*  royalty-free, irrevocable (except as stated in this section) patent    */
+/*  license to make, have made, use, offer to sell, sell, import, and      */
+/*  otherwise transfer the Work, where such license applies only to those  */
+/*  patent claims licensable by such contributor that are necessarily      */
+/*  infringed by their contribution(s) alone or by combination of their    */
+/*  contribution(s) with the Work to which such contribution(s) was        */
+/*  submitted.  If You institute patent litigation against any entity      */
+/*  (including a cross-claim or counterclaim in a lawsuit) alleging that   */
+/*  the Work or a contribution incorporated within the Work constitutes    */
+/*  direct or contributory patent infringement, then any patent licenses   */
+/*  granted to You under this License for that Work shall terminate as of  */
+/*  the date such litigation is filed.                                     */
+/*                                                                         */
+/*  By using, modifying, or distributing the Work you indicate that you    */
+/*  have read and understood the terms and conditions of the               */
+/*  FreeType Project License as well as those provided in this section,    */
+/*  and you accept them fully.                                             */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __CF2ARRST_H__
+#define __CF2ARRST_H__
+
+
+#include "cf2error.h"
+
+
+FT_BEGIN_HEADER
+
+
+  /* need to define the struct here (not opaque) so it can be allocated by */
+  /* clients                                                               */
+  typedef struct  CF2_ArrStackRec_
+  {
+    FT_Memory  memory;
+    FT_Error*  error;
+
+    size_t  sizeItem;       /* bytes per element             */
+    size_t  allocated;      /* items allocated               */
+    size_t  chunk;          /* allocation increment in items */
+    size_t  count;          /* number of elements allocated  */
+    size_t  totalSize;      /* total bytes allocated         */
+
+    void*  ptr;             /* ptr to data                   */
+
+  } CF2_ArrStackRec, *CF2_ArrStack;
+
+
+  FT_LOCAL( void )
+  cf2_arrstack_init( CF2_ArrStack  arrstack,
+                     FT_Memory     memory,
+                     FT_Error*     error,
+                     size_t        sizeItem );
+  FT_LOCAL( void )
+  cf2_arrstack_finalize( CF2_ArrStack  arrstack );
+
+  FT_LOCAL( void )
+  cf2_arrstack_setCount( CF2_ArrStack  arrstack,
+                         size_t        numElements );
+  FT_LOCAL( void )
+  cf2_arrstack_clear( CF2_ArrStack  arrstack );
+  FT_LOCAL( size_t )
+  cf2_arrstack_size( const CF2_ArrStack  arrstack );
+
+  FT_LOCAL( void* )
+  cf2_arrstack_getBuffer( const CF2_ArrStack  arrstack );
+  FT_LOCAL( void* )
+  cf2_arrstack_getPointer( const CF2_ArrStack  arrstack,
+                           size_t              idx );
+
+  FT_LOCAL( void )
+  cf2_arrstack_push( CF2_ArrStack  arrstack,
+                     const void*   ptr );
+
+
+FT_END_HEADER
+
+
+#endif /* __CF2ARRST_H__ */
+
+
+/* END */
diff --git a/src/cff/cf2blues.c b/src/cff/cf2blues.c
new file mode 100644
index 0000000..5b34839
--- /dev/null
+++ b/src/cff/cf2blues.c
@@ -0,0 +1,578 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cf2blues.c                                                             */
+/*                                                                         */
+/*    Adobe's code for handling Blue Zones (body).                         */
+/*                                                                         */
+/*  Copyright 2009-2013 Adobe Systems Incorporated.                        */
+/*                                                                         */
+/*  This software, and all works of authorship, whether in source or       */
+/*  object code form as indicated by the copyright notice(s) included      */
+/*  herein (collectively, the "Work") is made available, and may only be   */
+/*  used, modified, and distributed under the FreeType Project License,    */
+/*  LICENSE.TXT.  Additionally, subject to the terms and conditions of the */
+/*  FreeType Project License, each contributor to the Work hereby grants   */
+/*  to any individual or legal entity exercising permissions granted by    */
+/*  the FreeType Project License and this section (hereafter, "You" or     */
+/*  "Your") a perpetual, worldwide, non-exclusive, no-charge,              */
+/*  royalty-free, irrevocable (except as stated in this section) patent    */
+/*  license to make, have made, use, offer to sell, sell, import, and      */
+/*  otherwise transfer the Work, where such license applies only to those  */
+/*  patent claims licensable by such contributor that are necessarily      */
+/*  infringed by their contribution(s) alone or by combination of their    */
+/*  contribution(s) with the Work to which such contribution(s) was        */
+/*  submitted.  If You institute patent litigation against any entity      */
+/*  (including a cross-claim or counterclaim in a lawsuit) alleging that   */
+/*  the Work or a contribution incorporated within the Work constitutes    */
+/*  direct or contributory patent infringement, then any patent licenses   */
+/*  granted to You under this License for that Work shall terminate as of  */
+/*  the date such litigation is filed.                                     */
+/*                                                                         */
+/*  By using, modifying, or distributing the Work you indicate that you    */
+/*  have read and understood the terms and conditions of the               */
+/*  FreeType Project License as well as those provided in this section,    */
+/*  and you accept them fully.                                             */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include "cf2ft.h"
+#include FT_INTERNAL_DEBUG_H
+
+#include "cf2blues.h"
+#include "cf2hints.h"
+#include "cf2font.h"
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_cf2blues
+
+
+  /*
+   * For blue values, the FreeType parser produces an array of integers,
+   * while the Adobe CFF engine produces an array of fixed.
+   * Define a macro to convert FreeType to fixed.
+   */
+#define cf2_blueToFixed( x )  cf2_intToFixed( x )
+
+
+  FT_LOCAL_DEF( void )
+  cf2_blues_init( CF2_Blues  blues,
+                  CF2_Font   font )
+  {
+    /* pointer to parsed font object */
+    CFF_Decoder*  decoder = font->decoder;
+
+    CF2_Fixed  zoneHeight;
+    CF2_Fixed  maxZoneHeight = 0;
+    CF2_Fixed  csUnitsPerPixel;
+
+    size_t  numBlueValues;
+    size_t  numOtherBlues;
+    size_t  numFamilyBlues;
+    size_t  numFamilyOtherBlues;
+
+    FT_Pos*  blueValues;
+    FT_Pos*  otherBlues;
+    FT_Pos*  familyBlues;
+    FT_Pos*  familyOtherBlues;
+
+    size_t     i;
+    CF2_Fixed  emBoxBottom, emBoxTop;
+
+    CF2_Int  unitsPerEm = font->unitsPerEm;
+
+
+    if ( unitsPerEm == 0 )
+      unitsPerEm = 1000;
+
+    FT_ZERO( blues );
+    blues->scale = font->innerTransform.d;
+
+    cf2_getBlueMetrics( decoder,
+                        &blues->blueScale,
+                        &blues->blueShift,
+                        &blues->blueFuzz );
+
+    cf2_getBlueValues( decoder, &numBlueValues, &blueValues );
+    cf2_getOtherBlues( decoder, &numOtherBlues, &otherBlues );
+    cf2_getFamilyBlues( decoder, &numFamilyBlues, &familyBlues );
+    cf2_getFamilyOtherBlues( decoder, &numFamilyOtherBlues, &familyOtherBlues );
+
+    /*
+     * synthetic em box hint heuristic
+     *
+     * Apply this when ideographic dictionary (LanguageGroup 1) has no
+     * real alignment zones.  Adobe tools generate dummy zones at -250 and
+     * 1100 for a 1000 unit em.  Fonts with ICF-based alignment zones
+     * should not enable the heuristic.  When the heuristic is enabled,
+     * the font's blue zones are ignored.
+     *
+     */
+
+    /* get em box from OS/2 typoAscender/Descender                      */
+    /* TODO: FreeType does not parse these metrics.  Skip them for now. */
+#if 0
+    FCM_getHorizontalLineMetrics( &e,
+                                  font->font,
+                                  &ascender,
+                                  &descender,
+                                  &linegap );
+    if ( ascender - descender == unitsPerEm )
+    {
+      emBoxBottom = cf2_intToFixed( descender );
+      emBoxTop    = cf2_intToFixed( ascender );
+    }
+    else
+#endif
+    {
+      emBoxBottom = CF2_ICF_Bottom;
+      emBoxTop    = CF2_ICF_Top;
+    }
+
+    if ( cf2_getLanguageGroup( decoder ) == 1                   &&
+         ( numBlueValues == 0                                 ||
+           ( numBlueValues == 4                             &&
+             cf2_blueToFixed( blueValues[0] ) < emBoxBottom &&
+             cf2_blueToFixed( blueValues[1] ) < emBoxBottom &&
+             cf2_blueToFixed( blueValues[2] ) > emBoxTop    &&
+             cf2_blueToFixed( blueValues[3] ) > emBoxTop    ) ) )
+    {
+      /*
+       * Construct hint edges suitable for synthetic ghost hints at top
+       * and bottom of em box.  +-CF2_MIN_COUNTER allows for unhinted
+       * features above or below the last hinted edge.  This also gives a
+       * net 1 pixel boost to the height of ideographic glyphs.
+       *
+       * Note: Adjust synthetic hints outward by epsilon (0x.0001) to
+       *       avoid interference.  E.g., some fonts have real hints at
+       *       880 and -120.
+       */
+
+      blues->emBoxBottomEdge.csCoord = emBoxBottom - CF2_FIXED_EPSILON;
+      blues->emBoxBottomEdge.dsCoord = cf2_fixedRound(
+                                         FT_MulFix(
+                                           blues->emBoxBottomEdge.csCoord,
+                                           blues->scale ) ) -
+                                       CF2_MIN_COUNTER;
+      blues->emBoxBottomEdge.scale   = blues->scale;
+      blues->emBoxBottomEdge.flags   = CF2_GhostBottom |
+                                       CF2_Locked |
+                                       CF2_Synthetic;
+
+      blues->emBoxTopEdge.csCoord = emBoxTop + CF2_FIXED_EPSILON +
+                                    2 * font->darkenY;
+      blues->emBoxTopEdge.dsCoord = cf2_fixedRound(
+                                      FT_MulFix(
+                                        blues->emBoxTopEdge.csCoord,
+                                        blues->scale ) ) +
+                                    CF2_MIN_COUNTER;
+      blues->emBoxTopEdge.scale   = blues->scale;
+      blues->emBoxTopEdge.flags   = CF2_GhostTop |
+                                    CF2_Locked |
+                                    CF2_Synthetic;
+
+      blues->doEmBoxHints = TRUE;    /* enable the heuristic */
+
+      return;
+    }
+
+    /* copy `BlueValues' and `OtherBlues' to a combined array of top and */
+    /* bottom zones                                                      */
+    for ( i = 0; i < numBlueValues; i += 2 )
+    {
+      blues->zone[blues->count].csBottomEdge =
+        cf2_blueToFixed( blueValues[i] );
+      blues->zone[blues->count].csTopEdge =
+        cf2_blueToFixed( blueValues[i + 1] );
+
+      zoneHeight = blues->zone[blues->count].csTopEdge -
+                   blues->zone[blues->count].csBottomEdge;
+
+      if ( zoneHeight < 0 )
+      {
+        FT_TRACE4(( "cf2_blues_init: ignoring negative zone height\n" ));
+        continue;   /* reject this zone */
+      }
+
+      if ( zoneHeight > maxZoneHeight )
+      {
+        /* take maximum before darkening adjustment      */
+        /* so overshoot suppression point doesn't change */
+        maxZoneHeight = zoneHeight;
+      }
+
+      /* adjust both edges of top zone upward by twice darkening amount */
+      if ( i != 0 )
+      {
+        blues->zone[blues->count].csTopEdge    += 2 * font->darkenY;
+        blues->zone[blues->count].csBottomEdge += 2 * font->darkenY;
+      }
+
+      /* first `BlueValue' is bottom zone; others are top */
+      if ( i == 0 )
+      {
+        blues->zone[blues->count].bottomZone =
+          TRUE;
+        blues->zone[blues->count].csFlatEdge =
+          blues->zone[blues->count].csTopEdge;
+      }
+      else
+      {
+        blues->zone[blues->count].bottomZone =
+          FALSE;
+        blues->zone[blues->count].csFlatEdge =
+          blues->zone[blues->count].csBottomEdge;
+      }
+
+      blues->count += 1;
+    }
+
+    for ( i = 0; i < numOtherBlues; i += 2 )
+    {
+      blues->zone[blues->count].csBottomEdge =
+        cf2_blueToFixed( otherBlues[i] );
+      blues->zone[blues->count].csTopEdge =
+        cf2_blueToFixed( otherBlues[i + 1] );
+
+      zoneHeight = blues->zone[blues->count].csTopEdge -
+                   blues->zone[blues->count].csBottomEdge;
+
+      if ( zoneHeight < 0 )
+      {
+        FT_TRACE4(( "cf2_blues_init: ignoring negative zone height\n" ));
+        continue;   /* reject this zone */
+      }
+
+      if ( zoneHeight > maxZoneHeight )
+      {
+        /* take maximum before darkening adjustment      */
+        /* so overshoot suppression point doesn't change */
+        maxZoneHeight = zoneHeight;
+      }
+
+      /* Note: bottom zones are not adjusted for darkening amount */
+
+      /* all OtherBlues are bottom zone */
+      blues->zone[blues->count].bottomZone =
+        TRUE;
+      blues->zone[blues->count].csFlatEdge =
+        blues->zone[blues->count].csTopEdge;
+
+      blues->count += 1;
+    }
+
+    /* Adjust for FamilyBlues */
+
+    /* Search for the nearest flat edge in `FamilyBlues' or                */
+    /* `FamilyOtherBlues'.  According to the Black Book, any matching edge */
+    /* must be within one device pixel                                     */
+
+    csUnitsPerPixel = FT_DivFix( cf2_intToFixed( 1 ), blues->scale );
+
+    /* loop on all zones in this font */
+    for ( i = 0; i < blues->count; i++ )
+    {
+      size_t     j;
+      CF2_Fixed  minDiff;
+      CF2_Fixed  flatFamilyEdge, diff;
+      /* value for this font */
+      CF2_Fixed  flatEdge = blues->zone[i].csFlatEdge;
+
+
+      if ( blues->zone[i].bottomZone )
+      {
+        /* In a bottom zone, the top edge is the flat edge.             */
+        /* Search `FamilyOtherBlues' for bottom zones; look for closest */
+        /* Family edge that is within the one pixel threshold.          */
+
+        minDiff = CF2_FIXED_MAX;
+
+        for ( j = 0; j < numFamilyOtherBlues; j += 2 )
+        {
+          /* top edge */
+          flatFamilyEdge = cf2_blueToFixed( familyOtherBlues[j + 1] );
+
+          diff = cf2_fixedAbs( flatEdge - flatFamilyEdge );
+
+          if ( diff < minDiff && diff < csUnitsPerPixel )
+          {
+            blues->zone[i].csFlatEdge = flatFamilyEdge;
+            minDiff                   = diff;
+
+            if ( diff == 0 )
+              break;
+          }
+        }
+
+        /* check the first member of FamilyBlues, which is a bottom zone */
+        if ( numFamilyBlues >= 2 )
+        {
+          /* top edge */
+          flatFamilyEdge = cf2_blueToFixed( familyBlues[1] );
+
+          diff = cf2_fixedAbs( flatEdge - flatFamilyEdge );
+
+          if ( diff < minDiff && diff < csUnitsPerPixel )
+            blues->zone[i].csFlatEdge = flatFamilyEdge;
+        }
+      }
+      else
+      {
+        /* In a top zone, the bottom edge is the flat edge.                */
+        /* Search `FamilyBlues' for top zones; skip first zone, which is a */
+        /* bottom zone; look for closest Family edge that is within the    */
+        /* one pixel threshold                                             */
+
+        minDiff = CF2_FIXED_MAX;
+
+        for ( j = 2; j < numFamilyBlues; j += 2 )
+        {
+          /* bottom edge */
+          flatFamilyEdge = cf2_blueToFixed( familyBlues[j] );
+
+          /* adjust edges of top zone upward by twice darkening amount */
+          flatFamilyEdge += 2 * font->darkenY;      /* bottom edge */
+
+          diff = cf2_fixedAbs( flatEdge - flatFamilyEdge );
+
+          if ( diff < minDiff && diff < csUnitsPerPixel )
+          {
+            blues->zone[i].csFlatEdge = flatFamilyEdge;
+            minDiff                   = diff;
+
+            if ( diff == 0 )
+              break;
+          }
+        }
+      }
+    }
+
+    /* TODO: enforce separation of zones, including BlueFuzz */
+
+    /* Adjust BlueScale; similar to AdjustBlueScale() in coretype */
+    /* `bcsetup.c'.                                               */
+
+    if ( maxZoneHeight > 0 )
+    {
+      if ( blues->blueScale > FT_DivFix( cf2_intToFixed( 1 ),
+                                         maxZoneHeight ) )
+      {
+        /* clamp at maximum scale */
+        blues->blueScale = FT_DivFix( cf2_intToFixed( 1 ),
+                                      maxZoneHeight );
+      }
+
+      /*
+       * TODO: Revisit the bug fix for 613448.  The minimum scale
+       *       requirement catches a number of library fonts.  For
+       *       example, with default BlueScale (.039625) and 0.4 minimum,
+       *       the test below catches any font with maxZoneHeight < 10.1.
+       *       There are library fonts ranging from 2 to 10 that get
+       *       caught, including e.g., Eurostile LT Std Medium with
+       *       maxZoneHeight of 6.
+       *
+       */
+#if 0
+      if ( blueScale < .4 / maxZoneHeight )
+      {
+        tetraphilia_assert( 0 );
+        /* clamp at minimum scale, per bug 0613448 fix */
+        blueScale = .4 / maxZoneHeight;
+      }
+#endif
+
+    }
+
+    /*
+     * Suppress overshoot and boost blue zones at small sizes.  Boost
+     * amount varies linearly from 0.5 pixel near 0 to 0 pixel at
+     * blueScale cutoff.
+     * Note: This boost amount is different from the coretype heuristic.
+     *
+     */
+
+    if ( blues->scale < blues->blueScale )
+    {
+      blues->suppressOvershoot = TRUE;
+
+      /* Change rounding threshold for `dsFlatEdge'.                    */
+      /* Note: constant changed from 0.5 to 0.6 to avoid a problem with */
+      /*       10ppem Arial                                             */
+
+      blues->boost = FT_MulFix(
+                       cf2_floatToFixed( .6 ),
+                       ( cf2_intToFixed( 1 ) -
+                         FT_DivFix( blues->scale,
+                                    blues->blueScale ) ) );
+      if ( blues->boost > 0x7FFF )
+      {
+        /* boost must remain less than 0.5, or baseline could go negative */
+        blues->boost = 0x7FFF;
+      }
+    }
+
+    /* boost and darkening have similar effects; don't do both */
+    if ( font->stemDarkened )
+      blues->boost = 0;
+
+    /* set device space alignment for each zone;    */
+    /* apply boost amount before rounding flat edge */
+
+    for ( i = 0; i < blues->count; i++ )
+    {
+      if ( blues->zone[i].bottomZone )
+        blues->zone[i].dsFlatEdge = cf2_fixedRound(
+                                      FT_MulFix(
+                                        blues->zone[i].csFlatEdge,
+                                        blues->scale ) -
+                                      blues->boost );
+      else
+        blues->zone[i].dsFlatEdge = cf2_fixedRound(
+                                      FT_MulFix(
+                                        blues->zone[i].csFlatEdge,
+                                        blues->scale ) +
+                                      blues->boost );
+    }
+  }
+
+
+  /*
+   * Check whether `stemHint' is captured by one of the blue zones.
+   *
+   * Zero, one or both edges may be valid; only valid edges can be
+   * captured.  For compatibility with CoolType, search top and bottom
+   * zones in the same pass (see `BlueLock').  If a hint is captured,
+   * return true and position the edge(s) in one of 3 ways:
+   *
+   *  1) If `BlueScale' suppresses overshoot, position the captured edge
+   *     at the flat edge of the zone.
+   *  2) If overshoot is not suppressed and `BlueShift' requires
+   *     overshoot, position the captured edge a minimum of 1 device pixel
+   *     from the flat edge.
+   *  3) If overshoot is not suppressed or required, position the captured
+   *     edge at the nearest device pixel.
+   *
+   */
+  FT_LOCAL_DEF( FT_Bool )
+  cf2_blues_capture( const CF2_Blues  blues,
+                     CF2_Hint         bottomHintEdge,
+                     CF2_Hint         topHintEdge )
+  {
+    /* TODO: validate? */
+    CF2_Fixed  csFuzz = blues->blueFuzz;
+
+    /* new position of captured edge */
+    CF2_Fixed  dsNew;
+
+    /* amount that hint is moved when positioned */
+    CF2_Fixed  dsMove = 0;
+
+    FT_Bool   captured = FALSE;
+    CF2_UInt  i;
+
+
+    /* assert edge flags are consistent */
+    FT_ASSERT( !cf2_hint_isTop( bottomHintEdge ) &&
+               !cf2_hint_isBottom( topHintEdge ) );
+
+    /* TODO: search once without blue fuzz for compatibility with coretype? */
+    for ( i = 0; i < blues->count; i++ )
+    {
+      if ( blues->zone[i].bottomZone           &&
+           cf2_hint_isBottom( bottomHintEdge ) )
+      {
+        if ( ( blues->zone[i].csBottomEdge - csFuzz ) <=
+               bottomHintEdge->csCoord                   &&
+             bottomHintEdge->csCoord <=
+               ( blues->zone[i].csTopEdge + csFuzz )     )
+        {
+          /* bottom edge captured by bottom zone */
+
+          if ( blues->suppressOvershoot )
+            dsNew = blues->zone[i].dsFlatEdge;
+
+          else if ( ( blues->zone[i].csTopEdge - bottomHintEdge->csCoord ) >=
+                      blues->blueShift )
+          {
+            /* guarantee minimum of 1 pixel overshoot */
+            dsNew = FT_MIN(
+                      cf2_fixedRound( bottomHintEdge->dsCoord ),
+                      blues->zone[i].dsFlatEdge - cf2_intToFixed( 1 ) );
+          }
+
+          else
+          {
+            /* simply round captured edge */
+            dsNew = cf2_fixedRound( bottomHintEdge->dsCoord );
+          }
+
+          dsMove   = dsNew - bottomHintEdge->dsCoord;
+          captured = TRUE;
+
+          break;
+        }
+      }
+
+      if ( !blues->zone[i].bottomZone && cf2_hint_isTop( topHintEdge ) )
+      {
+        if ( ( blues->zone[i].csBottomEdge - csFuzz ) <=
+               topHintEdge->csCoord                      &&
+             topHintEdge->csCoord <=
+               ( blues->zone[i].csTopEdge + csFuzz )     )
+        {
+          /* top edge captured by top zone */
+
+          if ( blues->suppressOvershoot )
+            dsNew = blues->zone[i].dsFlatEdge;
+
+          else if ( ( topHintEdge->csCoord - blues->zone[i].csBottomEdge ) >=
+                      blues->blueShift )
+          {
+            /* guarantee minimum of 1 pixel overshoot */
+            dsNew = FT_MAX(
+                      cf2_fixedRound( topHintEdge->dsCoord ),
+                      blues->zone[i].dsFlatEdge + cf2_intToFixed( 1 ) );
+          }
+
+          else
+          {
+            /* simply round captured edge */
+            dsNew = cf2_fixedRound( topHintEdge->dsCoord );
+          }
+
+          dsMove   = dsNew - topHintEdge->dsCoord;
+          captured = TRUE;
+
+          break;
+        }
+      }
+    }
+
+    if ( captured )
+    {
+      /* move both edges and flag them `locked' */
+      if ( cf2_hint_isValid( bottomHintEdge ) )
+      {
+        bottomHintEdge->dsCoord += dsMove;
+        cf2_hint_lock( bottomHintEdge );
+      }
+
+      if ( cf2_hint_isValid( topHintEdge ) )
+      {
+        topHintEdge->dsCoord += dsMove;
+        cf2_hint_lock( topHintEdge );
+      }
+    }
+
+    return captured;
+  }
+
+
+/* END */
diff --git a/src/cff/cf2blues.h b/src/cff/cf2blues.h
new file mode 100644
index 0000000..2f38fca
--- /dev/null
+++ b/src/cff/cf2blues.h
@@ -0,0 +1,185 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cf2blues.h                                                             */
+/*                                                                         */
+/*    Adobe's code for handling Blue Zones (specification).                */
+/*                                                                         */
+/*  Copyright 2009-2013 Adobe Systems Incorporated.                        */
+/*                                                                         */
+/*  This software, and all works of authorship, whether in source or       */
+/*  object code form as indicated by the copyright notice(s) included      */
+/*  herein (collectively, the "Work") is made available, and may only be   */
+/*  used, modified, and distributed under the FreeType Project License,    */
+/*  LICENSE.TXT.  Additionally, subject to the terms and conditions of the */
+/*  FreeType Project License, each contributor to the Work hereby grants   */
+/*  to any individual or legal entity exercising permissions granted by    */
+/*  the FreeType Project License and this section (hereafter, "You" or     */
+/*  "Your") a perpetual, worldwide, non-exclusive, no-charge,              */
+/*  royalty-free, irrevocable (except as stated in this section) patent    */
+/*  license to make, have made, use, offer to sell, sell, import, and      */
+/*  otherwise transfer the Work, where such license applies only to those  */
+/*  patent claims licensable by such contributor that are necessarily      */
+/*  infringed by their contribution(s) alone or by combination of their    */
+/*  contribution(s) with the Work to which such contribution(s) was        */
+/*  submitted.  If You institute patent litigation against any entity      */
+/*  (including a cross-claim or counterclaim in a lawsuit) alleging that   */
+/*  the Work or a contribution incorporated within the Work constitutes    */
+/*  direct or contributory patent infringement, then any patent licenses   */
+/*  granted to You under this License for that Work shall terminate as of  */
+/*  the date such litigation is filed.                                     */
+/*                                                                         */
+/*  By using, modifying, or distributing the Work you indicate that you    */
+/*  have read and understood the terms and conditions of the               */
+/*  FreeType Project License as well as those provided in this section,    */
+/*  and you accept them fully.                                             */
+/*                                                                         */
+/***************************************************************************/
+
+
+  /*
+   * A `CF2_Blues' object stores the blue zones (horizontal alignment
+   * zones) of a font.  These are specified in the CFF private dictionary
+   * by `BlueValues', `OtherBlues', `FamilyBlues', and `FamilyOtherBlues'.
+   * Each zone is defined by a top and bottom edge in character space.
+   * Further, each zone is either a top zone or a bottom zone, as recorded
+   * by `bottomZone'.
+   *
+   * The maximum number of `BlueValues' and `FamilyBlues' is 7 each.
+   * However, these are combined to produce a total of 7 zones.
+   * Similarly, the maximum number of `OtherBlues' and `FamilyOtherBlues'
+   * is 5 and these are combined to produce an additional 5 zones.
+   *
+   * Blue zones are used to `capture' hints and force them to a common
+   * alignment point.  This alignment is recorded in device space in
+   * `dsFlatEdge'.  Except for this value, a `CF2_Blues' object could be
+   * constructed independently of scaling.  Construction may occur once
+   * the matrix is known.  Other features implemented in the Capture
+   * method are overshoot suppression, overshoot enforcement, and Blue
+   * Boost.
+   *
+   * Capture is determined by `BlueValues' and `OtherBlues', but the
+   * alignment point may be adjusted to the scaled flat edge of
+   * `FamilyBlues' or `FamilyOtherBlues'.  No alignment is done to the
+   * curved edge of a zone.
+   *
+   */
+
+
+#ifndef __CF2BLUES_H__
+#define __CF2BLUES_H__
+
+
+#include "cf2glue.h"
+
+
+FT_BEGIN_HEADER
+
+
+  /*
+   * `CF2_Hint' is shared by `cf2hints.h' and
+   * `cf2blues.h', but `cf2blues.h' depends on
+   * `cf2hints.h', so define it here.  Note: The typedef is in
+   * `cf2glue.h'.
+   *
+   */
+  enum
+  {
+    CF2_GhostBottom = 0x1,  /* a single bottom edge           */
+    CF2_GhostTop    = 0x2,  /* a single top edge              */
+    CF2_PairBottom  = 0x4,  /* the bottom edge of a stem hint */
+    CF2_PairTop     = 0x8,  /* the top edge of a stem hint    */
+    CF2_Locked      = 0x10, /* this edge has been aligned     */
+                            /* by a blue zone                 */
+    CF2_Synthetic   = 0x20  /* this edge was synthesized      */
+  };
+
+
+  /*
+   * Default value for OS/2 typoAscender/Descender when their difference
+   * is not equal to `unitsPerEm'.  The default is based on -250 and 1100
+   * in `CF2_Blues', assuming 1000 units per em here.
+   *
+   */
+  enum
+  {
+    CF2_ICF_Top    = cf2_intToFixed(  880 ),
+    CF2_ICF_Bottom = cf2_intToFixed( -120 )
+  };
+
+
+  /*
+   * Constant used for hint adjustment and for synthetic em box hint
+   * placement.
+   */
+#define CF2_MIN_COUNTER  cf2_floatToFixed( 0.5 )
+
+
+  /* shared typedef is in cf2glue.h */
+  struct  CF2_HintRec_
+  {
+    CF2_UInt  flags;  /* attributes of the edge            */
+    size_t    index;  /* index in original stem hint array */
+                      /* (if not synthetic)                */
+    CF2_Fixed  csCoord;
+    CF2_Fixed  dsCoord;
+    CF2_Fixed  scale;
+  };
+
+
+  typedef struct  CF2_BlueRec_
+  {
+    CF2_Fixed  csBottomEdge;
+    CF2_Fixed  csTopEdge;
+    CF2_Fixed  csFlatEdge; /* may be from either local or Family zones */
+    CF2_Fixed  dsFlatEdge; /* top edge of bottom zone or bottom edge   */
+                           /* of top zone (rounded)                    */
+    FT_Bool  bottomZone;
+
+  } CF2_BlueRec;
+
+
+  /* max total blue zones is 12 */
+  enum
+  {
+    CF2_MAX_BLUES      = 7,
+    CF2_MAX_OTHERBLUES = 5
+  };
+
+
+  typedef struct  CF2_BluesRec_
+  {
+    CF2_Fixed  scale;
+    CF2_UInt   count;
+    FT_Bool    suppressOvershoot;
+    FT_Bool    doEmBoxHints;
+
+    CF2_Fixed  blueScale;
+    CF2_Fixed  blueShift;
+    CF2_Fixed  blueFuzz;
+
+    CF2_Fixed  boost;
+
+    CF2_HintRec  emBoxTopEdge;
+    CF2_HintRec  emBoxBottomEdge;
+
+    CF2_BlueRec  zone[CF2_MAX_BLUES + CF2_MAX_OTHERBLUES];
+
+  } CF2_BluesRec, *CF2_Blues;
+
+
+  FT_LOCAL( void )
+  cf2_blues_init( CF2_Blues  blues,
+                  CF2_Font   font );
+  FT_LOCAL( FT_Bool )
+  cf2_blues_capture( const CF2_Blues  blues,
+                     CF2_Hint         bottomHintEdge,
+                     CF2_Hint         topHintEdge );
+
+
+FT_END_HEADER
+
+
+#endif /* __CF2BLUES_H__ */
+
+
+/* END */
diff --git a/src/cff/cf2error.c b/src/cff/cf2error.c
new file mode 100644
index 0000000..b5595a3
--- /dev/null
+++ b/src/cff/cf2error.c
@@ -0,0 +1,52 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cf2error.c                                                             */
+/*                                                                         */
+/*    Adobe's code for error handling (body).                              */
+/*                                                                         */
+/*  Copyright 2006-2013 Adobe Systems Incorporated.                        */
+/*                                                                         */
+/*  This software, and all works of authorship, whether in source or       */
+/*  object code form as indicated by the copyright notice(s) included      */
+/*  herein (collectively, the "Work") is made available, and may only be   */
+/*  used, modified, and distributed under the FreeType Project License,    */
+/*  LICENSE.TXT.  Additionally, subject to the terms and conditions of the */
+/*  FreeType Project License, each contributor to the Work hereby grants   */
+/*  to any individual or legal entity exercising permissions granted by    */
+/*  the FreeType Project License and this section (hereafter, "You" or     */
+/*  "Your") a perpetual, worldwide, non-exclusive, no-charge,              */
+/*  royalty-free, irrevocable (except as stated in this section) patent    */
+/*  license to make, have made, use, offer to sell, sell, import, and      */
+/*  otherwise transfer the Work, where such license applies only to those  */
+/*  patent claims licensable by such contributor that are necessarily      */
+/*  infringed by their contribution(s) alone or by combination of their    */
+/*  contribution(s) with the Work to which such contribution(s) was        */
+/*  submitted.  If You institute patent litigation against any entity      */
+/*  (including a cross-claim or counterclaim in a lawsuit) alleging that   */
+/*  the Work or a contribution incorporated within the Work constitutes    */
+/*  direct or contributory patent infringement, then any patent licenses   */
+/*  granted to You under this License for that Work shall terminate as of  */
+/*  the date such litigation is filed.                                     */
+/*                                                                         */
+/*  By using, modifying, or distributing the Work you indicate that you    */
+/*  have read and understood the terms and conditions of the               */
+/*  FreeType Project License as well as those provided in this section,    */
+/*  and you accept them fully.                                             */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include "cf2ft.h"
+#include "cf2error.h"
+
+
+  FT_LOCAL_DEF( void )
+  cf2_setError( FT_Error*  error,
+                FT_Error   value )
+  {
+    if ( error && *error == 0 )
+      *error = value;
+  }
+
+
+/* END */
diff --git a/src/cff/cf2error.h b/src/cff/cf2error.h
new file mode 100644
index 0000000..6453ebc
--- /dev/null
+++ b/src/cff/cf2error.h
@@ -0,0 +1,119 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cf2error.h                                                             */
+/*                                                                         */
+/*    Adobe's code for error handling (specification).                     */
+/*                                                                         */
+/*  Copyright 2006-2013 Adobe Systems Incorporated.                        */
+/*                                                                         */
+/*  This software, and all works of authorship, whether in source or       */
+/*  object code form as indicated by the copyright notice(s) included      */
+/*  herein (collectively, the "Work") is made available, and may only be   */
+/*  used, modified, and distributed under the FreeType Project License,    */
+/*  LICENSE.TXT.  Additionally, subject to the terms and conditions of the */
+/*  FreeType Project License, each contributor to the Work hereby grants   */
+/*  to any individual or legal entity exercising permissions granted by    */
+/*  the FreeType Project License and this section (hereafter, "You" or     */
+/*  "Your") a perpetual, worldwide, non-exclusive, no-charge,              */
+/*  royalty-free, irrevocable (except as stated in this section) patent    */
+/*  license to make, have made, use, offer to sell, sell, import, and      */
+/*  otherwise transfer the Work, where such license applies only to those  */
+/*  patent claims licensable by such contributor that are necessarily      */
+/*  infringed by their contribution(s) alone or by combination of their    */
+/*  contribution(s) with the Work to which such contribution(s) was        */
+/*  submitted.  If You institute patent litigation against any entity      */
+/*  (including a cross-claim or counterclaim in a lawsuit) alleging that   */
+/*  the Work or a contribution incorporated within the Work constitutes    */
+/*  direct or contributory patent infringement, then any patent licenses   */
+/*  granted to You under this License for that Work shall terminate as of  */
+/*  the date such litigation is filed.                                     */
+/*                                                                         */
+/*  By using, modifying, or distributing the Work you indicate that you    */
+/*  have read and understood the terms and conditions of the               */
+/*  FreeType Project License as well as those provided in this section,    */
+/*  and you accept them fully.                                             */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __CF2ERROR_H__
+#define __CF2ERROR_H__
+
+
+#include FT_MODULE_ERRORS_H
+
+#undef __FTERRORS_H__
+
+#undef  FT_ERR_PREFIX
+#define FT_ERR_PREFIX  CF2_Err_
+#define FT_ERR_BASE    FT_Mod_Err_CF2
+
+
+#include FT_ERRORS_H
+#include "cf2ft.h"
+
+
+FT_BEGIN_HEADER
+
+
+  /*
+   * A poor-man error facility.
+   *
+   * This code being written in vanilla C, doesn't have the luxury of a
+   * language-supported exception mechanism such as the one available in
+   * Java.  Instead, we are stuck with using error codes that must be
+   * carefully managed and preserved.  However, it is convenient for us to
+   * model our error mechanism on a Java-like exception mechanism.
+   * When we assign an error code we are thus `throwing' an error.
+   *
+   * The perservation of an error code is done by coding convention.
+   * Upon a function call if the error code is anything other than
+   * `FT_Err_Ok', which is guaranteed to be zero, we
+   * will return without altering that error.  This will allow the
+   * error to propogate and be handled at the appropriate location in
+   * the code.
+   *
+   * This allows a style of code where the error code is initialized
+   * up front and a block of calls are made with the error code only
+   * being checked after the block.  If a new error occurs, the original
+   * error will be preserved and a functional no-op should result in any
+   * subsequent function that has an initial error code not equal to
+   * `FT_Err_Ok'.
+   *
+   * Errors are encoded by calling the `FT_THROW' macro.  For example,
+   *
+   * {
+   *   FT_Error  e;
+   *
+   *
+   *   ...
+   *   e = FT_THROW( Out_Of_Memory );
+   * }
+   *
+   */
+
+
+  /* Set error code to a particular value. */
+  FT_LOCAL( void )
+  cf2_setError( FT_Error*  error,
+                FT_Error   value );
+
+
+  /*
+   * A macro that conditionally sets an error code.
+   *
+   * This macro will first check whether `error' is set;
+   * if not, it will set it to `e'.
+   *
+  */
+#define CF2_SET_ERROR( error, e )              \
+          cf2_setError( error, FT_THROW( e ) )
+
+
+FT_END_HEADER
+
+
+#endif /* __CF2ERROR_H__ */
+
+
+/* END */
diff --git a/src/cff/cf2fixed.h b/src/cff/cf2fixed.h
new file mode 100644
index 0000000..ed1452a
--- /dev/null
+++ b/src/cff/cf2fixed.h
@@ -0,0 +1,95 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cf2fixed.h                                                             */
+/*                                                                         */
+/*    Adobe's code for Fixed Point Mathematics (specification only).       */
+/*                                                                         */
+/*  Copyright 2007-2013 Adobe Systems Incorporated.                        */
+/*                                                                         */
+/*  This software, and all works of authorship, whether in source or       */
+/*  object code form as indicated by the copyright notice(s) included      */
+/*  herein (collectively, the "Work") is made available, and may only be   */
+/*  used, modified, and distributed under the FreeType Project License,    */
+/*  LICENSE.TXT.  Additionally, subject to the terms and conditions of the */
+/*  FreeType Project License, each contributor to the Work hereby grants   */
+/*  to any individual or legal entity exercising permissions granted by    */
+/*  the FreeType Project License and this section (hereafter, "You" or     */
+/*  "Your") a perpetual, worldwide, non-exclusive, no-charge,              */
+/*  royalty-free, irrevocable (except as stated in this section) patent    */
+/*  license to make, have made, use, offer to sell, sell, import, and      */
+/*  otherwise transfer the Work, where such license applies only to those  */
+/*  patent claims licensable by such contributor that are necessarily      */
+/*  infringed by their contribution(s) alone or by combination of their    */
+/*  contribution(s) with the Work to which such contribution(s) was        */
+/*  submitted.  If You institute patent litigation against any entity      */
+/*  (including a cross-claim or counterclaim in a lawsuit) alleging that   */
+/*  the Work or a contribution incorporated within the Work constitutes    */
+/*  direct or contributory patent infringement, then any patent licenses   */
+/*  granted to You under this License for that Work shall terminate as of  */
+/*  the date such litigation is filed.                                     */
+/*                                                                         */
+/*  By using, modifying, or distributing the Work you indicate that you    */
+/*  have read and understood the terms and conditions of the               */
+/*  FreeType Project License as well as those provided in this section,    */
+/*  and you accept them fully.                                             */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __CF2FIXED_H__
+#define __CF2FIXED_H__
+
+
+FT_BEGIN_HEADER
+
+
+  /* rasterizer integer and fixed point arithmetic must be 32-bit */
+
+#define   CF2_Fixed  CF2_F16Dot16
+  typedef FT_Int32   CF2_Frac;   /* 2.30 fixed point */
+
+
+#define CF2_FIXED_MAX      ( (CF2_Fixed)0x7FFFFFFFL )
+#define CF2_FIXED_MIN      ( (CF2_Fixed)0x80000000L )
+#define CF2_FIXED_ONE      0x10000L
+#define CF2_FIXED_EPSILON  0x0001
+
+  /* in C 89, left and right shift of negative numbers is  */
+  /* implementation specific behaviour in the general case */
+
+#define cf2_intToFixed( i )                                    \
+          ( (CF2_Fixed)( (FT_UInt32)(i) << 16 ) )
+#define cf2_fixedToInt( x )                                    \
+          ( (FT_Short)( ( (FT_UInt32)(x) + 0x8000U ) >> 16 ) )
+#define cf2_fixedRound( x )                                    \
+          ( (CF2_Fixed)( ( (x) + 0x8000 ) & 0xFFFF0000L ) )
+#define cf2_floatToFixed( f )                                  \
+          ( (CF2_Fixed)( (f) * 65536.0 + 0.5 ) )
+#define cf2_fixedAbs( x )                                      \
+          ( (x) < 0 ? -(x) : (x) )
+#define cf2_fixedFloor( x )                                    \
+          ( (CF2_Fixed)( (x) & 0xFFFF0000L ) )
+#define cf2_fixedFraction( x )                                 \
+          ( (x) - cf2_fixedFloor( x ) )
+#define cf2_fracToFixed( x )                                   \
+          ( (x) < 0 ? -( ( -(x) + 0x2000 ) >> 14 )             \
+                    :  ( (  (x) + 0x2000 ) >> 14 ) )
+
+
+  /* signed numeric types */
+  typedef enum  CF2_NumberType_
+  {
+    CF2_NumberFixed,    /* 16.16 */
+    CF2_NumberFrac,     /*  2.30 */
+    CF2_NumberInt       /* 32.0  */
+
+  } CF2_NumberType;
+
+
+FT_END_HEADER
+
+
+#endif /*  __CF2FIXED_H__ */
+
+
+/* END */
diff --git a/src/cff/cf2font.c b/src/cff/cf2font.c
new file mode 100644
index 0000000..8b2331d
--- /dev/null
+++ b/src/cff/cf2font.c
@@ -0,0 +1,401 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cf2font.c                                                              */
+/*                                                                         */
+/*    Adobe's code for font instances (body).                              */
+/*                                                                         */
+/*  Copyright 2007-2013 Adobe Systems Incorporated.                        */
+/*                                                                         */
+/*  This software, and all works of authorship, whether in source or       */
+/*  object code form as indicated by the copyright notice(s) included      */
+/*  herein (collectively, the "Work") is made available, and may only be   */
+/*  used, modified, and distributed under the FreeType Project License,    */
+/*  LICENSE.TXT.  Additionally, subject to the terms and conditions of the */
+/*  FreeType Project License, each contributor to the Work hereby grants   */
+/*  to any individual or legal entity exercising permissions granted by    */
+/*  the FreeType Project License and this section (hereafter, "You" or     */
+/*  "Your") a perpetual, worldwide, non-exclusive, no-charge,              */
+/*  royalty-free, irrevocable (except as stated in this section) patent    */
+/*  license to make, have made, use, offer to sell, sell, import, and      */
+/*  otherwise transfer the Work, where such license applies only to those  */
+/*  patent claims licensable by such contributor that are necessarily      */
+/*  infringed by their contribution(s) alone or by combination of their    */
+/*  contribution(s) with the Work to which such contribution(s) was        */
+/*  submitted.  If You institute patent litigation against any entity      */
+/*  (including a cross-claim or counterclaim in a lawsuit) alleging that   */
+/*  the Work or a contribution incorporated within the Work constitutes    */
+/*  direct or contributory patent infringement, then any patent licenses   */
+/*  granted to You under this License for that Work shall terminate as of  */
+/*  the date such litigation is filed.                                     */
+/*                                                                         */
+/*  By using, modifying, or distributing the Work you indicate that you    */
+/*  have read and understood the terms and conditions of the               */
+/*  FreeType Project License as well as those provided in this section,    */
+/*  and you accept them fully.                                             */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include "cf2ft.h"
+
+#include "cf2glue.h"
+#include "cf2font.h"
+#include "cf2error.h"
+#include "cf2intrp.h"
+
+
+  /* Compute a stem darkening amount in character space. */
+  static void
+  cf2_computeDarkening( CF2_Fixed   emRatio,
+                        CF2_Fixed   ppem,
+                        CF2_Fixed   stemWidth,
+                        CF2_Fixed*  darkenAmount,
+                        CF2_Fixed   boldenAmount,
+                        FT_Bool     stemDarkened )
+  {
+    /* Internal calculations are done in units per thousand for */
+    /* convenience.                                             */
+    CF2_Fixed  stemWidthPer1000, scaledStem;
+
+
+    *darkenAmount = 0;
+
+    if ( boldenAmount == 0 && !stemDarkened )
+      return;
+
+    /* protect against range problems and divide by zero */
+    if ( emRatio < cf2_floatToFixed( .01 ) )
+      return;
+
+    if ( stemDarkened )
+    {
+      /* convert from true character space to 1000 unit character space; */
+      /* add synthetic emboldening effect                                */
+
+      /* we have to assure that the computation of `scaledStem' */
+      /* and `stemWidthPer1000' don't overflow                  */
+
+      stemWidthPer1000 = FT_MulFix( stemWidth + boldenAmount, emRatio );
+
+      if ( emRatio > CF2_FIXED_ONE                          &&
+           stemWidthPer1000 <= ( stemWidth + boldenAmount ) )
+      {
+        stemWidthPer1000 = 0;                      /* to pacify compiler */
+        scaledStem       = cf2_intToFixed( 2333 );
+      }
+      else
+      {
+        scaledStem = FT_MulFix( stemWidthPer1000, ppem );
+
+        if ( ppem > CF2_FIXED_ONE           &&
+             scaledStem <= stemWidthPer1000 )
+          scaledStem = cf2_intToFixed( 2333 );
+      }
+
+      /*
+       * Total darkening amount is computed in 1000 unit character space
+       * using the modified 5 part curve as Avalon rasterizer.
+       * The darkening amount is smaller for thicker stems.
+       * It becomes zero when the stem is thicker than 2.333 pixels.
+       *
+       * In Avalon rasterizer,
+       *
+       *   darkenAmount = 0.5 pixels   if scaledStem <= 0.5 pixels,
+       *   darkenAmount = 0.333 pixels if 1 <= scaledStem <= 1.667 pixels,
+       *   darkenAmount = 0 pixel      if scaledStem >= 2.333 pixels,
+       *
+       * and piecewise linear in-between.
+       *
+       */
+      if ( scaledStem < cf2_intToFixed( 500 ) )
+        *darkenAmount = FT_DivFix( cf2_intToFixed( 400 ), ppem );
+
+      else if ( scaledStem < cf2_intToFixed( 1000 ) )
+        *darkenAmount = FT_DivFix( cf2_intToFixed( 525 ), ppem ) -
+                          FT_MulFix( stemWidthPer1000,
+                                     cf2_floatToFixed( .25 ) );
+
+      else if ( scaledStem < cf2_intToFixed( 1667 ) )
+        *darkenAmount = FT_DivFix( cf2_intToFixed( 275 ), ppem );
+
+      else if ( scaledStem < cf2_intToFixed( 2333 ) )
+        *darkenAmount = FT_DivFix( cf2_intToFixed( 963 ), ppem ) -
+                          FT_MulFix( stemWidthPer1000,
+                                     cf2_floatToFixed( .413 ) );
+
+      /* use half the amount on each side and convert back to true */
+      /* character space                                           */
+      *darkenAmount = FT_DivFix( *darkenAmount, 2 * emRatio );
+    }
+
+    /* add synthetic emboldening effect in character space */
+    *darkenAmount += boldenAmount / 2;
+  }
+
+
+  /* set up values for the current FontDict and matrix */
+
+  /* caller's transform is adjusted for subpixel positioning */
+  static void
+  cf2_font_setup( CF2_Font           font,
+                  const CF2_Matrix*  transform )
+  {
+    /* pointer to parsed font object */
+    CFF_Decoder*  decoder = font->decoder;
+
+    FT_Bool  needExtraSetup;
+
+    /* character space units */
+    CF2_Fixed  boldenX = font->syntheticEmboldeningAmountX;
+    CF2_Fixed  boldenY = font->syntheticEmboldeningAmountY;
+
+    CF2_Fixed  ppem;
+
+
+    /* clear previous error */
+    font->error = FT_Err_Ok;
+
+    /* if a CID fontDict has changed, we need to recompute some cached */
+    /* data                                                            */
+    needExtraSetup = font->lastSubfont != cf2_getSubfont( decoder );
+
+    /* if ppem has changed, we need to recompute some cached data         */
+    /* note: because of CID font matrix concatenation, ppem and transform */
+    /*       do not necessarily track.                                    */
+    ppem = cf2_getPpemY( decoder );
+    if ( font->ppem != ppem )
+    {
+      font->ppem     = ppem;
+      needExtraSetup = TRUE;
+    }
+
+    /* copy hinted flag on each call */
+    font->hinted = font->renderingFlags & CF2_FlagsHinted;
+
+    /* determine if transform has changed;       */
+    /* include Fontmatrix but ignore translation */
+    if ( ft_memcmp( transform,
+                    &font->currentTransform,
+                    4 * sizeof ( CF2_Fixed ) ) != 0 )
+    {
+      /* save `key' information for `cache of one' matrix data; */
+      /* save client transform, without the translation         */
+      font->currentTransform    = *transform;
+      font->currentTransform.tx =
+      font->currentTransform.ty = cf2_intToFixed( 0 );
+
+      /* TODO: FreeType transform is simple scalar; for now, use identity */
+      /*       for outer                                                  */
+      font->innerTransform   = *transform;
+      font->outerTransform.a =
+      font->outerTransform.d = cf2_intToFixed( 1 );
+      font->outerTransform.b =
+      font->outerTransform.c = cf2_intToFixed( 0 );
+
+      needExtraSetup = TRUE;
+    }
+
+    /*
+     * font->darkened is set to true if there is a stem darkening request or
+     * the font is synthetic emboldened.
+     * font->darkened controls whether to adjust blue zones, winding order,
+     * and hinting.
+     *
+     */
+    if ( font->stemDarkened != ( font->renderingFlags & CF2_FlagsDarkened ) )
+    {
+      font->stemDarkened = font->renderingFlags & CF2_FlagsDarkened;
+
+      /* blue zones depend on darkened flag */
+      needExtraSetup = TRUE;
+    }
+
+    /* recompute variables that are dependent on transform or FontDict or */
+    /* darken flag                                                        */
+    if ( needExtraSetup )
+    {
+      /* StdVW is found in the private dictionary;                       */
+      /* recompute darkening amounts whenever private dictionary or      */
+      /* transform change                                                */
+      /* Note: a rendering flag turns darkening on or off, so we want to */
+      /*       store the `on' amounts;                                   */
+      /*       darkening amount is computed in character space           */
+      /* TODO: testing size-dependent darkening here;                    */
+      /*       what to do for rotations?                                 */
+
+      CF2_Fixed  emRatio;
+      CF2_Fixed  stdHW;
+      CF2_Int    unitsPerEm = font->unitsPerEm;
+
+
+      if ( unitsPerEm == 0 )
+        unitsPerEm = 1000;
+
+      ppem = FT_MAX( cf2_intToFixed( 4 ),
+                     font->ppem ); /* use minimum ppem of 4 */
+
+#if 0
+      /* since vstem is measured in the x-direction, we use the `a' member */
+      /* of the fontMatrix                                                 */
+      emRatio = cf2_fixedFracMul( cf2_intToFixed( 1000 ), fontMatrix->a );
+#endif
+
+      /* Freetype does not preserve the fontMatrix when parsing; use */
+      /* unitsPerEm instead.                                         */
+      /* TODO: check precision of this                               */
+      emRatio     = cf2_intToFixed( 1000 ) / unitsPerEm;
+      font->stdVW = cf2_getStdVW( decoder );
+
+      if ( font->stdVW <= 0 )
+        font->stdVW = FT_DivFix( cf2_intToFixed( 75 ), emRatio );
+
+      if ( boldenX > 0 )
+      {
+        /* Ensure that boldenX is at least 1 pixel for synthetic bold font */
+        /* (similar to what Avalon does)                                   */
+        boldenX = FT_MAX( boldenX,
+                          FT_DivFix( cf2_intToFixed( unitsPerEm ), ppem ) );
+
+        /* Synthetic emboldening adds at least 1 pixel to darkenX, while */
+        /* stem darkening adds at most half pixel.  Since the purpose of */
+        /* stem darkening (readability at small sizes) is met with       */
+        /* synthetic emboldening, no need to add stem darkening for a    */
+        /* synthetic bold font.                                          */
+        cf2_computeDarkening( emRatio,
+                              ppem,
+                              font->stdVW,
+                              &font->darkenX,
+                              boldenX,
+                              FALSE );
+      }
+      else
+        cf2_computeDarkening( emRatio,
+                              ppem,
+                              font->stdVW,
+                              &font->darkenX,
+                              0,
+                              font->stemDarkened );
+
+#if 0
+      /* since hstem is measured in the y-direction, we use the `d' member */
+      /* of the fontMatrix                                                 */
+      /* TODO: use the same units per em as above; check this              */
+      emRatio = cf2_fixedFracMul( cf2_intToFixed( 1000 ), fontMatrix->d );
+#endif
+
+      /* set the default stem width, because it must be the same for all */
+      /* family members;                                                 */
+      /* choose a constant for StdHW that depends on font contrast       */
+      stdHW = cf2_getStdHW( decoder );
+
+      if ( stdHW > 0 && font->stdVW > 2 * stdHW )
+        font->stdHW = FT_DivFix( cf2_intToFixed( 75 ), emRatio );
+      else
+      {
+        /* low contrast font gets less hstem darkening */
+        font->stdHW = FT_DivFix( cf2_intToFixed( 110 ), emRatio );
+      }
+
+      cf2_computeDarkening( emRatio,
+                            ppem,
+                            font->stdHW,
+                            &font->darkenY,
+                            boldenY,
+                            font->stemDarkened );
+
+      if ( font->darkenX != 0 || font->darkenY != 0 )
+        font->darkened = TRUE;
+      else
+        font->darkened = FALSE;
+
+      font->reverseWinding = FALSE; /* initial expectation is CCW */
+
+      /* compute blue zones for this instance */
+      cf2_blues_init( &font->blues, font );
+    }
+  }
+
+
+  /* equivalent to AdobeGetOutline */
+  FT_LOCAL_DEF( FT_Error )
+  cf2_getGlyphOutline( CF2_Font           font,
+                       CF2_Buffer         charstring,
+                       const CF2_Matrix*  transform,
+                       CF2_F16Dot16*      glyphWidth )
+  {
+    FT_Error  lastError = FT_Err_Ok;
+
+    FT_Vector  translation;
+
+#if 0
+    FT_Vector  advancePoint;
+#endif
+
+    CF2_Fixed  advWidth = 0;
+    FT_Bool    needWinding;
+
+
+    /* Note: use both integer and fraction for outlines.  This allows bbox */
+    /*       to come out directly.                                         */
+
+    translation.x = transform->tx;
+    translation.y = transform->ty;
+
+    /* set up values based on transform */
+    cf2_font_setup( font, transform );
+    if ( font->error )
+      goto exit;                      /* setup encountered an error */
+
+    /* reset darken direction */
+    font->reverseWinding = FALSE;
+
+    /* winding order only affects darkening */
+    needWinding = font->darkened;
+
+    while ( 1 )
+    {
+      /* reset output buffer */
+      cf2_outline_reset( &font->outline );
+
+      /* build the outline, passing the full translation */
+      cf2_interpT2CharString( font,
+                              charstring,
+                              (CF2_OutlineCallbacks)&font->outline,
+                              &translation,
+                              FALSE,
+                              0,
+                              0,
+                              &advWidth );
+
+      if ( font->error )
+        goto exit;
+
+      if ( !needWinding )
+        break;
+
+      /* check winding order */
+      if ( font->outline.root.windingMomentum >= 0 ) /* CFF is CCW */
+        break;
+
+      /* invert darkening and render again                            */
+      /* TODO: this should be a parameter to getOutline-computeOffset */
+      font->reverseWinding = TRUE;
+
+      needWinding = FALSE;    /* exit after next iteration */
+    }
+
+    /* finish storing client outline */
+    cf2_outline_close( &font->outline );
+
+  exit:
+    /* FreeType just wants the advance width; there is no translation */
+    *glyphWidth = advWidth;
+
+    /* free resources and collect errors from objects we've used */
+    cf2_setError( &font->error, lastError );
+
+    return font->error;
+  }
+
+
+/* END */
diff --git a/src/cff/cf2font.h b/src/cff/cf2font.h
new file mode 100644
index 0000000..f9dd1bb
--- /dev/null
+++ b/src/cff/cf2font.h
@@ -0,0 +1,114 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cf2font.h                                                              */
+/*                                                                         */
+/*    Adobe's code for font instances (specification).                     */
+/*                                                                         */
+/*  Copyright 2007-2013 Adobe Systems Incorporated.                        */
+/*                                                                         */
+/*  This software, and all works of authorship, whether in source or       */
+/*  object code form as indicated by the copyright notice(s) included      */
+/*  herein (collectively, the "Work") is made available, and may only be   */
+/*  used, modified, and distributed under the FreeType Project License,    */
+/*  LICENSE.TXT.  Additionally, subject to the terms and conditions of the */
+/*  FreeType Project License, each contributor to the Work hereby grants   */
+/*  to any individual or legal entity exercising permissions granted by    */
+/*  the FreeType Project License and this section (hereafter, "You" or     */
+/*  "Your") a perpetual, worldwide, non-exclusive, no-charge,              */
+/*  royalty-free, irrevocable (except as stated in this section) patent    */
+/*  license to make, have made, use, offer to sell, sell, import, and      */
+/*  otherwise transfer the Work, where such license applies only to those  */
+/*  patent claims licensable by such contributor that are necessarily      */
+/*  infringed by their contribution(s) alone or by combination of their    */
+/*  contribution(s) with the Work to which such contribution(s) was        */
+/*  submitted.  If You institute patent litigation against any entity      */
+/*  (including a cross-claim or counterclaim in a lawsuit) alleging that   */
+/*  the Work or a contribution incorporated within the Work constitutes    */
+/*  direct or contributory patent infringement, then any patent licenses   */
+/*  granted to You under this License for that Work shall terminate as of  */
+/*  the date such litigation is filed.                                     */
+/*                                                                         */
+/*  By using, modifying, or distributing the Work you indicate that you    */
+/*  have read and understood the terms and conditions of the               */
+/*  FreeType Project License as well as those provided in this section,    */
+/*  and you accept them fully.                                             */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __CF2FONT_H__
+#define __CF2FONT_H__
+
+
+#include "cf2ft.h"
+#include "cf2blues.h"
+
+
+FT_BEGIN_HEADER
+
+
+#define CF2_OPERAND_STACK_SIZE  48
+#define CF2_MAX_SUBR            10 /* maximum subroutine nesting */
+
+
+  /* typedef is in `cf2glue.h' */
+  struct  CF2_FontRec_
+  {
+    FT_Memory  memory;
+    FT_Error   error;     /* shared error for this instance */
+
+    CF2_RenderingFlags  renderingFlags;
+
+    /* variables that depend on Transform:  */
+    /* the following have zero translation; */
+    /* inner * outer = font * original      */
+
+    CF2_Matrix  currentTransform;  /* original client matrix           */
+    CF2_Matrix  innerTransform;    /* for hinting; erect, scaled       */
+    CF2_Matrix  outerTransform;    /* post hinting; includes rotations */
+    CF2_Fixed   ppem;              /* transform-dependent              */
+
+    CF2_Int  unitsPerEm;
+
+    CF2_Fixed  syntheticEmboldeningAmountX;   /* character space units */
+    CF2_Fixed  syntheticEmboldeningAmountY;   /* character space units */
+
+    /* FreeType related members */
+    CF2_OutlineRec  outline;       /* freetype glyph outline functions */
+    CFF_Decoder*    decoder;
+    CFF_SubFont     lastSubfont;              /* FreeType parsed data; */
+                                              /* top font or subfont   */
+
+    /* these flags can vary from one call to the next */
+    FT_Bool  hinted;
+    FT_Bool  darkened;       /* true if stemDarkened or synthetic bold */
+                             /* i.e. darkenX != 0 || darkenY != 0      */
+    FT_Bool  stemDarkened;
+
+    /* variables that depend on both FontDict and Transform */
+    CF2_Fixed  stdVW;     /* in character space; depends on dict entry */
+    CF2_Fixed  stdHW;     /* in character space; depends on dict entry */
+    CF2_Fixed  darkenX;                    /* character space units    */
+    CF2_Fixed  darkenY;                    /* depends on transform     */
+                                           /* and private dict (StdVW) */
+    FT_Bool  reverseWinding;               /* darken assuming          */
+                                           /* counterclockwise winding */
+
+    CF2_BluesRec  blues;                         /* computed zone data */
+  };
+
+
+  FT_LOCAL( FT_Error )
+  cf2_getGlyphOutline( CF2_Font           font,
+                       CF2_Buffer         charstring,
+                       const CF2_Matrix*  transform,
+                       CF2_F16Dot16*      glyphWidth );
+
+
+FT_END_HEADER
+
+
+#endif /* __CF2FONT_H__ */
+
+
+/* END */
diff --git a/src/cff/cf2ft.c b/src/cff/cf2ft.c
new file mode 100644
index 0000000..c09a024
--- /dev/null
+++ b/src/cff/cf2ft.c
@@ -0,0 +1,639 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cf2ft.c                                                                */
+/*                                                                         */
+/*    FreeType Glue Component to Adobe's Interpreter (body).               */
+/*                                                                         */
+/*  Copyright 2013 Adobe Systems Incorporated.                             */
+/*                                                                         */
+/*  This software, and all works of authorship, whether in source or       */
+/*  object code form as indicated by the copyright notice(s) included      */
+/*  herein (collectively, the "Work") is made available, and may only be   */
+/*  used, modified, and distributed under the FreeType Project License,    */
+/*  LICENSE.TXT.  Additionally, subject to the terms and conditions of the */
+/*  FreeType Project License, each contributor to the Work hereby grants   */
+/*  to any individual or legal entity exercising permissions granted by    */
+/*  the FreeType Project License and this section (hereafter, "You" or     */
+/*  "Your") a perpetual, worldwide, non-exclusive, no-charge,              */
+/*  royalty-free, irrevocable (except as stated in this section) patent    */
+/*  license to make, have made, use, offer to sell, sell, import, and      */
+/*  otherwise transfer the Work, where such license applies only to those  */
+/*  patent claims licensable by such contributor that are necessarily      */
+/*  infringed by their contribution(s) alone or by combination of their    */
+/*  contribution(s) with the Work to which such contribution(s) was        */
+/*  submitted.  If You institute patent litigation against any entity      */
+/*  (including a cross-claim or counterclaim in a lawsuit) alleging that   */
+/*  the Work or a contribution incorporated within the Work constitutes    */
+/*  direct or contributory patent infringement, then any patent licenses   */
+/*  granted to You under this License for that Work shall terminate as of  */
+/*  the date such litigation is filed.                                     */
+/*                                                                         */
+/*  By using, modifying, or distributing the Work you indicate that you    */
+/*  have read and understood the terms and conditions of the               */
+/*  FreeType Project License as well as those provided in this section,    */
+/*  and you accept them fully.                                             */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include "cf2ft.h"
+#include FT_INTERNAL_DEBUG_H
+
+#include "cf2font.h"
+#include "cf2error.h"
+
+
+#define CF2_MAX_SIZE  cf2_intToFixed( 2000 )    /* max ppem */
+
+
+  /*
+   * This check should avoid most internal overflow cases.  Clients should
+   * generally respond to `Glyph_Too_Big' by getting a glyph outline
+   * at EM size, scaling it and filling it as a graphics operation.
+   *
+   */
+  static FT_Error
+  cf2_checkTransform( const CF2_Matrix*  transform,
+                      CF2_Int            unitsPerEm )
+  {
+    CF2_Fixed  maxScale;
+
+
+    FT_ASSERT( unitsPerEm > 0 );
+
+    FT_ASSERT( transform->a > 0 && transform->d > 0 );
+    FT_ASSERT( transform->b == 0 && transform->c == 0 );
+    FT_ASSERT( transform->tx == 0 && transform->ty == 0 );
+
+    if ( unitsPerEm > 0x7FFF )
+      return FT_THROW( Glyph_Too_Big );
+
+    maxScale = FT_DivFix( CF2_MAX_SIZE, cf2_intToFixed( unitsPerEm ) );
+
+    if ( transform->a > maxScale || transform->d > maxScale )
+      return FT_THROW( Glyph_Too_Big );
+
+    return FT_Err_Ok;
+  }
+
+
+  static void
+  cf2_setGlyphWidth( CF2_Outline  outline,
+                     CF2_Fixed    width )
+  {
+    CFF_Decoder*  decoder = outline->decoder;
+
+
+    FT_ASSERT( decoder );
+
+    decoder->glyph_width = cf2_fixedToInt( width );
+  }
+
+
+  /* Clean up font instance. */
+  static void
+  cf2_free_instance( void*  ptr )
+  {
+    CF2_Font  font = (CF2_Font)ptr;
+
+
+    if ( font )
+    {
+      FT_Memory  memory = font->memory;
+
+
+      (void)memory;
+    }
+  }
+
+
+  /********************************************/
+  /*                                          */
+  /* functions for handling client outline;   */
+  /* FreeType uses coordinates in 26.6 format */
+  /*                                          */
+  /********************************************/
+
+  static void
+  cf2_builder_moveTo( CF2_OutlineCallbacks      callbacks,
+                      const CF2_CallbackParams  params )
+  {
+    /* downcast the object pointer */
+    CF2_Outline   outline = (CF2_Outline)callbacks;
+    CFF_Builder*  builder;
+
+    (void)params;        /* only used in debug mode */
+
+
+    FT_ASSERT( outline && outline->decoder );
+    FT_ASSERT( params->op == CF2_PathOpMoveTo );
+
+    builder = &outline->decoder->builder;
+
+    /* note: two successive moves simply close the contour twice */
+    cff_builder_close_contour( builder );
+    builder->path_begun = 0;
+  }
+
+
+  static void
+  cf2_builder_lineTo( CF2_OutlineCallbacks      callbacks,
+                      const CF2_CallbackParams  params )
+  {
+    /* downcast the object pointer */
+    CF2_Outline   outline = (CF2_Outline)callbacks;
+    CFF_Builder*  builder;
+
+
+    FT_ASSERT( outline && outline->decoder );
+    FT_ASSERT( params->op == CF2_PathOpLineTo );
+
+    builder = &outline->decoder->builder;
+
+    if ( !builder->path_begun )
+    {
+      /* record the move before the line; also check points and set */
+      /* `path_begun'                                               */
+      cff_builder_start_point( builder,
+                               params->pt0.x,
+                               params->pt0.y );
+    }
+
+    /* `cff_builder_add_point1' includes a check_points call for one point */
+    cff_builder_add_point1( builder,
+                            params->pt1.x,
+                            params->pt1.y );
+  }
+
+
+  static void
+  cf2_builder_cubeTo( CF2_OutlineCallbacks      callbacks,
+                      const CF2_CallbackParams  params )
+  {
+    /* downcast the object pointer */
+    CF2_Outline   outline = (CF2_Outline)callbacks;
+    CFF_Builder*  builder;
+
+
+    FT_ASSERT( outline && outline->decoder );
+    FT_ASSERT( params->op == CF2_PathOpCubeTo );
+
+    builder = &outline->decoder->builder;
+
+    if ( !builder->path_begun )
+    {
+      /* record the move before the line; also check points and set */
+      /* `path_begun'                                               */
+      cff_builder_start_point( builder,
+                               params->pt0.x,
+                               params->pt0.y );
+    }
+
+    /* prepare room for 3 points: 2 off-curve, 1 on-curve */
+    cff_check_points( builder, 3 );
+
+    cff_builder_add_point( builder,
+                           params->pt1.x,
+                           params->pt1.y, 0 );
+    cff_builder_add_point( builder,
+                           params->pt2.x,
+                           params->pt2.y, 0 );
+    cff_builder_add_point( builder,
+                           params->pt3.x,
+                           params->pt3.y, 1 );
+  }
+
+
+  static void
+  cf2_outline_init( CF2_Outline  outline,
+                    FT_Memory    memory,
+                    FT_Error*    error )
+  {
+    FT_MEM_ZERO( outline, sizeof ( CF2_OutlineRec ) );
+
+    outline->root.memory = memory;
+    outline->root.error  = error;
+
+    outline->root.moveTo = cf2_builder_moveTo;
+    outline->root.lineTo = cf2_builder_lineTo;
+    outline->root.cubeTo = cf2_builder_cubeTo;
+  }
+
+
+  /* get scaling and hint flag from GlyphSlot */
+  static void
+  cf2_getScaleAndHintFlag( CFF_Decoder*  decoder,
+                           CF2_Fixed*    x_scale,
+                           CF2_Fixed*    y_scale,
+                           FT_Bool*      hinted,
+                           FT_Bool*      scaled )
+  {
+    FT_ASSERT( decoder && decoder->builder.glyph );
+
+    /* note: FreeType scale includes a factor of 64 */
+    *hinted = decoder->builder.glyph->hint;
+    *scaled = decoder->builder.glyph->scaled;
+
+    if ( *hinted )
+    {
+      *x_scale = FT_DivFix( decoder->builder.glyph->x_scale,
+                            cf2_intToFixed( 64 ) );
+      *y_scale = FT_DivFix( decoder->builder.glyph->y_scale,
+                            cf2_intToFixed( 64 ) );
+    }
+    else
+    {
+      /* for unhinted outlines, `cff_slot_load' does the scaling, */
+      /* thus render at `unity' scale                             */
+
+      *x_scale = 0x0400;   /* 1/64 as 16.16 */
+      *y_scale = 0x0400;
+    }
+  }
+
+
+  /* get units per em from `FT_Face' */
+  /* TODO: should handle font matrix concatenation? */
+  static FT_UShort
+  cf2_getUnitsPerEm( CFF_Decoder*  decoder )
+  {
+    FT_ASSERT( decoder && decoder->builder.face );
+    FT_ASSERT( decoder->builder.face->root.units_per_EM );
+
+    return decoder->builder.face->root.units_per_EM;
+  }
+
+
+  /* Main entry point: Render one glyph. */
+  FT_LOCAL_DEF( FT_Error )
+  cf2_decoder_parse_charstrings( CFF_Decoder*  decoder,
+                                 FT_Byte*      charstring_base,
+                                 FT_ULong      charstring_len )
+  {
+    FT_Memory  memory;
+    FT_Error   error = FT_Err_Ok;
+    CF2_Font   font;
+
+
+    FT_ASSERT( decoder && decoder->cff );
+
+    memory = decoder->builder.memory;
+
+    /* CF2 data is saved here across glyphs */
+    font = (CF2_Font)decoder->cff->cf2_instance.data;
+
+    /* on first glyph, allocate instance structure */
+    if ( decoder->cff->cf2_instance.data == NULL )
+    {
+      decoder->cff->cf2_instance.finalizer =
+        (FT_Generic_Finalizer)cf2_free_instance;
+
+      if ( FT_ALLOC( decoder->cff->cf2_instance.data,
+                     sizeof ( CF2_FontRec ) ) )
+        return FT_THROW( Out_Of_Memory );
+
+      font = (CF2_Font)decoder->cff->cf2_instance.data;
+
+      font->memory = memory;
+
+      /* initialize a client outline, to be shared by each glyph rendered */
+      cf2_outline_init( &font->outline, font->memory, &font->error );
+    }
+
+    /* save decoder; it is a stack variable and will be different on each */
+    /* call                                                               */
+    font->decoder         = decoder;
+    font->outline.decoder = decoder;
+
+    {
+      /* build parameters for Adobe engine */
+
+      CFF_Builder*  builder = &decoder->builder;
+      CFF_Driver    driver  = (CFF_Driver)FT_FACE_DRIVER( builder->face );
+
+      /* local error */
+      FT_Error       error2 = FT_Err_Ok;
+      CF2_BufferRec  buf;
+      CF2_Matrix     transform;
+      CF2_F16Dot16   glyphWidth;
+
+      FT_Bool  hinted;
+      FT_Bool  scaled;
+
+
+      /* FreeType has already looked up the GID; convert to         */
+      /* `RegionBuffer', assuming that the input has been validated */
+      FT_ASSERT( charstring_base + charstring_len >= charstring_base );
+
+      FT_ZERO( &buf );
+      buf.start =
+      buf.ptr   = charstring_base;
+      buf.end   = charstring_base + charstring_len;
+
+      FT_ZERO( &transform );
+
+      cf2_getScaleAndHintFlag( decoder,
+                               &transform.a,
+                               &transform.d,
+                               &hinted,
+                               &scaled );
+
+      font->renderingFlags = 0;
+      if ( hinted )
+        font->renderingFlags |= CF2_FlagsHinted;
+      if ( scaled && !driver->no_stem_darkening )
+        font->renderingFlags |= CF2_FlagsDarkened;
+
+      /* now get an outline for this glyph;      */
+      /* also get units per em to validate scale */
+      font->unitsPerEm = (CF2_Int)cf2_getUnitsPerEm( decoder );
+
+      error2 = cf2_checkTransform( &transform, font->unitsPerEm );
+      if ( error2 )
+        return error2;
+
+      error2 = cf2_getGlyphOutline( font, &buf, &transform, &glyphWidth );
+      if ( error2 )
+        return FT_ERR( Invalid_File_Format );
+
+      cf2_setGlyphWidth( &font->outline, glyphWidth );
+
+      return FT_Err_Ok;
+    }
+  }
+
+
+  /* get pointer to current FreeType subfont (based on current glyphID) */
+  FT_LOCAL_DEF( CFF_SubFont )
+  cf2_getSubfont( CFF_Decoder*  decoder )
+  {
+    FT_ASSERT( decoder && decoder->current_subfont );
+
+    return decoder->current_subfont;
+  }
+
+
+  /* get `y_ppem' from `CFF_Size' */
+  FT_LOCAL_DEF( CF2_Fixed )
+  cf2_getPpemY( CFF_Decoder*  decoder )
+  {
+    FT_ASSERT( decoder                          &&
+               decoder->builder.face            &&
+               decoder->builder.face->root.size );
+    FT_ASSERT( decoder->builder.face->root.size->metrics.y_ppem );
+
+    return cf2_intToFixed(
+             decoder->builder.face->root.size->metrics.y_ppem );
+  }
+
+
+  /* get standard stem widths for the current subfont; */
+  /* FreeType stores these as integer font units       */
+  /* (note: variable names seem swapped)               */
+  FT_LOCAL_DEF( CF2_Fixed )
+  cf2_getStdVW( CFF_Decoder*  decoder )
+  {
+    FT_ASSERT( decoder && decoder->current_subfont );
+
+    return cf2_intToFixed(
+             decoder->current_subfont->private_dict.standard_height );
+  }
+
+
+  FT_LOCAL_DEF( CF2_Fixed )
+  cf2_getStdHW( CFF_Decoder*  decoder )
+  {
+    FT_ASSERT( decoder && decoder->current_subfont );
+
+    return cf2_intToFixed(
+             decoder->current_subfont->private_dict.standard_width );
+  }
+
+
+  /* note: FreeType stores 1000 times the actual value for `BlueScale' */
+  FT_LOCAL_DEF( void )
+  cf2_getBlueMetrics( CFF_Decoder*  decoder,
+                      CF2_Fixed*    blueScale,
+                      CF2_Fixed*    blueShift,
+                      CF2_Fixed*    blueFuzz )
+  {
+    FT_ASSERT( decoder && decoder->current_subfont );
+
+    *blueScale = FT_DivFix(
+                   decoder->current_subfont->private_dict.blue_scale,
+                   cf2_intToFixed( 1000 ) );
+    *blueShift = cf2_intToFixed(
+                   decoder->current_subfont->private_dict.blue_shift );
+    *blueFuzz  = cf2_intToFixed(
+                   decoder->current_subfont->private_dict.blue_fuzz );
+  }
+
+
+  /* get blue values counts and arrays; the FreeType parser has validated */
+  /* the counts and verified that each is an even number                  */
+  FT_LOCAL_DEF( void )
+  cf2_getBlueValues( CFF_Decoder*  decoder,
+                     size_t*       count,
+                     FT_Pos*      *data )
+  {
+    FT_ASSERT( decoder && decoder->current_subfont );
+
+    *count = decoder->current_subfont->private_dict.num_blue_values;
+    *data  = (FT_Pos*)
+               &decoder->current_subfont->private_dict.blue_values;
+  }
+
+
+  FT_LOCAL_DEF( void )
+  cf2_getOtherBlues( CFF_Decoder*  decoder,
+                     size_t*       count,
+                     FT_Pos*      *data )
+  {
+    FT_ASSERT( decoder && decoder->current_subfont );
+
+    *count = decoder->current_subfont->private_dict.num_other_blues;
+    *data  = (FT_Pos*)
+               &decoder->current_subfont->private_dict.other_blues;
+  }
+
+
+  FT_LOCAL_DEF( void )
+  cf2_getFamilyBlues( CFF_Decoder*  decoder,
+                      size_t*       count,
+                      FT_Pos*      *data )
+  {
+    FT_ASSERT( decoder && decoder->current_subfont );
+
+    *count = decoder->current_subfont->private_dict.num_family_blues;
+    *data  = (FT_Pos*)
+               &decoder->current_subfont->private_dict.family_blues;
+  }
+
+
+  FT_LOCAL_DEF( void )
+  cf2_getFamilyOtherBlues( CFF_Decoder*  decoder,
+                           size_t*       count,
+                           FT_Pos*      *data )
+  {
+    FT_ASSERT( decoder && decoder->current_subfont );
+
+    *count = decoder->current_subfont->private_dict.num_family_other_blues;
+    *data  = (FT_Pos*)
+               &decoder->current_subfont->private_dict.family_other_blues;
+  }
+
+
+  FT_LOCAL_DEF( CF2_Int )
+  cf2_getLanguageGroup( CFF_Decoder*  decoder )
+  {
+    FT_ASSERT( decoder && decoder->current_subfont );
+
+    return decoder->current_subfont->private_dict.language_group;
+  }
+
+
+  /* convert unbiased subroutine index to `CF2_Buffer' and */
+  /* return 0 on success                                   */
+  FT_LOCAL_DEF( CF2_Int )
+  cf2_initGlobalRegionBuffer( CFF_Decoder*  decoder,
+                              CF2_UInt      idx,
+                              CF2_Buffer    buf )
+  {
+    FT_ASSERT( decoder && decoder->globals );
+
+    FT_ZERO( buf );
+
+    idx += decoder->globals_bias;
+    if ( idx >= decoder->num_globals )
+      return TRUE;     /* error */
+
+    buf->start =
+    buf->ptr   = decoder->globals[idx];
+    buf->end   = decoder->globals[idx + 1];
+
+    return FALSE;      /* success */
+  }
+
+
+  /* convert AdobeStandardEncoding code to CF2_Buffer; */
+  /* used for seac component                           */
+  FT_LOCAL_DEF( FT_Error )
+  cf2_getSeacComponent( CFF_Decoder*  decoder,
+                        CF2_UInt      code,
+                        CF2_Buffer    buf )
+  {
+    CF2_Int   gid;
+    FT_Byte*  charstring;
+    FT_ULong  len;
+    FT_Error  error;
+
+
+    FT_ASSERT( decoder );
+
+    FT_ZERO( buf );
+
+    gid = cff_lookup_glyph_by_stdcharcode( decoder->cff, code );
+    if ( gid < 0 )
+      return FT_THROW( Invalid_Glyph_Format );
+
+    error = cff_get_glyph_data( decoder->builder.face,
+                                gid,
+                                &charstring,
+                                &len );
+    /* TODO: for now, just pass the FreeType error through */
+    if ( error )
+      return error;
+
+    /* assume input has been validated */
+    FT_ASSERT( charstring + len >= charstring );
+
+    buf->start = charstring;
+    buf->end   = charstring + len;
+    buf->ptr   = buf->start;
+
+    return FT_Err_Ok;
+  }
+
+
+  FT_LOCAL_DEF( void )
+  cf2_freeSeacComponent( CFF_Decoder*  decoder,
+                         CF2_Buffer    buf )
+  {
+    FT_ASSERT( decoder );
+
+    cff_free_glyph_data( decoder->builder.face,
+                         (FT_Byte**)&buf->start,
+                         (FT_ULong)( buf->end - buf->start ) );
+  }
+
+
+  FT_LOCAL_DEF( CF2_Int )
+  cf2_initLocalRegionBuffer( CFF_Decoder*  decoder,
+                             CF2_UInt      idx,
+                             CF2_Buffer    buf )
+  {
+    FT_ASSERT( decoder && decoder->locals );
+
+    FT_ZERO( buf );
+
+    idx += decoder->locals_bias;
+    if ( idx >= decoder->num_locals )
+      return TRUE;     /* error */
+
+    buf->start =
+    buf->ptr   = decoder->locals[idx];
+    buf->end   = decoder->locals[idx + 1];
+
+    return FALSE;      /* success */
+  }
+
+
+  FT_LOCAL_DEF( CF2_Fixed )
+  cf2_getDefaultWidthX( CFF_Decoder*  decoder )
+  {
+    FT_ASSERT( decoder && decoder->current_subfont );
+
+    return cf2_intToFixed(
+             decoder->current_subfont->private_dict.default_width );
+  }
+
+
+  FT_LOCAL_DEF( CF2_Fixed )
+  cf2_getNominalWidthX( CFF_Decoder*  decoder )
+  {
+    FT_ASSERT( decoder && decoder->current_subfont );
+
+    return cf2_intToFixed(
+             decoder->current_subfont->private_dict.nominal_width );
+  }
+
+
+  FT_LOCAL_DEF( void )
+  cf2_outline_reset( CF2_Outline  outline )
+  {
+    CFF_Decoder*  decoder = outline->decoder;
+
+
+    FT_ASSERT( decoder );
+
+    outline->root.windingMomentum = 0;
+
+    FT_GlyphLoader_Rewind( decoder->builder.loader );
+  }
+
+
+  FT_LOCAL_DEF( void )
+  cf2_outline_close( CF2_Outline  outline )
+  {
+    CFF_Decoder*  decoder = outline->decoder;
+
+
+    FT_ASSERT( decoder );
+
+    cff_builder_close_contour( &decoder->builder );
+
+    FT_GlyphLoader_Add( decoder->builder.loader );
+  }
+
+
+/* END */
diff --git a/src/cff/cf2ft.h b/src/cff/cf2ft.h
new file mode 100644
index 0000000..731da3c
--- /dev/null
+++ b/src/cff/cf2ft.h
@@ -0,0 +1,147 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cf2ft.h                                                                */
+/*                                                                         */
+/*    FreeType Glue Component to Adobe's Interpreter (specification).      */
+/*                                                                         */
+/*  Copyright 2013 Adobe Systems Incorporated.                             */
+/*                                                                         */
+/*  This software, and all works of authorship, whether in source or       */
+/*  object code form as indicated by the copyright notice(s) included      */
+/*  herein (collectively, the "Work") is made available, and may only be   */
+/*  used, modified, and distributed under the FreeType Project License,    */
+/*  LICENSE.TXT.  Additionally, subject to the terms and conditions of the */
+/*  FreeType Project License, each contributor to the Work hereby grants   */
+/*  to any individual or legal entity exercising permissions granted by    */
+/*  the FreeType Project License and this section (hereafter, "You" or     */
+/*  "Your") a perpetual, worldwide, non-exclusive, no-charge,              */
+/*  royalty-free, irrevocable (except as stated in this section) patent    */
+/*  license to make, have made, use, offer to sell, sell, import, and      */
+/*  otherwise transfer the Work, where such license applies only to those  */
+/*  patent claims licensable by such contributor that are necessarily      */
+/*  infringed by their contribution(s) alone or by combination of their    */
+/*  contribution(s) with the Work to which such contribution(s) was        */
+/*  submitted.  If You institute patent litigation against any entity      */
+/*  (including a cross-claim or counterclaim in a lawsuit) alleging that   */
+/*  the Work or a contribution incorporated within the Work constitutes    */
+/*  direct or contributory patent infringement, then any patent licenses   */
+/*  granted to You under this License for that Work shall terminate as of  */
+/*  the date such litigation is filed.                                     */
+/*                                                                         */
+/*  By using, modifying, or distributing the Work you indicate that you    */
+/*  have read and understood the terms and conditions of the               */
+/*  FreeType Project License as well as those provided in this section,    */
+/*  and you accept them fully.                                             */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __CF2FT_H__
+#define __CF2FT_H__
+
+
+#include "cf2types.h"
+
+
+  /* TODO: disable asserts for now */
+#define CF2_NDEBUG
+
+
+#include FT_SYSTEM_H
+
+#include "cf2glue.h"
+#include "cffgload.h"    /* for CFF_Decoder */
+
+
+FT_BEGIN_HEADER
+
+
+  FT_LOCAL( FT_Error )
+  cf2_decoder_parse_charstrings( CFF_Decoder*  decoder,
+                                 FT_Byte*      charstring_base,
+                                 FT_ULong      charstring_len );
+
+  FT_LOCAL( CFF_SubFont )
+  cf2_getSubfont( CFF_Decoder*  decoder );
+
+
+  FT_LOCAL( CF2_Fixed )
+  cf2_getPpemY( CFF_Decoder*  decoder );
+  FT_LOCAL( CF2_Fixed )
+  cf2_getStdVW( CFF_Decoder*  decoder );
+  FT_LOCAL( CF2_Fixed )
+  cf2_getStdHW( CFF_Decoder*  decoder );
+
+  FT_LOCAL( void )
+  cf2_getBlueMetrics( CFF_Decoder*  decoder,
+                      CF2_Fixed*    blueScale,
+                      CF2_Fixed*    blueShift,
+                      CF2_Fixed*    blueFuzz );
+  FT_LOCAL( void )
+  cf2_getBlueValues( CFF_Decoder*  decoder,
+                     size_t*       count,
+                     FT_Pos*      *data );
+  FT_LOCAL( void )
+  cf2_getOtherBlues( CFF_Decoder*  decoder,
+                     size_t*       count,
+                     FT_Pos*      *data );
+  FT_LOCAL( void )
+  cf2_getFamilyBlues( CFF_Decoder*  decoder,
+                      size_t*       count,
+                      FT_Pos*      *data );
+  FT_LOCAL( void )
+  cf2_getFamilyOtherBlues( CFF_Decoder*  decoder,
+                           size_t*       count,
+                           FT_Pos*      *data );
+
+  FT_LOCAL( CF2_Int )
+  cf2_getLanguageGroup( CFF_Decoder*  decoder );
+
+  FT_LOCAL( CF2_Int )
+  cf2_initGlobalRegionBuffer( CFF_Decoder*  decoder,
+                              CF2_UInt      idx,
+                              CF2_Buffer    buf );
+  FT_LOCAL( FT_Error )
+  cf2_getSeacComponent( CFF_Decoder*  decoder,
+                        CF2_UInt      code,
+                        CF2_Buffer    buf );
+  FT_LOCAL( void )
+  cf2_freeSeacComponent( CFF_Decoder*  decoder,
+                         CF2_Buffer    buf );
+  FT_LOCAL( CF2_Int )
+  cf2_initLocalRegionBuffer( CFF_Decoder*  decoder,
+                             CF2_UInt      idx,
+                             CF2_Buffer    buf );
+
+  FT_LOCAL( CF2_Fixed )
+  cf2_getDefaultWidthX( CFF_Decoder*  decoder );
+  FT_LOCAL( CF2_Fixed )
+  cf2_getNominalWidthX( CFF_Decoder*  decoder );
+
+
+  /*
+   * FreeType client outline
+   *
+   * process output from the charstring interpreter
+   */
+  typedef struct  CF2_OutlineRec_
+  {
+    CF2_OutlineCallbacksRec  root;        /* base class must be first */
+    CFF_Decoder*             decoder;
+
+  } CF2_OutlineRec, *CF2_Outline;
+
+
+  FT_LOCAL( void )
+  cf2_outline_reset( CF2_Outline  outline );
+  FT_LOCAL( void )
+  cf2_outline_close( CF2_Outline  outline );
+
+
+FT_END_HEADER
+
+
+#endif /* __CF2FT_H__ */
+
+
+/* END */
diff --git a/src/cff/cf2glue.h b/src/cff/cf2glue.h
new file mode 100644
index 0000000..a24da39
--- /dev/null
+++ b/src/cff/cf2glue.h
@@ -0,0 +1,144 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cf2glue.h                                                              */
+/*                                                                         */
+/*    Adobe's code for shared stuff (specification only).                  */
+/*                                                                         */
+/*  Copyright 2007-2013 Adobe Systems Incorporated.                        */
+/*                                                                         */
+/*  This software, and all works of authorship, whether in source or       */
+/*  object code form as indicated by the copyright notice(s) included      */
+/*  herein (collectively, the "Work") is made available, and may only be   */
+/*  used, modified, and distributed under the FreeType Project License,    */
+/*  LICENSE.TXT.  Additionally, subject to the terms and conditions of the */
+/*  FreeType Project License, each contributor to the Work hereby grants   */
+/*  to any individual or legal entity exercising permissions granted by    */
+/*  the FreeType Project License and this section (hereafter, "You" or     */
+/*  "Your") a perpetual, worldwide, non-exclusive, no-charge,              */
+/*  royalty-free, irrevocable (except as stated in this section) patent    */
+/*  license to make, have made, use, offer to sell, sell, import, and      */
+/*  otherwise transfer the Work, where such license applies only to those  */
+/*  patent claims licensable by such contributor that are necessarily      */
+/*  infringed by their contribution(s) alone or by combination of their    */
+/*  contribution(s) with the Work to which such contribution(s) was        */
+/*  submitted.  If You institute patent litigation against any entity      */
+/*  (including a cross-claim or counterclaim in a lawsuit) alleging that   */
+/*  the Work or a contribution incorporated within the Work constitutes    */
+/*  direct or contributory patent infringement, then any patent licenses   */
+/*  granted to You under this License for that Work shall terminate as of  */
+/*  the date such litigation is filed.                                     */
+/*                                                                         */
+/*  By using, modifying, or distributing the Work you indicate that you    */
+/*  have read and understood the terms and conditions of the               */
+/*  FreeType Project License as well as those provided in this section,    */
+/*  and you accept them fully.                                             */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __CF2GLUE_H__
+#define __CF2GLUE_H__
+
+
+/* common includes for other modules */
+#include "cf2error.h"
+#include "cf2fixed.h"
+#include "cf2arrst.h"
+#include "cf2read.h"
+
+
+FT_BEGIN_HEADER
+
+
+  /* rendering parameters */
+
+  /* apply hints to rendered glyphs */
+#define CF2_FlagsHinted    1
+  /* for testing */
+#define CF2_FlagsDarkened  2
+
+  /* type for holding the flags */
+  typedef CF2_Int  CF2_RenderingFlags;
+
+
+  /* elements of a glyph outline */
+  typedef enum  CF2_PathOp_
+  {
+    CF2_PathOpMoveTo = 1,     /* change the current point */
+    CF2_PathOpLineTo = 2,     /* line                     */
+    CF2_PathOpQuadTo = 3,     /* quadratic curve          */
+    CF2_PathOpCubeTo = 4      /* cubic curve              */
+
+  } CF2_PathOp;
+
+
+  /* a matrix of fixed point values */
+  typedef struct  CF2_Matrix_
+  {
+    CF2_F16Dot16  a;
+    CF2_F16Dot16  b;
+    CF2_F16Dot16  c;
+    CF2_F16Dot16  d;
+    CF2_F16Dot16  tx;
+    CF2_F16Dot16  ty;
+
+  } CF2_Matrix;
+
+
+  /* these typedefs are needed by more than one header file */
+  /* and gcc compiler doesn't allow redefinition            */
+  typedef struct CF2_FontRec_  CF2_FontRec, *CF2_Font;
+  typedef struct CF2_HintRec_  CF2_HintRec, *CF2_Hint;
+
+
+  /* A common structure for all callback parameters.                       */
+  /*                                                                       */
+  /* Some members may be unused.  For example, `pt0' is not used for       */
+  /* `moveTo' and `pt3' is not used for `quadTo'.  The initial point `pt0' */
+  /* is included for each path element for generality; curve conversions   */
+  /* need it.  The `op' parameter allows one function to handle multiple   */
+  /* element types.                                                        */
+
+  typedef struct  CF2_CallbackParamsRec_
+  {
+    FT_Vector  pt0;
+    FT_Vector  pt1;
+    FT_Vector  pt2;
+    FT_Vector  pt3;
+
+    CF2_Int  op;
+
+  } CF2_CallbackParamsRec, *CF2_CallbackParams;
+
+
+  /* forward reference */
+  typedef struct CF2_OutlineCallbacksRec_  CF2_OutlineCallbacksRec,
+                                           *CF2_OutlineCallbacks;
+
+  /* callback function pointers */
+  typedef void
+  (*CF2_Callback_Type)( CF2_OutlineCallbacks      callbacks,
+                        const CF2_CallbackParams  params );
+
+
+  struct  CF2_OutlineCallbacksRec_
+  {
+    CF2_Callback_Type  moveTo;
+    CF2_Callback_Type  lineTo;
+    CF2_Callback_Type  quadTo;
+    CF2_Callback_Type  cubeTo;
+
+    CF2_Int  windingMomentum;    /* for winding order detection */
+
+    FT_Memory  memory;
+    FT_Error*  error;
+  };
+
+
+FT_END_HEADER
+
+
+#endif /* __CF2GLUE_H__ */
+
+
+/* END */
diff --git a/src/cff/cf2hints.c b/src/cff/cf2hints.c
new file mode 100644
index 0000000..1666e4f
--- /dev/null
+++ b/src/cff/cf2hints.c
@@ -0,0 +1,1733 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cf2hints.c                                                             */
+/*                                                                         */
+/*    Adobe's code for handling CFF hints (body).                          */
+/*                                                                         */
+/*  Copyright 2007-2013 Adobe Systems Incorporated.                        */
+/*                                                                         */
+/*  This software, and all works of authorship, whether in source or       */
+/*  object code form as indicated by the copyright notice(s) included      */
+/*  herein (collectively, the "Work") is made available, and may only be   */
+/*  used, modified, and distributed under the FreeType Project License,    */
+/*  LICENSE.TXT.  Additionally, subject to the terms and conditions of the */
+/*  FreeType Project License, each contributor to the Work hereby grants   */
+/*  to any individual or legal entity exercising permissions granted by    */
+/*  the FreeType Project License and this section (hereafter, "You" or     */
+/*  "Your") a perpetual, worldwide, non-exclusive, no-charge,              */
+/*  royalty-free, irrevocable (except as stated in this section) patent    */
+/*  license to make, have made, use, offer to sell, sell, import, and      */
+/*  otherwise transfer the Work, where such license applies only to those  */
+/*  patent claims licensable by such contributor that are necessarily      */
+/*  infringed by their contribution(s) alone or by combination of their    */
+/*  contribution(s) with the Work to which such contribution(s) was        */
+/*  submitted.  If You institute patent litigation against any entity      */
+/*  (including a cross-claim or counterclaim in a lawsuit) alleging that   */
+/*  the Work or a contribution incorporated within the Work constitutes    */
+/*  direct or contributory patent infringement, then any patent licenses   */
+/*  granted to You under this License for that Work shall terminate as of  */
+/*  the date such litigation is filed.                                     */
+/*                                                                         */
+/*  By using, modifying, or distributing the Work you indicate that you    */
+/*  have read and understood the terms and conditions of the               */
+/*  FreeType Project License as well as those provided in this section,    */
+/*  and you accept them fully.                                             */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include "cf2ft.h"
+#include FT_INTERNAL_DEBUG_H
+
+#include "cf2glue.h"
+#include "cf2font.h"
+#include "cf2hints.h"
+#include "cf2intrp.h"
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_cf2hints
+
+
+  typedef struct  CF2_HintMoveRec_
+  {
+    size_t     j;          /* index of upper hint map edge   */
+    CF2_Fixed  moveUp;     /* adjustment to optimum position */
+
+  } CF2_HintMoveRec, *CF2_HintMove;
+
+
+  /* Compute angular momentum for winding order detection.  It is called */
+  /* for all lines and curves, but not necessarily in element order.     */
+  static CF2_Int
+  cf2_getWindingMomentum( CF2_Fixed  x1,
+                          CF2_Fixed  y1,
+                          CF2_Fixed  x2,
+                          CF2_Fixed  y2 )
+  {
+    /* cross product of pt1 position from origin with pt2 position from  */
+    /* pt1; we reduce the precision so that the result fits into 32 bits */
+
+    return ( x1 >> 16 ) * ( ( y2 - y1 ) >> 16 ) -
+           ( y1 >> 16 ) * ( ( x2 - x1 ) >> 16 );
+  }
+
+
+  /*
+   * Construct from a StemHint; this is used as a parameter to
+   * `cf2_blues_capture'.
+   * `hintOrigin' is the character space displacement of a seac accent.
+   * Adjust stem hint for darkening here.
+   *
+   */
+  static void
+  cf2_hint_init( CF2_Hint            hint,
+                 const CF2_ArrStack  stemHintArray,
+                 size_t              indexStemHint,
+                 const CF2_Font      font,
+                 CF2_Fixed           hintOrigin,
+                 CF2_Fixed           scale,
+                 FT_Bool             bottom )
+  {
+    CF2_Fixed               width;
+    const CF2_StemHintRec*  stemHint;
+
+
+    FT_ZERO( hint );
+
+    stemHint = (const CF2_StemHintRec*)cf2_arrstack_getPointer(
+                                         stemHintArray,
+                                         indexStemHint );
+
+    width = stemHint->max - stemHint->min;
+
+    if ( width == cf2_intToFixed( -21 ) )
+    {
+      /* ghost bottom */
+
+      if ( bottom )
+      {
+        hint->csCoord = stemHint->max;
+        hint->flags   = CF2_GhostBottom;
+      }
+      else
+        hint->flags = 0;
+    }
+
+    else if ( width == cf2_intToFixed( -20 ) )
+    {
+      /* ghost top */
+
+      if ( bottom )
+        hint->flags = 0;
+      else
+      {
+        hint->csCoord = stemHint->min;
+        hint->flags   = CF2_GhostTop;
+      }
+    }
+
+    else if ( width < 0 )
+    {
+      /* inverted pair */
+
+      /*
+       * Hints with negative widths were produced by an early version of a
+       * non-Adobe font tool.  The Type 2 spec allows edge (ghost) hints
+       * with negative widths, but says
+       *
+       *   All other negative widths have undefined meaning.
+       *
+       * CoolType has a silent workaround that negates the hint width; for
+       * permissive mode, we do the same here.
+       *
+       * Note: Such fonts cannot use ghost hints, but should otherwise work.
+       * Note: Some poor hints in our faux fonts can produce negative
+       *       widths at some blends.  For example, see a light weight of
+       *       `u' in ASerifMM.
+       *
+       */
+      if ( bottom )
+      {
+        hint->csCoord = stemHint->max;
+        hint->flags   = CF2_PairBottom;
+      }
+      else
+      {
+        hint->csCoord = stemHint->min;
+        hint->flags   = CF2_PairTop;
+      }
+    }
+
+    else
+    {
+      /* normal pair */
+
+      if ( bottom )
+      {
+        hint->csCoord = stemHint->min;
+        hint->flags   = CF2_PairBottom;
+      }
+      else
+      {
+        hint->csCoord = stemHint->max;
+        hint->flags   = CF2_PairTop;
+      }
+    }
+
+    /* Now that ghost hints have been detected, adjust this edge for      */
+    /* darkening.  Bottoms are not changed; tops are incremented by twice */
+    /* `darkenY'.                                                         */
+    if ( cf2_hint_isTop( hint ) )
+      hint->csCoord += 2 * font->darkenY;
+
+    hint->csCoord += hintOrigin;
+    hint->scale    = scale;
+    hint->index    = indexStemHint;   /* index in original stem hint array */
+
+    /* if original stem hint has been used, use the same position */
+    if ( hint->flags != 0 && stemHint->used )
+    {
+      if ( cf2_hint_isTop( hint ) )
+        hint->dsCoord = stemHint->maxDS;
+      else
+        hint->dsCoord = stemHint->minDS;
+
+      cf2_hint_lock( hint );
+    }
+    else
+      hint->dsCoord = FT_MulFix( hint->csCoord, scale );
+  }
+
+
+  /* initialize an invalid hint map element */
+  static void
+  cf2_hint_initZero( CF2_Hint  hint )
+  {
+    FT_ZERO( hint );
+  }
+
+
+  FT_LOCAL_DEF( FT_Bool )
+  cf2_hint_isValid( const CF2_Hint  hint )
+  {
+    return hint->flags != 0;
+  }
+
+
+  static FT_Bool
+  cf2_hint_isPair( const CF2_Hint  hint )
+  {
+    return ( hint->flags                      &
+             ( CF2_PairBottom | CF2_PairTop ) ) != 0;
+  }
+
+
+  static FT_Bool
+  cf2_hint_isPairTop( const CF2_Hint  hint )
+  {
+    return ( hint->flags & CF2_PairTop ) != 0;
+  }
+
+
+  FT_LOCAL_DEF( FT_Bool )
+  cf2_hint_isTop( const CF2_Hint  hint )
+  {
+    return ( hint->flags                    &
+             ( CF2_PairTop | CF2_GhostTop ) ) != 0;
+  }
+
+
+  FT_LOCAL_DEF( FT_Bool )
+  cf2_hint_isBottom( const CF2_Hint  hint )
+  {
+    return ( hint->flags                          &
+             ( CF2_PairBottom | CF2_GhostBottom ) ) != 0;
+  }
+
+
+  static FT_Bool
+  cf2_hint_isLocked( const CF2_Hint  hint )
+  {
+    return ( hint->flags & CF2_Locked ) != 0;
+  }
+
+
+  static FT_Bool
+  cf2_hint_isSynthetic( const CF2_Hint  hint )
+  {
+    return ( hint->flags & CF2_Synthetic ) != 0;
+  }
+
+
+  FT_LOCAL_DEF( void )
+  cf2_hint_lock( CF2_Hint  hint )
+  {
+    hint->flags |= CF2_Locked;
+  }
+
+
+  FT_LOCAL_DEF( void )
+  cf2_hintmap_init( CF2_HintMap   hintmap,
+                    CF2_Font      font,
+                    CF2_HintMap   initialMap,
+                    CF2_ArrStack  hintMoves,
+                    CF2_Fixed     scale )
+  {
+    FT_ZERO( hintmap );
+
+    /* copy parameters from font instance */
+    hintmap->hinted         = font->hinted;
+    hintmap->scale          = scale;
+    hintmap->font           = font;
+    hintmap->initialHintMap = initialMap;
+    /* will clear in `cf2_hintmap_adjustHints' */
+    hintmap->hintMoves      = hintMoves;
+  }
+
+
+  static FT_Bool
+  cf2_hintmap_isValid( const CF2_HintMap  hintmap )
+  {
+    return hintmap->isValid;
+  }
+
+
+  /* transform character space coordinate to device space using hint map */
+  static CF2_Fixed
+  cf2_hintmap_map( CF2_HintMap  hintmap,
+                   CF2_Fixed    csCoord )
+  {
+    FT_ASSERT( hintmap->isValid );  /* must call Build before Map */
+    FT_ASSERT( hintmap->lastIndex < CF2_MAX_HINT_EDGES );
+
+    if ( hintmap->count == 0 || ! hintmap->hinted )
+    {
+      /* there are no hints; use uniform scale and zero offset */
+      return FT_MulFix( csCoord, hintmap->scale );
+    }
+    else
+    {
+      /* start linear search from last hit */
+      CF2_UInt  i = hintmap->lastIndex;
+
+
+      /* search up */
+      while ( i < hintmap->count - 1                  &&
+              csCoord >= hintmap->edge[i + 1].csCoord )
+        i += 1;
+
+      /* search down */
+      while ( i > 0 && csCoord < hintmap->edge[i].csCoord )
+        i -= 1;
+
+      hintmap->lastIndex = i;
+
+      if ( i == 0 && csCoord < hintmap->edge[0].csCoord )
+      {
+        /* special case for points below first edge: use uniform scale */
+        return FT_MulFix( csCoord - hintmap->edge[0].csCoord,
+                          hintmap->scale ) +
+                 hintmap->edge[0].dsCoord;
+      }
+      else
+      {
+        /*
+         * Note: entries with duplicate csCoord are allowed.
+         * Use edge[i], the highest entry where csCoord >= entry[i].csCoord
+         */
+        return FT_MulFix( csCoord - hintmap->edge[i].csCoord,
+                          hintmap->edge[i].scale ) +
+                 hintmap->edge[i].dsCoord;
+      }
+    }
+  }
+
+
+  /*
+   * This hinting policy moves a hint pair in device space so that one of
+   * its two edges is on a device pixel boundary (its fractional part is
+   * zero).  `cf2_hintmap_insertHint' guarantees no overlap in CS
+   * space.  Ensure here that there is no overlap in DS.
+   *
+   * In the first pass, edges are adjusted relative to adjacent hints.
+   * Those that are below have already been adjusted.  Those that are
+   * above have not yet been adjusted.  If a hint above blocks an
+   * adjustment to an optimal position, we will try again in a second
+   * pass.  The second pass is top-down.
+   *
+   */
+
+  static void
+  cf2_hintmap_adjustHints( CF2_HintMap  hintmap )
+  {
+    size_t  i, j;
+
+
+    cf2_arrstack_clear( hintmap->hintMoves );      /* working storage */
+
+    /*
+     * First pass is bottom-up (font hint order) without look-ahead.
+     * Locked edges are already adjusted.
+     * Unlocked edges begin with dsCoord from `initialHintMap'.
+     * Save edges that are not optimally adjusted in `hintMoves' array,
+     * and process them in second pass.
+     */
+
+    for ( i = 0; i < hintmap->count; i++ )
+    {
+      FT_Bool  isPair = cf2_hint_isPair( &hintmap->edge[i] );
+
+
+      /* index of upper edge (same value for ghost hint) */
+      j = isPair ? i + 1 : i;
+
+      FT_ASSERT( j < hintmap->count );
+      FT_ASSERT( cf2_hint_isValid( &hintmap->edge[i] ) );
+      FT_ASSERT( cf2_hint_isValid( &hintmap->edge[j] ) );
+      FT_ASSERT( cf2_hint_isLocked( &hintmap->edge[i] ) ==
+                   cf2_hint_isLocked( &hintmap->edge[j] ) );
+
+      if ( !cf2_hint_isLocked( &hintmap->edge[i] ) )
+      {
+        /* hint edge is not locked, we can adjust it */
+        CF2_Fixed  fracDown = cf2_fixedFraction( hintmap->edge[i].dsCoord );
+        CF2_Fixed  fracUp   = cf2_fixedFraction( hintmap->edge[j].dsCoord );
+
+        /* calculate all four possibilities; moves down are negative */
+        CF2_Fixed  downMoveDown = 0 - fracDown;
+        CF2_Fixed  upMoveDown   = 0 - fracUp;
+        CF2_Fixed  downMoveUp   = fracDown == 0
+                                    ? 0
+                                    : cf2_intToFixed( 1 ) - fracDown;
+        CF2_Fixed  upMoveUp     = fracUp == 0
+                                    ? 0
+                                    : cf2_intToFixed( 1 ) - fracUp;
+
+        /* smallest move up */
+        CF2_Fixed  moveUp   = FT_MIN( downMoveUp, upMoveUp );
+        /* smallest move down */
+        CF2_Fixed  moveDown = FT_MAX( downMoveDown, upMoveDown );
+
+        /* final amount to move edge or edge pair */
+        CF2_Fixed  move;
+
+        CF2_Fixed  downMinCounter = CF2_MIN_COUNTER;
+        CF2_Fixed  upMinCounter   = CF2_MIN_COUNTER;
+        FT_Bool    saveEdge       = FALSE;
+
+
+        /* minimum counter constraint doesn't apply when adjacent edges */
+        /* are synthetic                                                */
+        /* TODO: doesn't seem a big effect; for now, reduce the code    */
+#if 0
+        if ( i == 0                                        ||
+             cf2_hint_isSynthetic( &hintmap->edge[i - 1] ) )
+          downMinCounter = 0;
+
+        if ( j >= hintmap->count - 1                       ||
+             cf2_hint_isSynthetic( &hintmap->edge[j + 1] ) )
+          upMinCounter = 0;
+#endif
+
+        /* is there room to move up?                                    */
+        /* there is if we are at top of array or the next edge is at or */
+        /* beyond proposed move up?                                     */
+        if ( j >= hintmap->count - 1                            ||
+             hintmap->edge[j + 1].dsCoord >=
+               hintmap->edge[j].dsCoord + moveUp + upMinCounter )
+        {
+          /* there is room to move up; is there also room to move down? */
+          if ( i == 0                                                 ||
+               hintmap->edge[i - 1].dsCoord <=
+                 hintmap->edge[i].dsCoord + moveDown - downMinCounter )
+          {
+            /* move smaller absolute amount */
+            move = ( -moveDown < moveUp ) ? moveDown : moveUp;  /* optimum */
+          }
+          else
+            move = moveUp;
+        }
+        else
+        {
+          /* is there room to move down? */
+          if ( i == 0                                                 ||
+               hintmap->edge[i - 1].dsCoord <=
+                 hintmap->edge[i].dsCoord + moveDown - downMinCounter )
+          {
+            move     = moveDown;
+            saveEdge = moveUp < -moveDown;  /* true if non-optimum move */
+          }
+          else
+          {
+            /* no room to move either way without overlapping or reducing */
+            /* the counter too much                                       */
+            move     = 0;
+            saveEdge = TRUE;
+          }
+        }
+
+        /* Identify non-moves and moves down that aren't optimal, and save */
+        /* them for second pass.                                           */
+        /* Do this only if there is an unlocked edge above (which could    */
+        /* possibly move).                                                 */
+        if ( saveEdge                                    &&
+             j < hintmap->count - 1                      &&
+             !cf2_hint_isLocked( &hintmap->edge[j + 1] ) )
+        {
+          CF2_HintMoveRec  savedMove;
+
+
+          savedMove.j      = j;
+          /* desired adjustment in second pass */
+          savedMove.moveUp = moveUp - move;
+
+          cf2_arrstack_push( hintmap->hintMoves, &savedMove );
+        }
+
+        /* move the edge(s) */
+        hintmap->edge[i].dsCoord += move;
+        if ( isPair )
+          hintmap->edge[j].dsCoord += move;
+      }
+
+      /* assert there are no overlaps in device space */
+      FT_ASSERT( i == 0                                                   ||
+                 hintmap->edge[i - 1].dsCoord <= hintmap->edge[i].dsCoord );
+      FT_ASSERT( i < j                                                ||
+                 hintmap->edge[i].dsCoord <= hintmap->edge[j].dsCoord );
+
+      /* adjust the scales, avoiding divide by zero */
+      if ( i > 0 )
+      {
+        if ( hintmap->edge[i].csCoord != hintmap->edge[i - 1].csCoord )
+          hintmap->edge[i - 1].scale =
+            FT_DivFix(
+              hintmap->edge[i].dsCoord - hintmap->edge[i - 1].dsCoord,
+              hintmap->edge[i].csCoord - hintmap->edge[i - 1].csCoord );
+      }
+
+      if ( isPair )
+      {
+        if ( hintmap->edge[j].csCoord != hintmap->edge[j - 1].csCoord )
+          hintmap->edge[j - 1].scale =
+            FT_DivFix(
+              hintmap->edge[j].dsCoord - hintmap->edge[j - 1].dsCoord,
+              hintmap->edge[j].csCoord - hintmap->edge[j - 1].csCoord );
+
+        i += 1;     /* skip upper edge on next loop */
+      }
+    }
+
+    /* second pass tries to move non-optimal hints up, in case there is */
+    /* room now                                                         */
+    for ( i = cf2_arrstack_size( hintmap->hintMoves ); i > 0; i-- )
+    {
+      CF2_HintMove  hintMove = (CF2_HintMove)
+                      cf2_arrstack_getPointer( hintmap->hintMoves, i - 1 );
+
+
+      j = hintMove->j;
+
+      /* this was tested before the push, above */
+      FT_ASSERT( j < hintmap->count - 1 );
+
+      /* is there room to move up? */
+      if ( hintmap->edge[j + 1].dsCoord >=
+             hintmap->edge[j].dsCoord + hintMove->moveUp + CF2_MIN_COUNTER )
+      {
+        /* there is more room now, move edge up */
+        hintmap->edge[j].dsCoord += hintMove->moveUp;
+
+        if ( cf2_hint_isPair( &hintmap->edge[j] ) )
+        {
+          FT_ASSERT( j > 0 );
+          hintmap->edge[j - 1].dsCoord += hintMove->moveUp;
+        }
+      }
+    }
+  }
+
+
+  /* insert hint edges into map, sorted by csCoord */
+  static void
+  cf2_hintmap_insertHint( CF2_HintMap  hintmap,
+                          CF2_Hint     bottomHintEdge,
+                          CF2_Hint     topHintEdge )
+  {
+    CF2_UInt  indexInsert;
+
+    /* set default values, then check for edge hints */
+    FT_Bool   isPair         = TRUE;
+    CF2_Hint  firstHintEdge  = bottomHintEdge;
+    CF2_Hint  secondHintEdge = topHintEdge;
+
+
+    /* one or none of the input params may be invalid when dealing with */
+    /* edge hints; at least one edge must be valid                      */
+    FT_ASSERT( cf2_hint_isValid( bottomHintEdge ) ||
+               cf2_hint_isValid( topHintEdge )    );
+
+    /* determine how many and which edges to insert */
+    if ( !cf2_hint_isValid( bottomHintEdge ) )
+    {
+      /* insert only the top edge */
+      firstHintEdge = topHintEdge;
+      isPair        = FALSE;
+    }
+    else if ( !cf2_hint_isValid( topHintEdge ) )
+    {
+      /* insert only the bottom edge */
+      isPair = FALSE;
+    }
+
+    /* paired edges must be in proper order */
+    FT_ASSERT( !isPair                                         ||
+               topHintEdge->csCoord >= bottomHintEdge->csCoord );
+
+    /* linear search to find index value of insertion point */
+    indexInsert = 0;
+    for ( ; indexInsert < hintmap->count; indexInsert++ )
+    {
+      if ( hintmap->edge[indexInsert].csCoord > firstHintEdge->csCoord )
+        break;
+    }
+
+    /*
+     * Discard any hints that overlap in character space.  Most often,
+     * this is while building the initial map, but in theory, it can also
+     * occur because of darkening.
+     *
+     */
+    if ( indexInsert < hintmap->count )
+    {
+      /* we are inserting before an existing edge:              */
+      /* verify that a new pair does not straddle the next edge */
+      if ( isPair                                                       &&
+           hintmap->edge[indexInsert].csCoord < secondHintEdge->csCoord )
+        return; /* ignore overlapping stem hint */
+
+      /* verify that we are not inserting between paired edges */
+      if ( cf2_hint_isPairTop( &hintmap->edge[indexInsert] ) )
+        return; /* ignore overlapping stem hint */
+    }
+
+    /* recompute device space locations using initial hint map */
+    if ( cf2_hintmap_isValid( hintmap->initialHintMap ) &&
+         !cf2_hint_isLocked( firstHintEdge )            )
+    {
+      if ( isPair )
+      {
+        /* Use hint map to position the center of stem, and nominal scale */
+        /* to position the two edges.  This preserves the stem width.     */
+        CF2_Fixed  midpoint  = cf2_hintmap_map(
+                                 hintmap->initialHintMap,
+                                 ( secondHintEdge->csCoord +
+                                   firstHintEdge->csCoord ) / 2 );
+        CF2_Fixed  halfWidth = FT_MulFix(
+                                 ( secondHintEdge->csCoord -
+                                   firstHintEdge->csCoord ) / 2,
+                                 hintmap->scale );
+
+
+        firstHintEdge->dsCoord  = midpoint - halfWidth;
+        secondHintEdge->dsCoord = midpoint + halfWidth;
+      }
+      else
+        firstHintEdge->dsCoord = cf2_hintmap_map( hintmap->initialHintMap,
+                                                  firstHintEdge->csCoord );
+    }
+
+    /* discard any hints that overlap in device space; this can occur */
+    /* because locked hints have been moved to align with blue zones  */
+    if ( indexInsert > 0 )
+    {
+      /* we are inserting after an existing edge */
+      if ( firstHintEdge->dsCoord < hintmap->edge[indexInsert - 1].dsCoord )
+        return;
+    }
+
+    if ( indexInsert < hintmap->count )
+    {
+      /* we are inserting before an existing edge */
+      if ( isPair )
+      {
+        if ( secondHintEdge->dsCoord > hintmap->edge[indexInsert].dsCoord )
+          return;
+      }
+      else
+      {
+        if ( firstHintEdge->dsCoord > hintmap->edge[indexInsert].dsCoord )
+          return;
+      }
+    }
+
+    /* make room to insert */
+    {
+      CF2_Int  iSrc = hintmap->count - 1;
+      CF2_Int  iDst = isPair ? hintmap->count + 1 : hintmap->count;
+
+      CF2_Int  count = hintmap->count - indexInsert;
+
+
+      if ( iDst >= CF2_MAX_HINT_EDGES )
+      {
+        FT_TRACE4(( "cf2_hintmap_insertHint: too many hintmaps\n" ));
+        return;
+      }
+
+      while ( count-- )
+        hintmap->edge[iDst--] = hintmap->edge[iSrc--];
+
+      /* insert first edge */
+      hintmap->edge[indexInsert] = *firstHintEdge;         /* copy struct */
+      hintmap->count += 1;
+
+      if ( isPair )
+      {
+        /* insert second edge */
+        hintmap->edge[indexInsert + 1] = *secondHintEdge;  /* copy struct */
+        hintmap->count                += 1;
+      }
+    }
+
+    return;
+  }
+
+
+  /*
+   * Build a map from hints and mask.
+   *
+   * This function may recur one level if `hintmap->initialHintMap' is not yet
+   * valid.
+   * If `initialMap' is true, simply build initial map.
+   *
+   * Synthetic hints are used in two ways.  A hint at zero is inserted, if
+   * needed, in the initial hint map, to prevent translations from
+   * propagating across the origin.  If synthetic em box hints are enabled
+   * for ideographic dictionaries, then they are inserted in all hint
+   * maps, including the initial one.
+   *
+   */
+  FT_LOCAL_DEF( void )
+  cf2_hintmap_build( CF2_HintMap   hintmap,
+                     CF2_ArrStack  hStemHintArray,
+                     CF2_ArrStack  vStemHintArray,
+                     CF2_HintMask  hintMask,
+                     CF2_Fixed     hintOrigin,
+                     FT_Bool       initialMap )
+  {
+    FT_Byte*  maskPtr;
+
+    CF2_Font         font = hintmap->font;
+    CF2_HintMaskRec  tempHintMask;
+
+    size_t   bitCount, i;
+    FT_Byte  maskByte;
+
+
+    /* check whether initial map is constructed */
+    if ( !initialMap && !cf2_hintmap_isValid( hintmap->initialHintMap ) )
+    {
+      /* make recursive call with initialHintMap and temporary mask; */
+      /* temporary mask will get all bits set, below */
+      cf2_hintmask_init( &tempHintMask, hintMask->error );
+      cf2_hintmap_build( hintmap->initialHintMap,
+                         hStemHintArray,
+                         vStemHintArray,
+                         &tempHintMask,
+                         hintOrigin,
+                         TRUE );
+    }
+
+    if ( !cf2_hintmask_isValid( hintMask ) )
+    {
+      /* without a hint mask, assume all hints are active */
+      cf2_hintmask_setAll( hintMask,
+                           cf2_arrstack_size( hStemHintArray ) +
+                             cf2_arrstack_size( vStemHintArray ) );
+    }
+
+    /* begin by clearing the map */
+    hintmap->count     = 0;
+    hintmap->lastIndex = 0;
+
+    /* make a copy of the hint mask so we can modify it */
+    tempHintMask = *hintMask;
+    maskPtr      = cf2_hintmask_getMaskPtr( &tempHintMask );
+
+    /* use the hStem hints only, which are first in the mask */
+    /* TODO: compare this to cffhintmaskGetBitCount */
+    bitCount = cf2_arrstack_size( hStemHintArray );
+
+    /* synthetic embox hints get highest priority */
+    if ( font->blues.doEmBoxHints )
+    {
+      CF2_HintRec  dummy;
+
+
+      cf2_hint_initZero( &dummy );   /* invalid hint map element */
+
+      /* ghost bottom */
+      cf2_hintmap_insertHint( hintmap,
+                              &font->blues.emBoxBottomEdge,
+                              &dummy );
+      /* ghost top */
+      cf2_hintmap_insertHint( hintmap,
+                              &dummy,
+                              &font->blues.emBoxTopEdge );
+    }
+
+    /* insert hints captured by a blue zone or already locked (higher */
+    /* priority)                                                      */
+    for ( i = 0, maskByte = 0x80; i < bitCount; i++ )
+    {
+      if ( maskByte & *maskPtr )
+      {
+        /* expand StemHint into two `CF2_Hint' elements */
+        CF2_HintRec  bottomHintEdge, topHintEdge;
+
+
+        cf2_hint_init( &bottomHintEdge,
+                       hStemHintArray,
+                       i,
+                       font,
+                       hintOrigin,
+                       hintmap->scale,
+                       TRUE /* bottom */ );
+        cf2_hint_init( &topHintEdge,
+                       hStemHintArray,
+                       i,
+                       font,
+                       hintOrigin,
+                       hintmap->scale,
+                       FALSE /* top */ );
+
+        if ( cf2_hint_isLocked( &bottomHintEdge ) ||
+             cf2_hint_isLocked( &topHintEdge )    ||
+             cf2_blues_capture( &font->blues,
+                                &bottomHintEdge,
+                                &topHintEdge )   )
+        {
+          /* insert captured hint into map */
+          cf2_hintmap_insertHint( hintmap, &bottomHintEdge, &topHintEdge );
+
+          *maskPtr &= ~maskByte;      /* turn off the bit for this hint */
+        }
+      }
+
+      if ( ( i & 7 ) == 7 )
+      {
+        /* move to next mask byte */
+        maskPtr++;
+        maskByte = 0x80;
+      }
+      else
+        maskByte >>= 1;
+    }
+
+    /* initial hint map includes only captured hints plus maybe one at 0 */
+
+    /*
+     * TODO: There is a problem here because we are trying to build a
+     *       single hint map containing all captured hints.  It is
+     *       possible for there to be conflicts between captured hints,
+     *       either because of darkening or because the hints are in
+     *       separate hint zones (we are ignoring hint zones for the
+     *       initial map).  An example of the latter is MinionPro-Regular
+     *       v2.030 glyph 883 (Greek Capital Alpha with Psili) at 15ppem.
+     *       A stem hint for the psili conflicts with the top edge hint
+     *       for the base character.  The stem hint gets priority because
+     *       of its sort order.  In glyph 884 (Greek Capital Alpha with
+     *       Psili and Oxia), the top of the base character gets a stem
+     *       hint, and the psili does not.  This creates different initial
+     *       maps for the two glyphs resulting in different renderings of
+     *       the base character.  Will probably defer this either as not
+     *       worth the cost or as a font bug.  I don't think there is any
+     *       good reason for an accent to be captured by an alignment
+     *       zone.  -darnold 2/12/10
+     */
+
+    if ( initialMap )
+    {
+      /* Apply a heuristic that inserts a point for (0,0), unless it's     */
+      /* already covered by a mapping.  This locks the baseline for glyphs */
+      /* that have no baseline hints.                                      */
+
+      if ( hintmap->count == 0                           ||
+           hintmap->edge[0].csCoord > 0                  ||
+           hintmap->edge[hintmap->count - 1].csCoord < 0 )
+      {
+        /* all edges are above 0 or all edges are below 0; */
+        /* construct a locked edge hint at 0               */
+
+        CF2_HintRec  edge, invalid;
+
+
+        cf2_hint_initZero( &edge );
+
+        edge.flags = CF2_GhostBottom |
+                     CF2_Locked      |
+                     CF2_Synthetic;
+        edge.scale = hintmap->scale;
+
+        cf2_hint_initZero( &invalid );
+        cf2_hintmap_insertHint( hintmap, &edge, &invalid );
+      }
+    }
+    else
+    {
+      /* insert remaining hints */
+
+      maskPtr = cf2_hintmask_getMaskPtr( &tempHintMask );
+
+      for ( i = 0, maskByte = 0x80; i < bitCount; i++ )
+      {
+        if ( maskByte & *maskPtr )
+        {
+          CF2_HintRec  bottomHintEdge, topHintEdge;
+
+
+          cf2_hint_init( &bottomHintEdge,
+                         hStemHintArray,
+                         i,
+                         font,
+                         hintOrigin,
+                         hintmap->scale,
+                         TRUE /* bottom */ );
+          cf2_hint_init( &topHintEdge,
+                         hStemHintArray,
+                         i,
+                         font,
+                         hintOrigin,
+                         hintmap->scale,
+                         FALSE /* top */ );
+
+          cf2_hintmap_insertHint( hintmap, &bottomHintEdge, &topHintEdge );
+        }
+
+        if ( ( i & 7 ) == 7 )
+        {
+          /* move to next mask byte */
+          maskPtr++;
+          maskByte = 0x80;
+        }
+        else
+          maskByte >>= 1;
+      }
+    }
+
+    /*
+     * Note: The following line is a convenient place to break when
+     *       debugging hinting.  Examine `hintmap->edge' for the list of
+     *       enabled hints, then step over the call to see the effect of
+     *       adjustment.  We stop here first on the recursive call that
+     *       creates the initial map, and then on each counter group and
+     *       hint zone.
+     */
+
+    /* adjust positions of hint edges that are not locked to blue zones */
+    cf2_hintmap_adjustHints( hintmap );
+
+    /* save the position of all hints that were used in this hint map; */
+    /* if we use them again, we'll locate them in the same position    */
+    if ( !initialMap )
+    {
+      for ( i = 0; i < hintmap->count; i++ )
+      {
+        if ( !cf2_hint_isSynthetic( &hintmap->edge[i] ) )
+        {
+          /* Note: include both valid and invalid edges            */
+          /* Note: top and bottom edges are copied back separately */
+          CF2_StemHint  stemhint = (CF2_StemHint)
+                          cf2_arrstack_getPointer( hStemHintArray,
+                                                   hintmap->edge[i].index );
+
+
+          if ( cf2_hint_isTop( &hintmap->edge[i] ) )
+            stemhint->maxDS = hintmap->edge[i].dsCoord;
+          else
+            stemhint->minDS = hintmap->edge[i].dsCoord;
+
+          stemhint->used = TRUE;
+        }
+      }
+    }
+
+    /* hint map is ready to use */
+    hintmap->isValid = TRUE;
+
+    /* remember this mask has been used */
+    cf2_hintmask_setNew( hintMask, FALSE );
+  }
+
+
+  FT_LOCAL_DEF( void )
+  cf2_glyphpath_init( CF2_GlyphPath         glyphpath,
+                      CF2_Font              font,
+                      CF2_OutlineCallbacks  callbacks,
+                      CF2_Fixed             scaleY,
+                      /* CF2_Fixed  hShift, */
+                      CF2_ArrStack          hStemHintArray,
+                      CF2_ArrStack          vStemHintArray,
+                      CF2_HintMask          hintMask,
+                      CF2_Fixed             hintOriginY,
+                      const CF2_Blues       blues,
+                      const FT_Vector*      fractionalTranslation )
+  {
+    FT_ZERO( glyphpath );
+
+    glyphpath->font      = font;
+    glyphpath->callbacks = callbacks;
+
+    cf2_arrstack_init( &glyphpath->hintMoves,
+                       font->memory,
+                       &font->error,
+                       sizeof ( CF2_HintMoveRec ) );
+
+    cf2_hintmap_init( &glyphpath->initialHintMap,
+                      font,
+                      &glyphpath->initialHintMap,
+                      &glyphpath->hintMoves,
+                      scaleY );
+    cf2_hintmap_init( &glyphpath->firstHintMap,
+                      font,
+                      &glyphpath->initialHintMap,
+                      &glyphpath->hintMoves,
+                      scaleY );
+    cf2_hintmap_init( &glyphpath->hintMap,
+                      font,
+                      &glyphpath->initialHintMap,
+                      &glyphpath->hintMoves,
+                      scaleY );
+
+    glyphpath->scaleX = font->innerTransform.a;
+    glyphpath->scaleC = font->innerTransform.c;
+    glyphpath->scaleY = font->innerTransform.d;
+
+    glyphpath->fractionalTranslation = *fractionalTranslation;
+
+#if 0
+    glyphpath->hShift = hShift;       /* for fauxing */
+#endif
+
+    glyphpath->hStemHintArray = hStemHintArray;
+    glyphpath->vStemHintArray = vStemHintArray;
+    glyphpath->hintMask       = hintMask;      /* ptr to current mask */
+    glyphpath->hintOriginY    = hintOriginY;
+    glyphpath->blues          = blues;
+    glyphpath->darken         = font->darkened; /* TODO: should we make copies? */
+    glyphpath->xOffset        = font->darkenX;
+    glyphpath->yOffset        = font->darkenY;
+    glyphpath->miterLimit     = 2 * FT_MAX(
+                                     cf2_fixedAbs( glyphpath->xOffset ),
+                                     cf2_fixedAbs( glyphpath->yOffset ) );
+
+    /* .1 character space unit */
+    glyphpath->snapThreshold = cf2_floatToFixed( 0.1f );
+
+    glyphpath->moveIsPending = TRUE;
+    glyphpath->pathIsOpen    = FALSE;
+    glyphpath->elemIsQueued  = FALSE;
+  }
+
+
+  FT_LOCAL_DEF( void )
+  cf2_glyphpath_finalize( CF2_GlyphPath  glyphpath )
+  {
+    cf2_arrstack_finalize( &glyphpath->hintMoves );
+  }
+
+
+  /*
+   * Hint point in y-direction and apply outerTransform.
+   * Input `current' hint map (which is actually delayed by one element).
+   * Input x,y point in Character Space.
+   * Output x,y point in Device Space, including translation.
+   */
+  static void
+  cf2_glyphpath_hintPoint( CF2_GlyphPath  glyphpath,
+                           CF2_HintMap    hintmap,
+                           FT_Vector*     ppt,
+                           CF2_Fixed      x,
+                           CF2_Fixed      y )
+  {
+    FT_Vector  pt;   /* hinted point in upright DS */
+
+
+    pt.x = FT_MulFix( glyphpath->scaleX, x ) +
+             FT_MulFix( glyphpath->scaleC, y );
+    pt.y = cf2_hintmap_map( hintmap, y );
+
+    ppt->x = FT_MulFix( glyphpath->font->outerTransform.a, pt.x )   +
+               FT_MulFix( glyphpath->font->outerTransform.c, pt.y ) +
+               glyphpath->fractionalTranslation.x;
+    ppt->y = FT_MulFix( glyphpath->font->outerTransform.b, pt.x )   +
+               FT_MulFix( glyphpath->font->outerTransform.d, pt.y ) +
+               glyphpath->fractionalTranslation.y;
+  }
+
+
+  /*
+   * From two line segments, (u1,u2) and (v1,v2), compute a point of
+   * intersection on the corresponding lines.
+   * Return false if no intersection is found, or if the intersection is
+   * too far away from the ends of the line segments, u2 and v1.
+   *
+   */
+  static FT_Bool
+  cf2_glyphpath_computeIntersection( CF2_GlyphPath     glyphpath,
+                                     const FT_Vector*  u1,
+                                     const FT_Vector*  u2,
+                                     const FT_Vector*  v1,
+                                     const FT_Vector*  v2,
+                                     FT_Vector*        intersection )
+  {
+    /*
+     * Let `u' be a zero-based vector from the first segment, `v' from the
+     * second segment.
+     * Let `w 'be the zero-based vector from `u1' to `v1'.
+     * `perp' is the `perpendicular dot product'; see
+     * http://mathworld.wolfram.com/PerpDotProduct.html.
+     * `s' is the parameter for the parametric line for the first segment
+     * (`u').
+     *
+     * See notation in
+     * http://softsurfer.com/Archive/algorithm_0104/algorithm_0104B.htm.
+     * Calculations are done in 16.16, but must handle the squaring of
+     * line lengths in character space.  We scale all vectors by 1/32 to
+     * avoid overflow.  This allows values up to 4095 to be squared.  The
+     * scale factor cancels in the divide.
+     *
+     * TODO: the scale factor could be computed from UnitsPerEm.
+     *
+     */
+
+#define cf2_perp( a, b )                                    \
+          ( FT_MulFix( a.x, b.y ) - FT_MulFix( a.y, b.x ) )
+
+  /* round and divide by 32 */
+#define CF2_CS_SCALE( x )         \
+          ( ( (x) + 0x10 ) >> 5 )
+
+    FT_Vector  u, v, w;      /* scaled vectors */
+    CF2_Fixed  denominator, s;
+
+
+    u.x = CF2_CS_SCALE( u2->x - u1->x );
+    u.y = CF2_CS_SCALE( u2->y - u1->y );
+    v.x = CF2_CS_SCALE( v2->x - v1->x );
+    v.y = CF2_CS_SCALE( v2->y - v1->y );
+    w.x = CF2_CS_SCALE( v1->x - u1->x );
+    w.y = CF2_CS_SCALE( v1->y - u1->y );
+
+    denominator = cf2_perp( u, v );
+
+    if ( denominator == 0 )
+      return FALSE;           /* parallel or coincident lines */
+
+    s = FT_DivFix( cf2_perp( w, v ), denominator );
+
+    intersection->x = u1->x + FT_MulFix( s, u2->x - u1->x );
+    intersection->y = u1->y + FT_MulFix( s, u2->y - u1->y );
+
+    /*
+     * Special case snapping for horizontal and vertical lines.
+     * This cleans up intersections and reduces problems with winding
+     * order detection.
+     * Sample case is sbc cd KozGoPr6N-Medium.otf 20 16685.
+     * Note: these calculations are in character space.
+     *
+     */
+
+    if ( u1->x == u2->x                                                     &&
+         cf2_fixedAbs( intersection->x - u1->x ) < glyphpath->snapThreshold )
+      intersection->x = u1->x;
+    if ( u1->y == u2->y                                                     &&
+         cf2_fixedAbs( intersection->y - u1->y ) < glyphpath->snapThreshold )
+      intersection->y = u1->y;
+
+    if ( v1->x == v2->x                                                     &&
+         cf2_fixedAbs( intersection->x - v1->x ) < glyphpath->snapThreshold )
+      intersection->x = v1->x;
+    if ( v1->y == v2->y                                                     &&
+         cf2_fixedAbs( intersection->y - v1->y ) < glyphpath->snapThreshold )
+      intersection->y = v1->y;
+
+    /* limit the intersection distance from midpoint of u2 and v1 */
+    if ( cf2_fixedAbs( intersection->x - ( u2->x + v1->x ) / 2 ) >
+           glyphpath->miterLimit                                   ||
+         cf2_fixedAbs( intersection->y - ( u2->y + v1->y ) / 2 ) >
+           glyphpath->miterLimit                                   )
+      return FALSE;
+
+    return TRUE;
+  }
+
+
+  /*
+   * Push the cached element (glyphpath->prevElem*) to the outline
+   * consumer.  When a darkening offset is used, the end point of the
+   * cached element may be adjusted to an intersection point or it may be
+   * connected by a line to the current element.  This calculation must
+   * use a HintMap that was valid at the time the element was saved.  For
+   * the first point in a subpath, that is a saved HintMap.  For most
+   * elements, it just means the caller has delayed building a HintMap
+   * from the current HintMask.
+   *
+   * Transform each point with outerTransform and call the outline
+   * callbacks.  This is a general 3x3 transform:
+   *
+   *   x' = a*x + c*y + tx, y' = b*x + d*y + ty
+   *
+   * but it uses 4 elements from CF2_Font and the translation part
+   * from CF2_GlyphPath.
+   *
+   */
+  static void
+  cf2_glyphpath_pushPrevElem( CF2_GlyphPath  glyphpath,
+                              CF2_HintMap    hintmap,
+                              FT_Vector*     nextP0,
+                              FT_Vector      nextP1,
+                              FT_Bool        close )
+  {
+    CF2_CallbackParamsRec  params;
+
+    FT_Vector*  prevP0;
+    FT_Vector*  prevP1;
+
+    FT_Vector  intersection    = { 0, 0 };
+    FT_Bool    useIntersection = FALSE;
+
+
+    FT_ASSERT( glyphpath->prevElemOp == CF2_PathOpLineTo ||
+               glyphpath->prevElemOp == CF2_PathOpCubeTo );
+
+    if ( glyphpath->prevElemOp == CF2_PathOpLineTo )
+    {
+      prevP0 = &glyphpath->prevElemP0;
+      prevP1 = &glyphpath->prevElemP1;
+    }
+    else
+    {
+      prevP0 = &glyphpath->prevElemP2;
+      prevP1 = &glyphpath->prevElemP3;
+    }
+
+    /* optimization: if previous and next elements are offset by the same */
+    /* amount, then there will be no gap, and no need to compute an       */
+    /* intersection.                                                      */
+    if ( prevP1->x != nextP0->x || prevP1->y != nextP0->y )
+    {
+      /* previous element does not join next element:             */
+      /* adjust end point of previous element to the intersection */
+      useIntersection = cf2_glyphpath_computeIntersection( glyphpath,
+                                                           prevP0,
+                                                           prevP1,
+                                                           nextP0,
+                                                           &nextP1,
+                                                           &intersection );
+      if ( useIntersection )
+      {
+        /* modify the last point of the cached element (either line or */
+        /* curve)                                                      */
+        *prevP1 = intersection;
+      }
+    }
+
+    params.pt0 = glyphpath->currentDS;
+
+    switch( glyphpath->prevElemOp )
+    {
+    case CF2_PathOpLineTo:
+      params.op = CF2_PathOpLineTo;
+
+      /* note: pt2 and pt3 are unused */
+      cf2_glyphpath_hintPoint( glyphpath,
+                               hintmap,
+                               &params.pt1,
+                               glyphpath->prevElemP1.x,
+                               glyphpath->prevElemP1.y );
+
+      glyphpath->callbacks->lineTo( glyphpath->callbacks, &params );
+
+      glyphpath->currentDS = params.pt1;
+
+      break;
+
+    case CF2_PathOpCubeTo:
+      params.op = CF2_PathOpCubeTo;
+
+      /* TODO: should we intersect the interior joins (p1-p2 and p2-p3)? */
+      cf2_glyphpath_hintPoint( glyphpath,
+                               hintmap,
+                               &params.pt1,
+                               glyphpath->prevElemP1.x,
+                               glyphpath->prevElemP1.y );
+      cf2_glyphpath_hintPoint( glyphpath,
+                               hintmap,
+                               &params.pt2,
+                               glyphpath->prevElemP2.x,
+                               glyphpath->prevElemP2.y );
+      cf2_glyphpath_hintPoint( glyphpath,
+                               hintmap,
+                               &params.pt3,
+                               glyphpath->prevElemP3.x,
+                               glyphpath->prevElemP3.y );
+
+      glyphpath->callbacks->cubeTo( glyphpath->callbacks, &params );
+
+      glyphpath->currentDS = params.pt3;
+
+      break;
+    }
+
+    if ( !useIntersection || close )
+    {
+      /* insert connecting line between end of previous element and start */
+      /* of current one                                                   */
+      /* note: at the end of a subpath, we might do both, so use `nextP0' */
+      /* before we change it, below                                       */
+
+      cf2_glyphpath_hintPoint( glyphpath,
+                               hintmap,
+                               &params.pt1,
+                               nextP0->x,
+                               nextP0->y );
+
+      if ( params.pt1.x != glyphpath->currentDS.x ||
+           params.pt1.y != glyphpath->currentDS.y )
+      {
+        /* length is nonzero */
+        params.op  = CF2_PathOpLineTo;
+        params.pt0 = glyphpath->currentDS;
+
+        /* note: pt2 and pt3 are unused */
+        glyphpath->callbacks->lineTo( glyphpath->callbacks, &params );
+
+        glyphpath->currentDS = params.pt1;
+      }
+    }
+
+    if ( useIntersection )
+    {
+      /* return intersection point to caller */
+      *nextP0 = intersection;
+    }
+  }
+
+
+  /* push a MoveTo element based on current point and offset of current */
+  /* element                                                            */
+  static void
+  cf2_glyphpath_pushMove( CF2_GlyphPath  glyphpath,
+                          FT_Vector      start )
+  {
+    CF2_CallbackParamsRec  params;
+
+
+    params.op  = CF2_PathOpMoveTo;
+    params.pt0 = glyphpath->currentDS;
+
+    /* Test if move has really happened yet; it would have called */
+    /* `cf2_hintmap_build' to set `isValid'.                   */
+    if ( !cf2_hintmap_isValid( &glyphpath->hintMap ) )
+    {
+      /* we are here iff first subpath is missing a moveto operator: */
+      /* synthesize first moveTo to finish initialization of hintMap */
+      cf2_glyphpath_moveTo( glyphpath,
+                            glyphpath->start.x,
+                            glyphpath->start.y );
+    }
+
+    cf2_glyphpath_hintPoint( glyphpath,
+                             &glyphpath->hintMap,
+                             &params.pt1,
+                             start.x,
+                             start.y );
+
+    /* note: pt2 and pt3 are unused */
+    glyphpath->callbacks->moveTo( glyphpath->callbacks, &params );
+
+    glyphpath->currentDS    = params.pt1;
+    glyphpath->offsetStart0 = start;
+  }
+
+
+  /*
+   * All coordinates are in character space.
+   * On input, (x1, y1) and (x2, y2) give line segment.
+   * On output, (x, y) give offset vector.
+   * We use a piecewise approximation to trig functions.
+   *
+   * TODO: Offset true perpendicular and proper length
+   *       supply the y-translation for hinting here, too,
+   *       that adds yOffset unconditionally to *y.
+   */
+  static void
+  cf2_glyphpath_computeOffset( CF2_GlyphPath  glyphpath,
+                               CF2_Fixed      x1,
+                               CF2_Fixed      y1,
+                               CF2_Fixed      x2,
+                               CF2_Fixed      y2,
+                               CF2_Fixed*     x,
+                               CF2_Fixed*     y )
+  {
+    CF2_Fixed  dx = x2 - x1;
+    CF2_Fixed  dy = y2 - y1;
+
+
+    /* note: negative offsets don't work here; negate deltas to change */
+    /* quadrants, below                                                */
+    if ( glyphpath->font->reverseWinding )
+    {
+      dx = -dx;
+      dy = -dy;
+    }
+
+    *x = *y = 0;
+
+    if ( !glyphpath->darken )
+        return;
+
+    /* add momentum for this path element */
+    glyphpath->callbacks->windingMomentum +=
+      cf2_getWindingMomentum( x1, y1, x2, y2 );
+
+    /* note: allow mixed integer and fixed multiplication here */
+    if ( dx >= 0 )
+    {
+      if ( dy >= 0 )
+      {
+        /* first quadrant, +x +y */
+
+        if ( dx > 2 * dy )
+        {
+          /* +x */
+          *x = 0;
+          *y = 0;
+        }
+        else if ( dy > 2 * dx )
+        {
+          /* +y */
+          *x = glyphpath->xOffset;
+          *y = glyphpath->yOffset;
+        }
+        else
+        {
+          /* +x +y */
+          *x = FT_MulFix( cf2_floatToFixed( 0.7 ),
+                          glyphpath->xOffset );
+          *y = FT_MulFix( cf2_floatToFixed( 1.0 - 0.7 ),
+                          glyphpath->yOffset );
+        }
+      }
+      else
+      {
+        /* fourth quadrant, +x -y */
+
+        if ( dx > -2 * dy )
+        {
+          /* +x */
+          *x = 0;
+          *y = 0;
+        }
+        else if ( -dy > 2 * dx )
+        {
+          /* -y */
+          *x = -glyphpath->xOffset;
+          *y = glyphpath->yOffset;
+        }
+        else
+        {
+          /* +x -y */
+          *x = FT_MulFix( cf2_floatToFixed( -0.7 ),
+                          glyphpath->xOffset );
+          *y = FT_MulFix( cf2_floatToFixed( 1.0 - 0.7 ),
+                          glyphpath->yOffset );
+        }
+      }
+    }
+    else
+    {
+      if ( dy >= 0 )
+      {
+        /* second quadrant, -x +y */
+
+        if ( -dx > 2 * dy )
+        {
+          /* -x */
+          *x = 0;
+          *y = 2 * glyphpath->yOffset;
+        }
+        else if ( dy > -2 * dx )
+        {
+          /* +y */
+          *x = glyphpath->xOffset;
+          *y = glyphpath->yOffset;
+        }
+        else
+        {
+          /* -x +y */
+          *x = FT_MulFix( cf2_floatToFixed( 0.7 ),
+                          glyphpath->xOffset );
+          *y = FT_MulFix( cf2_floatToFixed( 1.0 + 0.7 ),
+                          glyphpath->yOffset );
+        }
+      }
+      else
+      {
+        /* third quadrant, -x -y */
+
+        if ( -dx > -2 * dy )
+        {
+          /* -x */
+          *x = 0;
+          *y = 2 * glyphpath->yOffset;
+        }
+        else if ( -dy > -2 * dx )
+        {
+          /* -y */
+          *x = -glyphpath->xOffset;
+          *y = glyphpath->xOffset;
+        }
+        else
+        {
+          /* -x -y */
+          *x = FT_MulFix( cf2_floatToFixed( -0.7 ),
+                          glyphpath->xOffset );
+          *y = FT_MulFix( cf2_floatToFixed( 1.0 + 0.7 ),
+                          glyphpath->yOffset );
+        }
+      }
+    }
+  }
+
+
+  FT_LOCAL_DEF( void )
+  cf2_glyphpath_moveTo( CF2_GlyphPath  glyphpath,
+                        CF2_Fixed      x,
+                        CF2_Fixed      y )
+  {
+    cf2_glyphpath_closeOpenPath( glyphpath );
+
+    /* save the parameters of the move for later, when we'll know how to */
+    /* offset it;                                                        */
+    /* also save last move point */
+    glyphpath->currentCS.x = glyphpath->start.x = x;
+    glyphpath->currentCS.y = glyphpath->start.y = y;
+
+    glyphpath->moveIsPending = TRUE;
+
+    /* ensure we have a valid map with current mask */
+    if ( !cf2_hintmap_isValid( &glyphpath->hintMap ) ||
+         cf2_hintmask_isNew( glyphpath->hintMask )   )
+      cf2_hintmap_build( &glyphpath->hintMap,
+                         glyphpath->hStemHintArray,
+                         glyphpath->vStemHintArray,
+                         glyphpath->hintMask,
+                         glyphpath->hintOriginY,
+                         FALSE );
+
+    /* save a copy of current HintMap to use when drawing initial point */
+    glyphpath->firstHintMap = glyphpath->hintMap;     /* structure copy */
+  }
+
+
+  FT_LOCAL_DEF( void )
+  cf2_glyphpath_lineTo( CF2_GlyphPath  glyphpath,
+                        CF2_Fixed      x,
+                        CF2_Fixed      y )
+  {
+    CF2_Fixed  xOffset, yOffset;
+    FT_Vector  P0, P1;
+
+
+    /* can't compute offset of zero length line, so ignore them */
+    if ( glyphpath->currentCS.x == x && glyphpath->currentCS.y == y )
+      return;
+
+    cf2_glyphpath_computeOffset( glyphpath,
+                                 glyphpath->currentCS.x,
+                                 glyphpath->currentCS.y,
+                                 x,
+                                 y,
+                                 &xOffset,
+                                 &yOffset );
+
+    /* construct offset points */
+    P0.x = glyphpath->currentCS.x + xOffset;
+    P0.y = glyphpath->currentCS.y + yOffset;
+    P1.x = x + xOffset;
+    P1.y = y + yOffset;
+
+    if ( glyphpath->moveIsPending )
+    {
+      /* emit offset 1st point as MoveTo */
+      cf2_glyphpath_pushMove( glyphpath, P0 );
+
+      glyphpath->moveIsPending = FALSE;  /* adjust state machine */
+      glyphpath->pathIsOpen    = TRUE;
+
+      glyphpath->offsetStart1 = P1;              /* record second point */
+    }
+
+    if ( glyphpath->elemIsQueued )
+    {
+      FT_ASSERT( cf2_hintmap_isValid( &glyphpath->hintMap ) );
+
+      cf2_glyphpath_pushPrevElem( glyphpath,
+                                  &glyphpath->hintMap,
+                                  &P0,
+                                  P1,
+                                  FALSE );
+    }
+
+    /* queue the current element with offset points */
+    glyphpath->elemIsQueued = TRUE;
+    glyphpath->prevElemOp   = CF2_PathOpLineTo;
+    glyphpath->prevElemP0   = P0;
+    glyphpath->prevElemP1   = P1;
+
+    /* update current map */
+    if ( cf2_hintmask_isNew( glyphpath->hintMask ) )
+      cf2_hintmap_build( &glyphpath->hintMap,
+                         glyphpath->hStemHintArray,
+                         glyphpath->vStemHintArray,
+                         glyphpath->hintMask,
+                         glyphpath->hintOriginY,
+                         FALSE );
+
+    glyphpath->currentCS.x = x;     /* pre-offset current point */
+    glyphpath->currentCS.y = y;
+  }
+
+
+  FT_LOCAL_DEF( void )
+  cf2_glyphpath_curveTo( CF2_GlyphPath  glyphpath,
+                         CF2_Fixed      x1,
+                         CF2_Fixed      y1,
+                         CF2_Fixed      x2,
+                         CF2_Fixed      y2,
+                         CF2_Fixed      x3,
+                         CF2_Fixed      y3 )
+  {
+    CF2_Fixed  xOffset1, yOffset1, xOffset3, yOffset3;
+    FT_Vector  P0, P1, P2, P3;
+
+
+    /* TODO: ignore zero length portions of curve?? */
+    cf2_glyphpath_computeOffset( glyphpath,
+                                 glyphpath->currentCS.x,
+                                 glyphpath->currentCS.y,
+                                 x1,
+                                 y1,
+                                 &xOffset1,
+                                 &yOffset1 );
+    cf2_glyphpath_computeOffset( glyphpath,
+                                 x2,
+                                 y2,
+                                 x3,
+                                 y3,
+                                 &xOffset3,
+                                 &yOffset3 );
+
+    /* add momentum from the middle segment */
+    glyphpath->callbacks->windingMomentum +=
+      cf2_getWindingMomentum( x1, y1, x2, y2 );
+
+    /* construct offset points */
+    P0.x = glyphpath->currentCS.x + xOffset1;
+    P0.y = glyphpath->currentCS.y + yOffset1;
+    P1.x = x1 + xOffset1;
+    P1.y = y1 + yOffset1;
+    /* note: preserve angle of final segment by using offset3 at both ends */
+    P2.x = x2 + xOffset3;
+    P2.y = y2 + yOffset3;
+    P3.x = x3 + xOffset3;
+    P3.y = y3 + yOffset3;
+
+    if ( glyphpath->moveIsPending )
+    {
+      /* emit offset 1st point as MoveTo */
+      cf2_glyphpath_pushMove( glyphpath, P0 );
+
+      glyphpath->moveIsPending = FALSE;
+      glyphpath->pathIsOpen    = TRUE;
+
+      glyphpath->offsetStart1 = P1;              /* record second point */
+    }
+
+    if ( glyphpath->elemIsQueued )
+    {
+      FT_ASSERT( cf2_hintmap_isValid( &glyphpath->hintMap ) );
+
+      cf2_glyphpath_pushPrevElem( glyphpath,
+                                  &glyphpath->hintMap,
+                                  &P0,
+                                  P1,
+                                  FALSE );
+    }
+
+    /* queue the current element with offset points */
+    glyphpath->elemIsQueued = TRUE;
+    glyphpath->prevElemOp   = CF2_PathOpCubeTo;
+    glyphpath->prevElemP0   = P0;
+    glyphpath->prevElemP1   = P1;
+    glyphpath->prevElemP2   = P2;
+    glyphpath->prevElemP3   = P3;
+
+    /* update current map */
+    if ( cf2_hintmask_isNew( glyphpath->hintMask ) )
+      cf2_hintmap_build( &glyphpath->hintMap,
+                         glyphpath->hStemHintArray,
+                         glyphpath->vStemHintArray,
+                         glyphpath->hintMask,
+                         glyphpath->hintOriginY,
+                         FALSE );
+
+    glyphpath->currentCS.x = x3;       /* pre-offset current point */
+    glyphpath->currentCS.y = y3;
+  }
+
+
+  FT_LOCAL_DEF( void )
+  cf2_glyphpath_closeOpenPath( CF2_GlyphPath  glyphpath )
+  {
+    if ( glyphpath->pathIsOpen )
+    {
+      FT_ASSERT( cf2_hintmap_isValid( &glyphpath->firstHintMap ) );
+
+      /* since we need to apply an offset to the implicit lineto, we make */
+      /* it explicit here                                                 */
+      cf2_glyphpath_lineTo( glyphpath,
+                            glyphpath->start.x,
+                            glyphpath->start.y );
+
+      /* Draw previous element (the explicit LineTo we just created,      */
+      /* above) and connect it to the start point, but with the offset we */
+      /* saved from the first element.                                    */
+      /* Use the saved HintMap, too. */
+      FT_ASSERT( glyphpath->elemIsQueued );
+
+      cf2_glyphpath_pushPrevElem( glyphpath,
+                                  &glyphpath->firstHintMap,
+                                  &glyphpath->offsetStart0,
+                                  glyphpath->offsetStart1,
+                                  TRUE );
+
+      /* reset state machine */
+      glyphpath->moveIsPending = TRUE;
+      glyphpath->pathIsOpen    = FALSE;
+      glyphpath->elemIsQueued  = FALSE;
+    }
+  }
+
+
+/* END */
diff --git a/src/cff/cf2hints.h b/src/cff/cf2hints.h
new file mode 100644
index 0000000..c4fa922
--- /dev/null
+++ b/src/cff/cf2hints.h
@@ -0,0 +1,287 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cf2hints.h                                                             */
+/*                                                                         */
+/*    Adobe's code for handling CFF hints (body).                          */
+/*                                                                         */
+/*  Copyright 2007-2013 Adobe Systems Incorporated.                        */
+/*                                                                         */
+/*  This software, and all works of authorship, whether in source or       */
+/*  object code form as indicated by the copyright notice(s) included      */
+/*  herein (collectively, the "Work") is made available, and may only be   */
+/*  used, modified, and distributed under the FreeType Project License,    */
+/*  LICENSE.TXT.  Additionally, subject to the terms and conditions of the */
+/*  FreeType Project License, each contributor to the Work hereby grants   */
+/*  to any individual or legal entity exercising permissions granted by    */
+/*  the FreeType Project License and this section (hereafter, "You" or     */
+/*  "Your") a perpetual, worldwide, non-exclusive, no-charge,              */
+/*  royalty-free, irrevocable (except as stated in this section) patent    */
+/*  license to make, have made, use, offer to sell, sell, import, and      */
+/*  otherwise transfer the Work, where such license applies only to those  */
+/*  patent claims licensable by such contributor that are necessarily      */
+/*  infringed by their contribution(s) alone or by combination of their    */
+/*  contribution(s) with the Work to which such contribution(s) was        */
+/*  submitted.  If You institute patent litigation against any entity      */
+/*  (including a cross-claim or counterclaim in a lawsuit) alleging that   */
+/*  the Work or a contribution incorporated within the Work constitutes    */
+/*  direct or contributory patent infringement, then any patent licenses   */
+/*  granted to You under this License for that Work shall terminate as of  */
+/*  the date such litigation is filed.                                     */
+/*                                                                         */
+/*  By using, modifying, or distributing the Work you indicate that you    */
+/*  have read and understood the terms and conditions of the               */
+/*  FreeType Project License as well as those provided in this section,    */
+/*  and you accept them fully.                                             */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __CF2HINTS_H__
+#define __CF2HINTS_H__
+
+
+FT_BEGIN_HEADER
+
+
+  enum
+  {
+    CF2_MAX_HINTS = 96    /* maximum # of hints */
+  };
+
+
+  /*
+   * A HintMask object stores a bit mask that specifies which hints in the
+   * charstring are active at a given time.  Hints in CFF must be declared
+   * at the start, before any drawing operators, with horizontal hints
+   * preceding vertical hints.  The HintMask is ordered the same way, with
+   * horizontal hints immediately followed by vertical hints.  Clients are
+   * responsible for knowing how many of each type are present.
+   *
+   * The maximum total number of hints is 96, as specified by the CFF
+   * specification.
+   *
+   * A HintMask is built 0 or more times while interpreting a charstring, by
+   * the HintMask operator.  There is only one HintMask, but it is built or
+   * rebuilt each time there is a hint substitution (HintMask operator) in
+   * the charstring.  A default HintMask with all bits set is built if there
+   * has been no HintMask operator prior to the first drawing operator.
+   *
+   */
+
+  typedef struct  CF2_HintMaskRec_
+  {
+    FT_Error*  error;
+
+    FT_Bool  isValid;
+    FT_Bool  isNew;
+
+    size_t  bitCount;
+    size_t  byteCount;
+
+    FT_Byte  mask[( CF2_MAX_HINTS + 7 ) / 8];
+
+  } CF2_HintMaskRec, *CF2_HintMask;
+
+
+  typedef struct  CF2_StemHintRec_
+  {
+    FT_Bool  used;     /* DS positions are valid         */
+
+    CF2_Fixed  min;    /* original character space value */
+    CF2_Fixed  max;
+
+    CF2_Fixed  minDS;  /* DS position after first use    */
+    CF2_Fixed  maxDS;
+
+  } CF2_StemHintRec, *CF2_StemHint;
+
+
+  /*
+   * A HintMap object stores a piecewise linear function for mapping
+   * y-coordinates from character space to device space, providing
+   * appropriate pixel alignment to stem edges.
+   *
+   * The map is implemented as an array of `CF2_Hint' elements, each
+   * representing an edge.  When edges are paired, as from stem hints, the
+   * bottom edge must immediately precede the top edge in the array.
+   * Element character space AND device space positions must both increase
+   * monotonically in the array.  `CF2_Hint' elements are also used as
+   * parameters to `cf2_blues_capture'.
+   *
+   * The `cf2_hintmap_build' method must be called before any drawing
+   * operation (beginning with a Move operator) and at each hint
+   * substitution (HintMask operator).
+   *
+   * The `cf2_hintmap_map' method is called to transform y-coordinates at
+   * each drawing operation (move, line, curve).
+   *
+   */
+
+  /* TODO: make this a CF2_ArrStack and add a deep copy method */
+  enum
+  {
+    CF2_MAX_HINT_EDGES = CF2_MAX_HINTS * 2
+  };
+
+
+  typedef struct  CF2_HintMapRec_
+  {
+    CF2_Font  font;
+
+    /* initial map based on blue zones */
+    struct CF2_HintMapRec_*  initialHintMap;
+
+    /* working storage for 2nd pass adjustHints */
+    CF2_ArrStack  hintMoves;
+
+    FT_Bool  isValid;
+    FT_Bool  hinted;
+
+    CF2_Fixed  scale;
+    CF2_UInt   count;
+
+    /* start search from this index */
+    CF2_UInt  lastIndex;
+
+    CF2_HintRec  edge[CF2_MAX_HINT_EDGES]; /* 192 */
+
+  } CF2_HintMapRec, *CF2_HintMap;
+
+
+  FT_LOCAL( FT_Bool )
+  cf2_hint_isValid( const CF2_Hint  hint );
+  FT_LOCAL( FT_Bool )
+  cf2_hint_isTop( const CF2_Hint  hint );
+  FT_LOCAL( FT_Bool )
+  cf2_hint_isBottom( const CF2_Hint  hint );
+  FT_LOCAL( void )
+  cf2_hint_lock( CF2_Hint  hint );
+
+
+  FT_LOCAL( void )
+  cf2_hintmap_init( CF2_HintMap   hintmap,
+                    CF2_Font      font,
+                    CF2_HintMap   initialMap,
+                    CF2_ArrStack  hintMoves,
+                    CF2_Fixed     scale );
+  FT_LOCAL( void )
+  cf2_hintmap_build( CF2_HintMap   hintmap,
+                     CF2_ArrStack  hStemHintArray,
+                     CF2_ArrStack  vStemHintArray,
+                     CF2_HintMask  hintMask,
+                     CF2_Fixed     hintOrigin,
+                     FT_Bool       initialMap );
+
+
+  /*
+   * GlyphPath is a wrapper for drawing operations that scales the
+   * coordinates according to the render matrix and HintMap.  It also tracks
+   * open paths to control ClosePath and to insert MoveTo for broken fonts.
+   *
+   */
+  typedef struct  CF2_GlyphPathRec_
+  {
+    /* TODO: gather some of these into a hinting context */
+
+    CF2_Font              font;           /* font instance    */
+    CF2_OutlineCallbacks  callbacks;      /* outline consumer */
+
+
+    CF2_HintMapRec  hintMap;        /* current hint map            */
+    CF2_HintMapRec  firstHintMap;   /* saved copy                  */
+    CF2_HintMapRec  initialHintMap; /* based on all captured hints */
+
+    CF2_ArrStackRec  hintMoves;  /* list of hint moves for 2nd pass */
+
+    CF2_Fixed  scaleX;         /* matrix a */
+    CF2_Fixed  scaleC;         /* matrix c */
+    CF2_Fixed  scaleY;         /* matrix d */
+
+    FT_Vector  fractionalTranslation;  /* including deviceXScale */
+#if 0
+    CF2_Fixed  hShift;    /* character space horizontal shift */
+                          /* (for fauxing)                    */
+#endif
+
+    FT_Bool  pathIsOpen;     /* true after MoveTo                     */
+    FT_Bool  darken;         /* true if stem darkening                */
+    FT_Bool  moveIsPending;  /* true between MoveTo and offset MoveTo */
+
+    /* references used to call `cf2_hintmap_build', if necessary */
+    CF2_ArrStack         hStemHintArray;
+    CF2_ArrStack         vStemHintArray;
+    CF2_HintMask         hintMask;     /* ptr to the current mask */
+    CF2_Fixed            hintOriginY;  /* copy of current origin  */
+    const CF2_BluesRec*  blues;
+
+    CF2_Fixed  xOffset;        /* character space offsets */
+    CF2_Fixed  yOffset;
+
+    /* character space miter limit threshold */
+    CF2_Fixed  miterLimit;
+    /* vertical/horzizontal snap distance in character space */
+    CF2_Fixed  snapThreshold;
+
+    FT_Vector  offsetStart0;  /* first and second points of first */
+    FT_Vector  offsetStart1;  /* element with offset applied      */
+
+    /* current point, character space, before offset */
+    FT_Vector  currentCS;
+    /* current point, device space */
+    FT_Vector  currentDS;
+    FT_Vector  start;         /* start point of subpath */
+
+    /* the following members constitute the `queue' of one element */
+    FT_Bool  elemIsQueued;
+    CF2_Int  prevElemOp;
+
+    FT_Vector  prevElemP0;
+    FT_Vector  prevElemP1;
+    FT_Vector  prevElemP2;
+    FT_Vector  prevElemP3;
+
+  } CF2_GlyphPathRec, *CF2_GlyphPath;
+
+
+  FT_LOCAL( void )
+  cf2_glyphpath_init( CF2_GlyphPath         glyphpath,
+                      CF2_Font              font,
+                      CF2_OutlineCallbacks  callbacks,
+                      CF2_Fixed             scaleY,
+                      /* CF2_Fixed hShift, */
+                      CF2_ArrStack          hStemHintArray,
+                      CF2_ArrStack          vStemHintArray,
+                      CF2_HintMask          hintMask,
+                      CF2_Fixed             hintOrigin,
+                      const CF2_Blues       blues,
+                      const FT_Vector*      fractionalTranslation );
+  FT_LOCAL( void )
+  cf2_glyphpath_finalize( CF2_GlyphPath  glyphpath );
+
+  FT_LOCAL( void )
+  cf2_glyphpath_moveTo( CF2_GlyphPath  glyphpath,
+                        CF2_Fixed      x,
+                        CF2_Fixed      y );
+  FT_LOCAL( void )
+  cf2_glyphpath_lineTo( CF2_GlyphPath  glyphpath,
+                        CF2_Fixed      x,
+                        CF2_Fixed      y );
+  FT_LOCAL( void )
+  cf2_glyphpath_curveTo( CF2_GlyphPath  glyphpath,
+                         CF2_Fixed      x1,
+                         CF2_Fixed      y1,
+                         CF2_Fixed      x2,
+                         CF2_Fixed      y2,
+                         CF2_Fixed      x3,
+                         CF2_Fixed      y3 );
+  FT_LOCAL( void )
+  cf2_glyphpath_closeOpenPath( CF2_GlyphPath  glyphpath );
+
+
+FT_END_HEADER
+
+
+#endif /* __CF2HINTS_H__ */
+
+
+/* END */
diff --git a/src/cff/cf2intrp.c b/src/cff/cf2intrp.c
new file mode 100644
index 0000000..5b73e60
--- /dev/null
+++ b/src/cff/cf2intrp.c
@@ -0,0 +1,1538 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cf2intrp.c                                                             */
+/*                                                                         */
+/*    Adobe's CFF Interpreter (body).                                      */
+/*                                                                         */
+/*  Copyright 2007-2013 Adobe Systems Incorporated.                        */
+/*                                                                         */
+/*  This software, and all works of authorship, whether in source or       */
+/*  object code form as indicated by the copyright notice(s) included      */
+/*  herein (collectively, the "Work") is made available, and may only be   */
+/*  used, modified, and distributed under the FreeType Project License,    */
+/*  LICENSE.TXT.  Additionally, subject to the terms and conditions of the */
+/*  FreeType Project License, each contributor to the Work hereby grants   */
+/*  to any individual or legal entity exercising permissions granted by    */
+/*  the FreeType Project License and this section (hereafter, "You" or     */
+/*  "Your") a perpetual, worldwide, non-exclusive, no-charge,              */
+/*  royalty-free, irrevocable (except as stated in this section) patent    */
+/*  license to make, have made, use, offer to sell, sell, import, and      */
+/*  otherwise transfer the Work, where such license applies only to those  */
+/*  patent claims licensable by such contributor that are necessarily      */
+/*  infringed by their contribution(s) alone or by combination of their    */
+/*  contribution(s) with the Work to which such contribution(s) was        */
+/*  submitted.  If You institute patent litigation against any entity      */
+/*  (including a cross-claim or counterclaim in a lawsuit) alleging that   */
+/*  the Work or a contribution incorporated within the Work constitutes    */
+/*  direct or contributory patent infringement, then any patent licenses   */
+/*  granted to You under this License for that Work shall terminate as of  */
+/*  the date such litigation is filed.                                     */
+/*                                                                         */
+/*  By using, modifying, or distributing the Work you indicate that you    */
+/*  have read and understood the terms and conditions of the               */
+/*  FreeType Project License as well as those provided in this section,    */
+/*  and you accept them fully.                                             */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include "cf2ft.h"
+#include FT_INTERNAL_DEBUG_H
+
+#include "cf2glue.h"
+#include "cf2font.h"
+#include "cf2stack.h"
+#include "cf2hints.h"
+
+#include "cf2error.h"
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_cf2interp
+
+
+  /* some operators are not implemented yet */
+#define CF2_FIXME  FT_TRACE4(( "cf2_interpT2CharString:"            \
+                               " operator not implemented yet\n" ))
+
+
+
+  FT_LOCAL_DEF( void )
+  cf2_hintmask_init( CF2_HintMask  hintmask,
+                     FT_Error*     error )
+  {
+    FT_ZERO( hintmask );
+
+    hintmask->error = error;
+  }
+
+
+  FT_LOCAL_DEF( FT_Bool )
+  cf2_hintmask_isValid( const CF2_HintMask  hintmask )
+  {
+    return hintmask->isValid;
+  }
+
+
+  FT_LOCAL_DEF( FT_Bool )
+  cf2_hintmask_isNew( const CF2_HintMask  hintmask )
+  {
+    return hintmask->isNew;
+  }
+
+
+  FT_LOCAL_DEF( void )
+  cf2_hintmask_setNew( CF2_HintMask  hintmask,
+                       FT_Bool       val )
+  {
+    hintmask->isNew = val;
+  }
+
+
+  /* clients call `getMaskPtr' in order to iterate */
+  /* through hint mask                             */
+
+  FT_LOCAL_DEF( FT_Byte* )
+  cf2_hintmask_getMaskPtr( CF2_HintMask  hintmask )
+  {
+    return hintmask->mask;
+  }
+
+
+  static size_t
+  cf2_hintmask_setCounts( CF2_HintMask  hintmask,
+                          size_t        bitCount )
+  {
+    if ( bitCount > CF2_MAX_HINTS )
+    {
+      /* total of h and v stems must be <= 96 */
+      CF2_SET_ERROR( hintmask->error, Invalid_Glyph_Format );
+      return 0;
+    }
+
+    hintmask->bitCount  = bitCount;
+    hintmask->byteCount = ( hintmask->bitCount + 7 ) / 8;
+
+    hintmask->isValid = TRUE;
+    hintmask->isNew   = TRUE;
+
+    return bitCount;
+  }
+
+
+  /* consume the hintmask bytes from the charstring, advancing the src */
+  /* pointer                                                           */
+  static void
+  cf2_hintmask_read( CF2_HintMask  hintmask,
+                     CF2_Buffer    charstring,
+                     size_t        bitCount )
+  {
+    size_t  i;
+
+#ifndef CF2_NDEBUG
+    /* these are the bits in the final mask byte that should be zero  */
+    /* Note: this variable is only used in an assert expression below */
+    /* and then only if CF2_NDEBUG is not defined                     */
+    CF2_UInt  mask = ( 1 << ( -(CF2_Int)bitCount & 7 ) ) - 1;
+#endif
+
+
+    /* initialize counts and isValid */
+    if ( cf2_hintmask_setCounts( hintmask, bitCount ) == 0 )
+      return;
+
+    FT_ASSERT( hintmask->byteCount > 0 );
+
+    FT_TRACE4(( " (maskbytes:" ));
+
+    /* set mask and advance interpreter's charstring pointer */
+    for ( i = 0; i < hintmask->byteCount; i++ )
+    {
+      hintmask->mask[i] = (FT_Byte)cf2_buf_readByte( charstring );
+      FT_TRACE4(( " 0x%02X", hintmask->mask[i] ));
+    }
+
+    FT_TRACE4(( ")\n" ));
+
+    /* assert any unused bits in last byte are zero unless there's a prior */
+    /* error                                                               */
+    /* bitCount -> mask, 0 -> 0, 1 -> 7f, 2 -> 3f, ... 6 -> 3, 7 -> 1      */
+#ifndef CF2_NDEBUG
+    FT_ASSERT( ( hintmask->mask[hintmask->byteCount - 1] & mask ) == 0 ||
+               *hintmask->error                                        );
+#endif
+  }
+
+
+  FT_LOCAL_DEF( void )
+  cf2_hintmask_setAll( CF2_HintMask  hintmask,
+                       size_t        bitCount )
+  {
+    size_t    i;
+    CF2_UInt  mask = ( 1 << ( -(CF2_Int)bitCount & 7 ) ) - 1;
+
+
+    /* initialize counts and isValid */
+    if ( cf2_hintmask_setCounts( hintmask, bitCount ) == 0 )
+      return;
+
+    FT_ASSERT( hintmask->byteCount > 0 );
+    FT_ASSERT( hintmask->byteCount <
+                 sizeof ( hintmask->mask ) / sizeof ( hintmask->mask[0] ) );
+
+    /* set mask to all ones */
+    for ( i = 0; i < hintmask->byteCount; i++ )
+      hintmask->mask[i] = 0xFF;
+
+    /* clear unused bits                                              */
+    /* bitCount -> mask, 0 -> 0, 1 -> 7f, 2 -> 3f, ... 6 -> 3, 7 -> 1 */
+    hintmask->mask[hintmask->byteCount - 1] &= ~mask;
+  }
+
+
+  /* Type2 charstring opcodes */
+  enum
+  {
+    cf2_cmdRESERVED_0,   /* 0 */
+    cf2_cmdHSTEM,        /* 1 */
+    cf2_cmdRESERVED_2,   /* 2 */
+    cf2_cmdVSTEM,        /* 3 */
+    cf2_cmdVMOVETO,      /* 4 */
+    cf2_cmdRLINETO,      /* 5 */
+    cf2_cmdHLINETO,      /* 6 */
+    cf2_cmdVLINETO,      /* 7 */
+    cf2_cmdRRCURVETO,    /* 8 */
+    cf2_cmdRESERVED_9,   /* 9 */
+    cf2_cmdCALLSUBR,     /* 10 */
+    cf2_cmdRETURN,       /* 11 */
+    cf2_cmdESC,          /* 12 */
+    cf2_cmdRESERVED_13,  /* 13 */
+    cf2_cmdENDCHAR,      /* 14 */
+    cf2_cmdRESERVED_15,  /* 15 */
+    cf2_cmdRESERVED_16,  /* 16 */
+    cf2_cmdRESERVED_17,  /* 17 */
+    cf2_cmdHSTEMHM,      /* 18 */
+    cf2_cmdHINTMASK,     /* 19 */
+    cf2_cmdCNTRMASK,     /* 20 */
+    cf2_cmdRMOVETO,      /* 21 */
+    cf2_cmdHMOVETO,      /* 22 */
+    cf2_cmdVSTEMHM,      /* 23 */
+    cf2_cmdRCURVELINE,   /* 24 */
+    cf2_cmdRLINECURVE,   /* 25 */
+    cf2_cmdVVCURVETO,    /* 26 */
+    cf2_cmdHHCURVETO,    /* 27 */
+    cf2_cmdEXTENDEDNMBR, /* 28 */
+    cf2_cmdCALLGSUBR,    /* 29 */
+    cf2_cmdVHCURVETO,    /* 30 */
+    cf2_cmdHVCURVETO     /* 31 */
+  };
+
+  enum
+  {
+    cf2_escDOTSECTION,   /* 0 */
+    cf2_escRESERVED_1,   /* 1 */
+    cf2_escRESERVED_2,   /* 2 */
+    cf2_escAND,          /* 3 */
+    cf2_escOR,           /* 4 */
+    cf2_escNOT,          /* 5 */
+    cf2_escRESERVED_6,   /* 6 */
+    cf2_escRESERVED_7,   /* 7 */
+    cf2_escRESERVED_8,   /* 8 */
+    cf2_escABS,          /* 9 */
+    cf2_escADD,          /* 10     like otherADD */
+    cf2_escSUB,          /* 11     like otherSUB */
+    cf2_escDIV,          /* 12 */
+    cf2_escRESERVED_13,  /* 13 */
+    cf2_escNEG,          /* 14 */
+    cf2_escEQ,           /* 15 */
+    cf2_escRESERVED_16,  /* 16 */
+    cf2_escRESERVED_17,  /* 17 */
+    cf2_escDROP,         /* 18 */
+    cf2_escRESERVED_19,  /* 19 */
+    cf2_escPUT,          /* 20     like otherPUT    */
+    cf2_escGET,          /* 21     like otherGET    */
+    cf2_escIFELSE,       /* 22     like otherIFELSE */
+    cf2_escRANDOM,       /* 23     like otherRANDOM */
+    cf2_escMUL,          /* 24     like otherMUL    */
+    cf2_escRESERVED_25,  /* 25 */
+    cf2_escSQRT,         /* 26 */
+    cf2_escDUP,          /* 27     like otherDUP    */
+    cf2_escEXCH,         /* 28     like otherEXCH   */
+    cf2_escINDEX,        /* 29 */
+    cf2_escROLL,         /* 30 */
+    cf2_escRESERVED_31,  /* 31 */
+    cf2_escRESERVED_32,  /* 32 */
+    cf2_escRESERVED_33,  /* 33 */
+    cf2_escHFLEX,        /* 34 */
+    cf2_escFLEX,         /* 35 */
+    cf2_escHFLEX1,       /* 36 */
+    cf2_escFLEX1         /* 37 */
+  };
+
+
+  /* `stemHintArray' does not change once we start drawing the outline. */
+  static void
+  cf2_doStems( const CF2_Font  font,
+               CF2_Stack       opStack,
+               CF2_ArrStack    stemHintArray,
+               CF2_Fixed*      width,
+               FT_Bool*        haveWidth,
+               CF2_Fixed       hintOffset )
+  {
+    CF2_UInt  i;
+    CF2_UInt  count       = cf2_stack_count( opStack );
+    FT_Bool   hasWidthArg = count & 1;
+
+    /* variable accumulates delta values from operand stack */
+    CF2_Fixed  position = hintOffset;
+
+    if ( hasWidthArg && ! *haveWidth )
+      *width = cf2_stack_getReal( opStack, 0 ) +
+                 cf2_getNominalWidthX( font->decoder );
+
+    if ( font->decoder->width_only )
+      goto exit;
+
+    for ( i = hasWidthArg ? 1 : 0; i < count; i += 2 )
+    {
+      /* construct a CF2_StemHint and push it onto the list */
+      CF2_StemHintRec  stemhint;
+
+
+      stemhint.min  =
+        position   += cf2_stack_getReal( opStack, i );
+      stemhint.max  =
+        position   += cf2_stack_getReal( opStack, i + 1 );
+
+      stemhint.used  = FALSE;
+      stemhint.maxDS =
+      stemhint.minDS = 0;
+
+      cf2_arrstack_push( stemHintArray, &stemhint ); /* defer error check */
+    }
+
+    cf2_stack_clear( opStack );
+
+  exit:
+    /* cf2_doStems must define a width (may be default) */
+    *haveWidth = TRUE;
+  }
+
+
+  static void
+  cf2_doFlex( CF2_Stack       opStack,
+              CF2_Fixed*      curX,
+              CF2_Fixed*      curY,
+              CF2_GlyphPath   glyphPath,
+              const FT_Bool*  readFromStack,
+              FT_Bool         doConditionalLastRead )
+  {
+    CF2_Fixed  vals[14];
+    CF2_UInt   index;
+    FT_Bool    isHFlex;
+    CF2_Int    top, i, j;
+
+
+    vals[0] = *curX;
+    vals[1] = *curY;
+    index   = 0;
+    isHFlex = readFromStack[9] == FALSE;
+    top     = isHFlex ? 9 : 10;
+
+    for ( i = 0; i < top; i++ )
+    {
+      vals[i + 2] = vals[i];
+      if ( readFromStack[i] )
+        vals[i + 2] += cf2_stack_getReal( opStack, index++ );
+    }
+
+    if ( isHFlex )
+      vals[9 + 2] = *curY;
+
+    if ( doConditionalLastRead )
+    {
+      FT_Bool    lastIsX = cf2_fixedAbs( vals[10] - *curX ) >
+                             cf2_fixedAbs( vals[11] - *curY );
+      CF2_Fixed  lastVal = cf2_stack_getReal( opStack, index );
+
+
+      if ( lastIsX )
+      {
+        vals[12] = vals[10] + lastVal;
+        vals[13] = *curY;
+      }
+      else
+      {
+        vals[12] = *curX;
+        vals[13] = vals[11] + lastVal;
+      }
+    }
+    else
+    {
+      if ( readFromStack[10] )
+        vals[12] = vals[10] + cf2_stack_getReal( opStack, index++ );
+      else
+        vals[12] = *curX;
+
+      if ( readFromStack[11] )
+        vals[13] = vals[11] + cf2_stack_getReal( opStack, index );
+      else
+        vals[13] = *curY;
+    }
+
+    for ( j = 0; j < 2; j++ )
+      cf2_glyphpath_curveTo( glyphPath, vals[j * 6 + 2],
+                                        vals[j * 6 + 3],
+                                        vals[j * 6 + 4],
+                                        vals[j * 6 + 5],
+                                        vals[j * 6 + 6],
+                                        vals[j * 6 + 7] );
+
+    cf2_stack_clear( opStack );
+
+    *curX = vals[12];
+    *curY = vals[13];
+  }
+
+
+  /*
+   * `error' is a shared error code used by many objects in this
+   * routine.  Before the code continues from an error, it must check and
+   * record the error in `*error'.  The idea is that this shared
+   * error code will record the first error encountered.  If testing
+   * for an error anyway, the cost of `goto exit' is small, so we do it,
+   * even if continuing would be safe.  In this case, `lastError' is
+   * set, so the testing and storing can be done in one place, at `exit'.
+   *
+   * Continuing after an error is intended for objects which do their own
+   * testing of `*error', e.g., array stack functions.  This allows us to
+   * avoid an extra test after the call.
+   *
+   * Unimplemented opcodes are ignored.
+   *
+   */
+  FT_LOCAL_DEF( void )
+  cf2_interpT2CharString( CF2_Font              font,
+                          CF2_Buffer            buf,
+                          CF2_OutlineCallbacks  callbacks,
+                          const FT_Vector*      translation,
+                          FT_Bool               doingSeac,
+                          CF2_Fixed             curX,
+                          CF2_Fixed             curY,
+                          CF2_Fixed*            width )
+  {
+    /* lastError is used for errors that are immediately tested */
+    FT_Error  lastError = FT_Err_Ok;
+
+    /* pointer to parsed font object */
+    CFF_Decoder*  decoder = font->decoder;
+
+    FT_Error*  error  = &font->error;
+    FT_Memory  memory = font->memory;
+
+    CF2_Fixed  scaleY        = font->innerTransform.d;
+    CF2_Fixed  nominalWidthX = cf2_getNominalWidthX( decoder );
+
+    /* save this for hinting seac accents */
+    CF2_Fixed  hintOriginY = curY;
+
+    CF2_Stack  opStack = NULL;
+    FT_Byte    op1;                       /* first opcode byte */
+
+    /* instruction limit; 20,000,000 matches Avalon */
+    FT_UInt32  instructionLimit = 20000000UL;
+
+    CF2_ArrStackRec  subrStack;
+
+    FT_Bool     haveWidth;
+    CF2_Buffer  charstring = NULL;
+
+    CF2_Int  charstringIndex = -1;       /* initialize to empty */
+
+    /* TODO: placeholders for hint structures */
+
+    /* objects used for hinting */
+    CF2_ArrStackRec  hStemHintArray;
+    CF2_ArrStackRec  vStemHintArray;
+
+    CF2_HintMaskRec   hintMask;
+    CF2_GlyphPathRec  glyphPath;
+
+
+    /* initialize the remaining objects */
+    cf2_arrstack_init( &subrStack,
+                       memory,
+                       error,
+                       sizeof ( CF2_BufferRec ) );
+    cf2_arrstack_init( &hStemHintArray,
+                       memory,
+                       error,
+                       sizeof ( CF2_StemHintRec ) );
+    cf2_arrstack_init( &vStemHintArray,
+                       memory,
+                       error,
+                       sizeof ( CF2_StemHintRec ) );
+
+    /* initialize CF2_StemHint arrays */
+    cf2_hintmask_init( &hintMask, error );
+
+    /* initialize path map to manage drawing operations */
+
+    /* Note: last 4 params are used to handle `MoveToPermissive', which */
+    /*       may need to call `hintMap.Build'                           */
+    /* TODO: MoveToPermissive is gone; are these still needed?          */
+    cf2_glyphpath_init( &glyphPath,
+                        font,
+                        callbacks,
+                        scaleY,
+                        /* hShift, */
+                        &hStemHintArray,
+                        &vStemHintArray,
+                        &hintMask,
+                        hintOriginY,
+                        &font->blues,
+                        translation );
+
+    /*
+     * Initialize state for width parsing.  From the CFF Spec:
+     *
+     *   The first stack-clearing operator, which must be one of hstem,
+     *   hstemhm, vstem, vstemhm, cntrmask, hintmask, hmoveto, vmoveto,
+     *   rmoveto, or endchar, takes an additional argument - the width (as
+     *   described earlier), which may be expressed as zero or one numeric
+     *   argument.
+     *
+     * What we implement here uses the first validly specified width, but
+     * does not detect errors for specifying more than one width.
+     *
+     * If one of the above operators occurs without explicitly specifying
+     * a width, we assume the default width.
+     *
+     */
+    haveWidth = FALSE;
+    *width    = cf2_getDefaultWidthX( decoder );
+
+    /*
+     * Note: at this point, all pointers to resources must be NULL
+     * and all local objects must be initialized.
+     * There must be no branches to exit: above this point.
+     *
+     */
+
+    /* allocate an operand stack */
+    opStack = cf2_stack_init( memory, error );
+    if ( !opStack )
+    {
+      lastError = FT_THROW( Out_Of_Memory );
+      goto exit;
+    }
+
+    /* initialize subroutine stack by placing top level charstring as */
+    /* first element (max depth plus one for the charstring)          */
+    /* Note: Caller owns and must finalize the first charstring.      */
+    /*       Our copy of it does not change that requirement.         */
+    cf2_arrstack_setCount( &subrStack, CF2_MAX_SUBR + 1 );
+
+    charstring  = (CF2_Buffer)cf2_arrstack_getBuffer( &subrStack );
+    *charstring = *buf;    /* structure copy */
+
+    charstringIndex = 0;       /* entry is valid now */
+
+    /* catch errors so far */
+    if ( *error )
+      goto exit;
+
+    /* main interpreter loop */
+    while ( 1 )
+    {
+      if ( cf2_buf_isEnd( charstring ) )
+      {
+        /* If we've reached the end of the charstring, simulate a */
+        /* cf2_cmdRETURN or cf2_cmdENDCHAR.                       */
+        if ( charstringIndex )
+          op1 = cf2_cmdRETURN;  /* end of buffer for subroutine */
+        else
+          op1 = cf2_cmdENDCHAR; /* end of buffer for top level charstring */
+      }
+      else
+        op1 = (FT_Byte)cf2_buf_readByte( charstring );
+
+      /* check for errors once per loop */
+      if ( *error )
+        goto exit;
+
+      instructionLimit--;
+      if ( instructionLimit == 0 )
+      {
+        lastError = FT_THROW( Invalid_Glyph_Format );
+        goto exit;
+      }
+
+      switch( op1 )
+      {
+      case cf2_cmdRESERVED_0:
+      case cf2_cmdRESERVED_2:
+      case cf2_cmdRESERVED_9:
+      case cf2_cmdRESERVED_13:
+      case cf2_cmdRESERVED_15:
+      case cf2_cmdRESERVED_16:
+      case cf2_cmdRESERVED_17:
+        /* we may get here if we have a prior error */
+        FT_TRACE4(( " unknown op (%d)\n", op1 ));
+        break;
+
+      case cf2_cmdHSTEMHM:
+      case cf2_cmdHSTEM:
+        FT_TRACE4(( op1 == cf2_cmdHSTEMHM ? " hstemhm\n" : " hstem\n" ));
+
+        /* never add hints after the mask is computed */
+        if ( cf2_hintmask_isValid( &hintMask ) )
+          FT_TRACE4(( "cf2_interpT2CharString:"
+                      " invalid horizontal hint mask\n" ));
+
+        cf2_doStems( font,
+                     opStack,
+                     &hStemHintArray,
+                     width,
+                     &haveWidth,
+                     0 );
+
+        if ( font->decoder->width_only )
+            goto exit;
+
+        break;
+
+      case cf2_cmdVSTEMHM:
+      case cf2_cmdVSTEM:
+        FT_TRACE4(( op1 == cf2_cmdVSTEMHM ? " vstemhm\n" : " vstem\n" ));
+
+        /* never add hints after the mask is computed */
+        if ( cf2_hintmask_isValid( &hintMask ) )
+          FT_TRACE4(( "cf2_interpT2CharString:"
+                      " invalid vertical hint mask\n" ));
+
+        cf2_doStems( font,
+                     opStack,
+                     &vStemHintArray,
+                     width,
+                     &haveWidth,
+                     0 );
+
+        if ( font->decoder->width_only )
+            goto exit;
+
+        break;
+
+      case cf2_cmdVMOVETO:
+        FT_TRACE4(( " vmoveto\n" ));
+
+        if ( cf2_stack_count( opStack ) > 1 && !haveWidth )
+          *width = cf2_stack_getReal( opStack, 0 ) + nominalWidthX;
+
+        /* width is defined or default after this */
+        haveWidth = TRUE;
+
+        if ( font->decoder->width_only )
+            goto exit;
+
+        curY += cf2_stack_popFixed( opStack );
+
+        cf2_glyphpath_moveTo( &glyphPath, curX, curY );
+
+        break;
+
+      case cf2_cmdRLINETO:
+        {
+          CF2_UInt  index;
+          CF2_UInt  count = cf2_stack_count( opStack );
+
+
+          FT_TRACE4(( " rlineto\n" ));
+
+          for ( index = 0; index < count; index += 2 )
+          {
+            curX += cf2_stack_getReal( opStack, index + 0 );
+            curY += cf2_stack_getReal( opStack, index + 1 );
+
+            cf2_glyphpath_lineTo( &glyphPath, curX, curY );
+          }
+
+          cf2_stack_clear( opStack );
+        }
+        continue; /* no need to clear stack again */
+
+      case cf2_cmdHLINETO:
+      case cf2_cmdVLINETO:
+        {
+          CF2_UInt  index;
+          CF2_UInt  count = cf2_stack_count( opStack );
+
+          FT_Bool  isX = op1 == cf2_cmdHLINETO;
+
+
+          FT_TRACE4(( isX ? " hlineto\n" : " vlineto\n" ));
+
+          for ( index = 0; index < count; index++ )
+          {
+            CF2_Fixed  v = cf2_stack_getReal( opStack, index );
+
+
+            if ( isX )
+              curX += v;
+            else
+              curY += v;
+
+            isX = !isX;
+
+            cf2_glyphpath_lineTo( &glyphPath, curX, curY );
+          }
+
+          cf2_stack_clear( opStack );
+        }
+        continue;
+
+      case cf2_cmdRCURVELINE:
+      case cf2_cmdRRCURVETO:
+        {
+          CF2_UInt  count = cf2_stack_count( opStack );
+          CF2_UInt  index = 0;
+
+
+          FT_TRACE4(( op1 == cf2_cmdRCURVELINE ? " rcurveline\n"
+                                               : " rrcurveto\n" ));
+
+          while ( index + 6 <= count )
+          {
+            CF2_Fixed  x1 = cf2_stack_getReal( opStack, index + 0 ) + curX;
+            CF2_Fixed  y1 = cf2_stack_getReal( opStack, index + 1 ) + curY;
+            CF2_Fixed  x2 = cf2_stack_getReal( opStack, index + 2 ) + x1;
+            CF2_Fixed  y2 = cf2_stack_getReal( opStack, index + 3 ) + y1;
+            CF2_Fixed  x3 = cf2_stack_getReal( opStack, index + 4 ) + x2;
+            CF2_Fixed  y3 = cf2_stack_getReal( opStack, index + 5 ) + y2;
+
+
+            cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 );
+
+            curX   = x3;
+            curY   = y3;
+            index += 6;
+          }
+
+          if ( op1 == cf2_cmdRCURVELINE )
+          {
+            curX += cf2_stack_getReal( opStack, index + 0 );
+            curY += cf2_stack_getReal( opStack, index + 1 );
+
+            cf2_glyphpath_lineTo( &glyphPath, curX, curY );
+          }
+
+          cf2_stack_clear( opStack );
+        }
+        continue; /* no need to clear stack again */
+
+      case cf2_cmdCALLGSUBR:
+      case cf2_cmdCALLSUBR:
+        {
+          CF2_UInt  subrIndex;
+
+
+          FT_TRACE4(( op1 == cf2_cmdCALLGSUBR ? " callgsubr"
+                                              : " callsubr" ));
+
+          if ( charstringIndex > CF2_MAX_SUBR )
+          {
+            /* max subr plus one for charstring */
+            lastError = FT_THROW( Invalid_Glyph_Format );
+            goto exit;                      /* overflow of stack */
+          }
+
+          /* push our current CFF charstring region on subrStack */
+          charstring = (CF2_Buffer)
+                         cf2_arrstack_getPointer( &subrStack,
+                                                  charstringIndex + 1 );
+
+          /* set up the new CFF region and pointer */
+          subrIndex = cf2_stack_popInt( opStack );
+
+          switch ( op1 )
+          {
+          case cf2_cmdCALLGSUBR:
+            FT_TRACE4(( "(%d)\n", subrIndex + decoder->globals_bias ));
+
+            if ( cf2_initGlobalRegionBuffer( decoder,
+                                             subrIndex,
+                                             charstring ) )
+            {
+              lastError = FT_THROW( Invalid_Glyph_Format );
+              goto exit;  /* subroutine lookup or stream error */
+            }
+            break;
+
+          default:
+            /* cf2_cmdCALLSUBR */
+            FT_TRACE4(( "(%d)\n", subrIndex + decoder->locals_bias ));
+
+            if ( cf2_initLocalRegionBuffer( decoder,
+                                            subrIndex,
+                                            charstring ) )
+            {
+              lastError = FT_THROW( Invalid_Glyph_Format );
+              goto exit;  /* subroutine lookup or stream error */
+            }
+          }
+
+          charstringIndex += 1;       /* entry is valid now */
+        }
+        continue; /* do not clear the stack */
+
+      case cf2_cmdRETURN:
+        FT_TRACE4(( " return\n" ));
+
+        if ( charstringIndex < 1 )
+        {
+          /* Note: cannot return from top charstring */
+          lastError = FT_THROW( Invalid_Glyph_Format );
+          goto exit;                      /* underflow of stack */
+        }
+
+        /* restore position in previous charstring */
+        charstring = (CF2_Buffer)
+                       cf2_arrstack_getPointer( &subrStack,
+                                                --charstringIndex );
+        continue;     /* do not clear the stack */
+
+      case cf2_cmdESC:
+        {
+          FT_Byte  op2 = (FT_Byte)cf2_buf_readByte( charstring );
+
+
+          switch ( op2 )
+          {
+          case cf2_escDOTSECTION:
+            /* something about `flip type of locking' -- ignore it */
+            FT_TRACE4(( " dotsection\n" ));
+
+            break;
+
+          /* TODO: should these operators be supported? */
+          case cf2_escAND: /* in spec */
+            FT_TRACE4(( " and\n" ));
+
+            CF2_FIXME;
+            break;
+
+          case cf2_escOR: /* in spec */
+            FT_TRACE4(( " or\n" ));
+
+            CF2_FIXME;
+            break;
+
+          case cf2_escNOT: /* in spec */
+            FT_TRACE4(( " not\n" ));
+
+            CF2_FIXME;
+            break;
+
+          case cf2_escABS: /* in spec */
+            FT_TRACE4(( " abs\n" ));
+
+            CF2_FIXME;
+            break;
+
+          case cf2_escADD: /* in spec */
+            FT_TRACE4(( " add\n" ));
+
+            CF2_FIXME;
+            break;
+
+          case cf2_escSUB: /* in spec */
+            FT_TRACE4(( " sub\n" ));
+
+            CF2_FIXME;
+            break;
+
+          case cf2_escDIV: /* in spec */
+            FT_TRACE4(( " div\n" ));
+
+            CF2_FIXME;
+            break;
+
+          case cf2_escNEG: /* in spec */
+            FT_TRACE4(( " neg\n" ));
+
+            CF2_FIXME;
+            break;
+
+          case cf2_escEQ: /* in spec */
+            FT_TRACE4(( " eq\n" ));
+
+            CF2_FIXME;
+            break;
+
+          case cf2_escDROP: /* in spec */
+            FT_TRACE4(( " drop\n" ));
+
+            CF2_FIXME;
+            break;
+
+          case cf2_escPUT: /* in spec */
+            FT_TRACE4(( " put\n" ));
+
+            CF2_FIXME;
+            break;
+
+          case cf2_escGET: /* in spec */
+            FT_TRACE4(( " get\n" ));
+
+            CF2_FIXME;
+            break;
+
+          case cf2_escIFELSE: /* in spec */
+            FT_TRACE4(( " ifelse\n" ));
+
+            CF2_FIXME;
+            break;
+
+          case cf2_escRANDOM: /* in spec */
+            FT_TRACE4(( " random\n" ));
+
+            CF2_FIXME;
+            break;
+
+          case cf2_escMUL: /* in spec */
+            FT_TRACE4(( " mul\n" ));
+
+            CF2_FIXME;
+            break;
+
+          case cf2_escSQRT: /* in spec */
+            FT_TRACE4(( " sqrt\n" ));
+
+            CF2_FIXME;
+            break;
+
+          case cf2_escDUP: /* in spec */
+            FT_TRACE4(( " dup\n" ));
+
+            CF2_FIXME;
+            break;
+
+          case cf2_escEXCH: /* in spec */
+            FT_TRACE4(( " exch\n" ));
+
+            CF2_FIXME;
+            break;
+
+          case cf2_escINDEX: /* in spec */
+            FT_TRACE4(( " index\n" ));
+
+            CF2_FIXME;
+            break;
+
+          case cf2_escROLL: /* in spec */
+            FT_TRACE4(( " roll\n" ));
+
+            CF2_FIXME;
+            break;
+
+          case cf2_escHFLEX:
+            {
+              static const FT_Bool  readFromStack[12] =
+              {
+                TRUE /* dx1 */, FALSE /* dy1 */,
+                TRUE /* dx2 */, TRUE  /* dy2 */,
+                TRUE /* dx3 */, FALSE /* dy3 */,
+                TRUE /* dx4 */, FALSE /* dy4 */,
+                TRUE /* dx5 */, FALSE /* dy5 */,
+                TRUE /* dx6 */, FALSE /* dy6 */
+              };
+
+
+              FT_TRACE4(( " hflex\n" ));
+
+              cf2_doFlex( opStack,
+                          &curX,
+                          &curY,
+                          &glyphPath,
+                          readFromStack,
+                          FALSE /* doConditionalLastRead */ );
+            }
+            continue;
+
+          case cf2_escFLEX:
+            {
+              static const FT_Bool  readFromStack[12] =
+              {
+                TRUE /* dx1 */, TRUE /* dy1 */,
+                TRUE /* dx2 */, TRUE /* dy2 */,
+                TRUE /* dx3 */, TRUE /* dy3 */,
+                TRUE /* dx4 */, TRUE /* dy4 */,
+                TRUE /* dx5 */, TRUE /* dy5 */,
+                TRUE /* dx6 */, TRUE /* dy6 */
+              };
+
+
+              FT_TRACE4(( " flex\n" ));
+
+              cf2_doFlex( opStack,
+                          &curX,
+                          &curY,
+                          &glyphPath,
+                          readFromStack,
+                          FALSE /* doConditionalLastRead */ );
+            }
+            break;      /* TODO: why is this not a continue? */
+
+          case cf2_escHFLEX1:
+            {
+              static const FT_Bool  readFromStack[12] =
+              {
+                TRUE /* dx1 */, TRUE  /* dy1 */,
+                TRUE /* dx2 */, TRUE  /* dy2 */,
+                TRUE /* dx3 */, FALSE /* dy3 */,
+                TRUE /* dx4 */, FALSE /* dy4 */,
+                TRUE /* dx5 */, TRUE  /* dy5 */,
+                TRUE /* dx6 */, FALSE /* dy6 */
+              };
+
+
+              FT_TRACE4(( " hflex1\n" ));
+
+              cf2_doFlex( opStack,
+                          &curX,
+                          &curY,
+                          &glyphPath,
+                          readFromStack,
+                          FALSE /* doConditionalLastRead */ );
+            }
+            continue;
+
+          case cf2_escFLEX1:
+            {
+              static const FT_Bool  readFromStack[12] =
+              {
+                TRUE  /* dx1 */, TRUE  /* dy1 */,
+                TRUE  /* dx2 */, TRUE  /* dy2 */,
+                TRUE  /* dx3 */, TRUE  /* dy3 */,
+                TRUE  /* dx4 */, TRUE  /* dy4 */,
+                TRUE  /* dx5 */, TRUE  /* dy5 */,
+                FALSE /* dx6 */, FALSE /* dy6 */
+              };
+
+
+              FT_TRACE4(( " flex1\n" ));
+
+              cf2_doFlex( opStack,
+                          &curX,
+                          &curY,
+                          &glyphPath,
+                          readFromStack,
+                          TRUE /* doConditionalLastRead */ );
+            }
+            continue;
+
+          case cf2_escRESERVED_1:
+          case cf2_escRESERVED_2:
+          case cf2_escRESERVED_6:
+          case cf2_escRESERVED_7:
+          case cf2_escRESERVED_8:
+          case cf2_escRESERVED_13:
+          case cf2_escRESERVED_16:
+          case cf2_escRESERVED_17:
+          case cf2_escRESERVED_19:
+          case cf2_escRESERVED_25:
+          case cf2_escRESERVED_31:
+          case cf2_escRESERVED_32:
+          case cf2_escRESERVED_33:
+          default:
+            FT_TRACE4(( " unknown op (12, %d)\n", op2 ));
+
+          }; /* end of switch statement checking `op2' */
+
+        } /* case cf2_cmdESC */
+        break;
+
+      case cf2_cmdENDCHAR:
+        FT_TRACE4(( " endchar\n" ));
+
+        if ( cf2_stack_count( opStack ) == 1 ||
+             cf2_stack_count( opStack ) == 5 )
+        {
+          if ( !haveWidth )
+            *width = cf2_stack_getReal( opStack, 0 ) + nominalWidthX;
+        }
+
+        /* width is defined or default after this */
+        haveWidth = TRUE;
+
+        if ( font->decoder->width_only )
+            goto exit;
+
+        /* close path if still open */
+        cf2_glyphpath_closeOpenPath( &glyphPath );
+
+        if ( cf2_stack_count( opStack ) > 1 )
+        {
+          /* must be either 4 or 5 --                       */
+          /* this is a (deprecated) implied `seac' operator */
+
+          CF2_UInt       achar;
+          CF2_UInt       bchar;
+          CF2_BufferRec  component;
+          CF2_Fixed      dummyWidth;   /* ignore component width */
+          FT_Error       error2;
+
+
+          if ( doingSeac )
+          {
+            lastError = FT_THROW( Invalid_Glyph_Format );
+            goto exit;      /* nested seac */
+          }
+
+          achar = cf2_stack_popInt( opStack );
+          bchar = cf2_stack_popInt( opStack );
+
+          curY = cf2_stack_popFixed( opStack );
+          curX = cf2_stack_popFixed( opStack );
+
+          error2 = cf2_getSeacComponent( decoder, achar, &component );
+          if ( error2 )
+          {
+             lastError = error2;      /* pass FreeType error through */
+             goto exit;
+          }
+          cf2_interpT2CharString( font,
+                                  &component,
+                                  callbacks,
+                                  translation,
+                                  TRUE,
+                                  curX,
+                                  curY,
+                                  &dummyWidth );
+          cf2_freeSeacComponent( decoder, &component );
+
+          error2 = cf2_getSeacComponent( decoder, bchar, &component );
+          if ( error2 )
+          {
+            lastError = error2;      /* pass FreeType error through */
+            goto exit;
+          }
+          cf2_interpT2CharString( font,
+                                  &component,
+                                  callbacks,
+                                  translation,
+                                  TRUE,
+                                  0,
+                                  0,
+                                  &dummyWidth );
+          cf2_freeSeacComponent( decoder, &component );
+        }
+        goto exit;
+
+      case cf2_cmdCNTRMASK:
+      case cf2_cmdHINTMASK:
+        /* the final \n in the tracing message gets added in      */
+        /* `cf2_hintmask_read' (which also traces the mask bytes) */
+        FT_TRACE4(( op1 == cf2_cmdCNTRMASK ? " cntrmask" : " hintmask" ));
+
+        /* if there are arguments on the stack, there this is an */
+        /* implied cf2_cmdVSTEMHM                                */
+        if ( cf2_stack_count( opStack ) != 0 )
+        {
+          /* never add hints after the mask is computed */
+          if ( cf2_hintmask_isValid( &hintMask ) )
+            FT_TRACE4(( "cf2_interpT2CharString: invalid hint mask\n" ));
+        }
+
+        cf2_doStems( font,
+                     opStack,
+                     &vStemHintArray,
+                     width,
+                     &haveWidth,
+                     0 );
+
+        if ( font->decoder->width_only )
+            goto exit;
+
+        if ( op1 == cf2_cmdHINTMASK )
+        {
+          /* consume the hint mask bytes which follow the operator */
+          cf2_hintmask_read( &hintMask,
+                             charstring,
+                             cf2_arrstack_size( &hStemHintArray ) +
+                               cf2_arrstack_size( &vStemHintArray ) );
+        }
+        else
+        {
+          /*
+           * Consume the counter mask bytes which follow the operator:
+           * Build a temporary hint map, just to place and lock those
+           * stems participating in the counter mask.  These are most
+           * likely the dominant hstems, and are grouped together in a
+           * few counter groups, not necessarily in correspondence
+           * with the hint groups.  This reduces the chances of
+           * conflicts between hstems that are initially placed in
+           * separate hint groups and then brought together.  The
+           * positions are copied back to `hStemHintArray', so we can
+           * discard `counterMask' and `counterHintMap'.
+           *
+           */
+          CF2_HintMapRec   counterHintMap;
+          CF2_HintMaskRec  counterMask;
+
+
+          cf2_hintmap_init( &counterHintMap,
+                            font,
+                            &glyphPath.initialHintMap,
+                            &glyphPath.hintMoves,
+                            scaleY );
+          cf2_hintmask_init( &counterMask, error );
+
+          cf2_hintmask_read( &counterMask,
+                             charstring,
+                             cf2_arrstack_size( &hStemHintArray ) +
+                               cf2_arrstack_size( &vStemHintArray ) );
+          cf2_hintmap_build( &counterHintMap,
+                             &hStemHintArray,
+                             &vStemHintArray,
+                             &counterMask,
+                             0,
+                             FALSE );
+        }
+        break;
+
+      case cf2_cmdRMOVETO:
+        FT_TRACE4(( " rmoveto\n" ));
+
+        if ( cf2_stack_count( opStack ) > 2 && !haveWidth )
+          *width = cf2_stack_getReal( opStack, 0 ) + nominalWidthX;
+
+        /* width is defined or default after this */
+        haveWidth = TRUE;
+
+        if ( font->decoder->width_only )
+            goto exit;
+
+        curY += cf2_stack_popFixed( opStack );
+        curX += cf2_stack_popFixed( opStack );
+
+        cf2_glyphpath_moveTo( &glyphPath, curX, curY );
+
+        break;
+
+      case cf2_cmdHMOVETO:
+        FT_TRACE4(( " hmoveto\n" ));
+
+        if ( cf2_stack_count( opStack ) > 1 && !haveWidth )
+          *width = cf2_stack_getReal( opStack, 0 ) + nominalWidthX;
+
+        /* width is defined or default after this */
+        haveWidth = TRUE;
+
+        if ( font->decoder->width_only )
+            goto exit;
+
+        curX += cf2_stack_popFixed( opStack );
+
+        cf2_glyphpath_moveTo( &glyphPath, curX, curY );
+
+        break;
+
+      case cf2_cmdRLINECURVE:
+        {
+          CF2_UInt  count = cf2_stack_count( opStack );
+          CF2_UInt  index = 0;
+
+
+          FT_TRACE4(( " rlinecurve\n" ));
+
+          while ( index + 6 < count )
+          {
+            curX += cf2_stack_getReal( opStack, index + 0 );
+            curY += cf2_stack_getReal( opStack, index + 1 );
+
+            cf2_glyphpath_lineTo( &glyphPath, curX, curY );
+            index += 2;
+          }
+
+          while ( index < count )
+          {
+            CF2_Fixed  x1 = cf2_stack_getReal( opStack, index + 0 ) + curX;
+            CF2_Fixed  y1 = cf2_stack_getReal( opStack, index + 1 ) + curY;
+            CF2_Fixed  x2 = cf2_stack_getReal( opStack, index + 2 ) + x1;
+            CF2_Fixed  y2 = cf2_stack_getReal( opStack, index + 3 ) + y1;
+            CF2_Fixed  x3 = cf2_stack_getReal( opStack, index + 4 ) + x2;
+            CF2_Fixed  y3 = cf2_stack_getReal( opStack, index + 5 ) + y2;
+
+
+            cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 );
+
+            curX   = x3;
+            curY   = y3;
+            index += 6;
+          }
+
+          cf2_stack_clear( opStack );
+        }
+        continue; /* no need to clear stack again */
+
+      case cf2_cmdVVCURVETO:
+        {
+          CF2_UInt  count = cf2_stack_count( opStack );
+          CF2_UInt  index = 0;
+
+
+          FT_TRACE4(( " vvcurveto\n" ));
+
+          while ( index < count )
+          {
+            CF2_Fixed  x1, y1, x2, y2, x3, y3;
+
+
+            if ( ( count - index ) & 1 )
+            {
+              x1 = cf2_stack_getReal( opStack, index ) + curX;
+
+              ++index;
+            }
+            else
+              x1 = curX;
+
+            y1 = cf2_stack_getReal( opStack, index + 0 ) + curY;
+            x2 = cf2_stack_getReal( opStack, index + 1 ) + x1;
+            y2 = cf2_stack_getReal( opStack, index + 2 ) + y1;
+            x3 = x2;
+            y3 = cf2_stack_getReal( opStack, index + 3 ) + y2;
+
+            cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 );
+
+            curX   = x3;
+            curY   = y3;
+            index += 4;
+          }
+
+          cf2_stack_clear( opStack );
+        }
+        continue; /* no need to clear stack again */
+
+      case cf2_cmdHHCURVETO:
+        {
+          CF2_UInt  count = cf2_stack_count( opStack );
+          CF2_UInt  index = 0;
+
+
+          FT_TRACE4(( " hhcurveto\n" ));
+
+          while ( index < count )
+          {
+            CF2_Fixed  x1, y1, x2, y2, x3, y3;
+
+
+            if ( ( count - index ) & 1 )
+            {
+              y1 = cf2_stack_getReal( opStack, index ) + curY;
+
+              ++index;
+            }
+            else
+              y1 = curY;
+
+            x1 = cf2_stack_getReal( opStack, index + 0 ) + curX;
+            x2 = cf2_stack_getReal( opStack, index + 1 ) + x1;
+            y2 = cf2_stack_getReal( opStack, index + 2 ) + y1;
+            x3 = cf2_stack_getReal( opStack, index + 3 ) + x2;
+            y3 = y2;
+
+            cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 );
+
+            curX   = x3;
+            curY   = y3;
+            index += 4;
+          }
+
+          cf2_stack_clear( opStack );
+        }
+        continue; /* no need to clear stack again */
+
+      case cf2_cmdVHCURVETO:
+      case cf2_cmdHVCURVETO:
+        {
+          CF2_UInt  count = cf2_stack_count( opStack );
+          CF2_UInt  index = 0;
+
+          FT_Bool  alternate = op1 == cf2_cmdHVCURVETO;
+
+
+          FT_TRACE4(( alternate ? " hvcurveto\n" : " vhcurveto\n" ));
+
+          while ( index < count )
+          {
+            CF2_Fixed x1, x2, x3, y1, y2, y3;
+
+
+            if ( alternate )
+            {
+              x1 = cf2_stack_getReal( opStack, index + 0 ) + curX;
+              y1 = curY;
+              x2 = cf2_stack_getReal( opStack, index + 1 ) + x1;
+              y2 = cf2_stack_getReal( opStack, index + 2 ) + y1;
+              y3 = cf2_stack_getReal( opStack, index + 3 ) + y2;
+
+              if ( count - index == 5 )
+              {
+                x3 = cf2_stack_getReal( opStack, index + 4 ) + x2;
+
+                ++index;
+              }
+              else
+                x3 = x2;
+
+              alternate = FALSE;
+            }
+            else
+            {
+              x1 = curX;
+              y1 = cf2_stack_getReal( opStack, index + 0 ) + curY;
+              x2 = cf2_stack_getReal( opStack, index + 1 ) + x1;
+              y2 = cf2_stack_getReal( opStack, index + 2 ) + y1;
+              x3 = cf2_stack_getReal( opStack, index + 3 ) + x2;
+
+              if ( count - index == 5 )
+              {
+                y3 = cf2_stack_getReal( opStack, index + 4 ) + y2;
+
+                ++index;
+              }
+              else
+                y3 = y2;
+
+              alternate = TRUE;
+            }
+
+            cf2_glyphpath_curveTo( &glyphPath, x1, y1, x2, y2, x3, y3 );
+
+            curX   = x3;
+            curY   = y3;
+            index += 4;
+          }
+
+          cf2_stack_clear( opStack );
+        }
+        continue;     /* no need to clear stack again */
+
+      case cf2_cmdEXTENDEDNMBR:
+        {
+          CF2_Int  v;
+
+
+          v = (FT_Short)( ( cf2_buf_readByte( charstring ) << 8 ) |
+                            cf2_buf_readByte( charstring )        );
+
+          FT_TRACE4(( " %d", v ));
+
+          cf2_stack_pushInt( opStack, v );
+        }
+        continue;
+
+      default:
+        /* numbers */
+        {
+          if ( /* op1 >= 32 && */ op1 <= 246 )
+          {
+            CF2_Int  v;
+
+
+            v = op1 - 139;
+
+            FT_TRACE4(( " %d", v ));
+
+            /* -107 .. 107 */
+            cf2_stack_pushInt( opStack, v );
+          }
+
+          else if ( /* op1 >= 247 && */ op1 <= 250 )
+          {
+            CF2_Int  v;
+
+
+            v  = op1;
+            v -= 247;
+            v *= 256;
+            v += cf2_buf_readByte( charstring );
+            v += 108;
+
+            FT_TRACE4(( " %d", v ));
+
+            /* 108 .. 1131 */
+            cf2_stack_pushInt( opStack, v );
+          }
+
+          else if ( /* op1 >= 251 && */ op1 <= 254 )
+          {
+            CF2_Int  v;
+
+
+            v  = op1;
+            v -= 251;
+            v *= 256;
+            v += cf2_buf_readByte( charstring );
+            v  = -v - 108;
+
+            FT_TRACE4(( " %d", v ));
+
+            /* -1131 .. -108 */
+            cf2_stack_pushInt( opStack, v );
+          }
+
+          else /* op1 == 255 */
+          {
+            CF2_Fixed  v;
+
+
+            v = (CF2_Fixed)
+                  ( ( (FT_UInt32)cf2_buf_readByte( charstring ) << 24 ) |
+                    ( (FT_UInt32)cf2_buf_readByte( charstring ) << 16 ) |
+                    ( (FT_UInt32)cf2_buf_readByte( charstring ) <<  8 ) |
+                      (FT_UInt32)cf2_buf_readByte( charstring )         );
+
+            FT_TRACE4(( " %.2f", v / 65536.0 ));
+
+            cf2_stack_pushFixed( opStack, v );
+          }
+        }
+        continue;   /* don't clear stack */
+
+      } /* end of switch statement checking `op1' */
+
+      cf2_stack_clear( opStack );
+
+    } /* end of main interpreter loop */
+
+    /* we get here if the charstring ends without cf2_cmdENDCHAR */
+    FT_TRACE4(( "cf2_interpT2CharString:"
+                "  charstring ends without ENDCHAR\n" ));
+
+  exit:
+    /* check whether last error seen is also the first one */
+    cf2_setError( error, lastError );
+
+    /* free resources from objects we've used */
+    cf2_glyphpath_finalize( &glyphPath );
+    cf2_arrstack_finalize( &vStemHintArray );
+    cf2_arrstack_finalize( &hStemHintArray );
+    cf2_arrstack_finalize( &subrStack );
+    cf2_stack_free( opStack );
+
+    FT_TRACE4(( "\n" ));
+
+    return;
+  }
+
+
+/* END */
diff --git a/src/cff/cf2intrp.h b/src/cff/cf2intrp.h
new file mode 100644
index 0000000..b5d8947
--- /dev/null
+++ b/src/cff/cf2intrp.h
@@ -0,0 +1,83 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cf2font.h                                                              */
+/*                                                                         */
+/*    Adobe's CFF Interpreter (specification).                             */
+/*                                                                         */
+/*  Copyright 2007-2013 Adobe Systems Incorporated.                        */
+/*                                                                         */
+/*  This software, and all works of authorship, whether in source or       */
+/*  object code form as indicated by the copyright notice(s) included      */
+/*  herein (collectively, the "Work") is made available, and may only be   */
+/*  used, modified, and distributed under the FreeType Project License,    */
+/*  LICENSE.TXT.  Additionally, subject to the terms and conditions of the */
+/*  FreeType Project License, each contributor to the Work hereby grants   */
+/*  to any individual or legal entity exercising permissions granted by    */
+/*  the FreeType Project License and this section (hereafter, "You" or     */
+/*  "Your") a perpetual, worldwide, non-exclusive, no-charge,              */
+/*  royalty-free, irrevocable (except as stated in this section) patent    */
+/*  license to make, have made, use, offer to sell, sell, import, and      */
+/*  otherwise transfer the Work, where such license applies only to those  */
+/*  patent claims licensable by such contributor that are necessarily      */
+/*  infringed by their contribution(s) alone or by combination of their    */
+/*  contribution(s) with the Work to which such contribution(s) was        */
+/*  submitted.  If You institute patent litigation against any entity      */
+/*  (including a cross-claim or counterclaim in a lawsuit) alleging that   */
+/*  the Work or a contribution incorporated within the Work constitutes    */
+/*  direct or contributory patent infringement, then any patent licenses   */
+/*  granted to You under this License for that Work shall terminate as of  */
+/*  the date such litigation is filed.                                     */
+/*                                                                         */
+/*  By using, modifying, or distributing the Work you indicate that you    */
+/*  have read and understood the terms and conditions of the               */
+/*  FreeType Project License as well as those provided in this section,    */
+/*  and you accept them fully.                                             */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __CF2INTRP_H__
+#define __CF2INTRP_H__
+
+
+#include "cf2ft.h"
+#include "cf2hints.h"
+
+
+FT_BEGIN_HEADER
+
+
+  FT_LOCAL( void )
+  cf2_hintmask_init( CF2_HintMask  hintmask,
+                     FT_Error*     error );
+  FT_LOCAL( FT_Bool )
+  cf2_hintmask_isValid( const CF2_HintMask  hintmask );
+  FT_LOCAL( FT_Bool )
+  cf2_hintmask_isNew( const CF2_HintMask  hintmask );
+  FT_LOCAL( void )
+  cf2_hintmask_setNew( CF2_HintMask  hintmask,
+                       FT_Bool       val );
+  FT_LOCAL( FT_Byte* )
+  cf2_hintmask_getMaskPtr( CF2_HintMask  hintmask );
+  FT_LOCAL( void )
+  cf2_hintmask_setAll( CF2_HintMask  hintmask,
+                       size_t        bitCount );
+
+  FT_LOCAL( void )
+  cf2_interpT2CharString( CF2_Font              font,
+                          CF2_Buffer            charstring,
+                          CF2_OutlineCallbacks  callbacks,
+                          const FT_Vector*      translation,
+                          FT_Bool               doingSeac,
+                          CF2_Fixed             curX,
+                          CF2_Fixed             curY,
+                          CF2_Fixed*            width );
+
+
+FT_END_HEADER
+
+
+#endif /* __CF2INTRP_H__ */
+
+
+/* END */
diff --git a/src/cff/cf2read.c b/src/cff/cf2read.c
new file mode 100644
index 0000000..cb671ec
--- /dev/null
+++ b/src/cff/cf2read.c
@@ -0,0 +1,112 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cf2read.c                                                              */
+/*                                                                         */
+/*    Adobe's code for stream handling (body).                             */
+/*                                                                         */
+/*  Copyright 2007-2013 Adobe Systems Incorporated.                        */
+/*                                                                         */
+/*  This software, and all works of authorship, whether in source or       */
+/*  object code form as indicated by the copyright notice(s) included      */
+/*  herein (collectively, the "Work") is made available, and may only be   */
+/*  used, modified, and distributed under the FreeType Project License,    */
+/*  LICENSE.TXT.  Additionally, subject to the terms and conditions of the */
+/*  FreeType Project License, each contributor to the Work hereby grants   */
+/*  to any individual or legal entity exercising permissions granted by    */
+/*  the FreeType Project License and this section (hereafter, "You" or     */
+/*  "Your") a perpetual, worldwide, non-exclusive, no-charge,              */
+/*  royalty-free, irrevocable (except as stated in this section) patent    */
+/*  license to make, have made, use, offer to sell, sell, import, and      */
+/*  otherwise transfer the Work, where such license applies only to those  */
+/*  patent claims licensable by such contributor that are necessarily      */
+/*  infringed by their contribution(s) alone or by combination of their    */
+/*  contribution(s) with the Work to which such contribution(s) was        */
+/*  submitted.  If You institute patent litigation against any entity      */
+/*  (including a cross-claim or counterclaim in a lawsuit) alleging that   */
+/*  the Work or a contribution incorporated within the Work constitutes    */
+/*  direct or contributory patent infringement, then any patent licenses   */
+/*  granted to You under this License for that Work shall terminate as of  */
+/*  the date such litigation is filed.                                     */
+/*                                                                         */
+/*  By using, modifying, or distributing the Work you indicate that you    */
+/*  have read and understood the terms and conditions of the               */
+/*  FreeType Project License as well as those provided in this section,    */
+/*  and you accept them fully.                                             */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include "cf2ft.h"
+#include FT_INTERNAL_DEBUG_H
+
+#include "cf2glue.h"
+
+#include "cf2error.h"
+
+
+  /* Define CF2_IO_FAIL as 1 to enable random errors and random */
+  /* value errors in I/O.                                       */
+#define CF2_IO_FAIL  0
+
+
+#if CF2_IO_FAIL
+
+  /* set the .00 value to a nonzero probability */
+  static int
+  randomError2( void )
+  {
+    /* for region buffer ReadByte (interp) function */
+    return (double)rand() / RAND_MAX < .00;
+  }
+
+  /* set the .00 value to a nonzero probability */
+  static CF2_Int
+  randomValue()
+  {
+    return (double)rand() / RAND_MAX < .00 ? rand() : 0;
+  }
+
+#endif /* CF2_IO_FAIL */
+
+
+  /* Region Buffer                                      */
+  /*                                                    */
+  /* Can be constructed from a copied buffer managed by */
+  /* `FCM_getDatablock'.                                */
+  /* Reads bytes with check for end of buffer.          */
+
+  /* reading past the end of the buffer sets error and returns zero */
+  FT_LOCAL_DEF( CF2_Int )
+  cf2_buf_readByte( CF2_Buffer  buf )
+  {
+    if ( buf->ptr < buf->end )
+    {
+#if CF2_IO_FAIL
+      if ( randomError2() )
+      {
+        CF2_SET_ERROR( buf->error, Invalid_Stream_Operation );
+        return 0;
+      }
+
+      return *(buf->ptr)++ + randomValue();
+#else
+      return *(buf->ptr)++;
+#endif
+    }
+    else
+    {
+      CF2_SET_ERROR( buf->error, Invalid_Stream_Operation );
+      return 0;
+    }
+  }
+
+
+  /* note: end condition can occur without error */
+  FT_LOCAL_DEF( FT_Bool )
+  cf2_buf_isEnd( CF2_Buffer  buf )
+  {
+    return buf->ptr >= buf->end;
+  }
+
+
+/* END */
diff --git a/src/cff/cf2read.h b/src/cff/cf2read.h
new file mode 100644
index 0000000..7ef7c8c
--- /dev/null
+++ b/src/cff/cf2read.h
@@ -0,0 +1,68 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cf2read.h                                                              */
+/*                                                                         */
+/*    Adobe's code for stream handling (specification).                    */
+/*                                                                         */
+/*  Copyright 2007-2013 Adobe Systems Incorporated.                        */
+/*                                                                         */
+/*  This software, and all works of authorship, whether in source or       */
+/*  object code form as indicated by the copyright notice(s) included      */
+/*  herein (collectively, the "Work") is made available, and may only be   */
+/*  used, modified, and distributed under the FreeType Project License,    */
+/*  LICENSE.TXT.  Additionally, subject to the terms and conditions of the */
+/*  FreeType Project License, each contributor to the Work hereby grants   */
+/*  to any individual or legal entity exercising permissions granted by    */
+/*  the FreeType Project License and this section (hereafter, "You" or     */
+/*  "Your") a perpetual, worldwide, non-exclusive, no-charge,              */
+/*  royalty-free, irrevocable (except as stated in this section) patent    */
+/*  license to make, have made, use, offer to sell, sell, import, and      */
+/*  otherwise transfer the Work, where such license applies only to those  */
+/*  patent claims licensable by such contributor that are necessarily      */
+/*  infringed by their contribution(s) alone or by combination of their    */
+/*  contribution(s) with the Work to which such contribution(s) was        */
+/*  submitted.  If You institute patent litigation against any entity      */
+/*  (including a cross-claim or counterclaim in a lawsuit) alleging that   */
+/*  the Work or a contribution incorporated within the Work constitutes    */
+/*  direct or contributory patent infringement, then any patent licenses   */
+/*  granted to You under this License for that Work shall terminate as of  */
+/*  the date such litigation is filed.                                     */
+/*                                                                         */
+/*  By using, modifying, or distributing the Work you indicate that you    */
+/*  have read and understood the terms and conditions of the               */
+/*  FreeType Project License as well as those provided in this section,    */
+/*  and you accept them fully.                                             */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __CF2READ_H__
+#define __CF2READ_H__
+
+
+FT_BEGIN_HEADER
+
+
+  typedef struct  CF2_BufferRec_
+  {
+    FT_Error*       error;
+    const FT_Byte*  start;
+    const FT_Byte*  end;
+    const FT_Byte*  ptr;
+
+  } CF2_BufferRec, *CF2_Buffer;
+
+
+  FT_LOCAL( CF2_Int )
+  cf2_buf_readByte( CF2_Buffer  buf );
+  FT_LOCAL( FT_Bool )
+  cf2_buf_isEnd( CF2_Buffer  buf );
+
+
+FT_END_HEADER
+
+
+#endif /* __CF2READ_H__ */
+
+
+/* END */
diff --git a/src/cff/cf2stack.c b/src/cff/cf2stack.c
new file mode 100644
index 0000000..8332b5d
--- /dev/null
+++ b/src/cff/cf2stack.c
@@ -0,0 +1,205 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cf2stack.c                                                             */
+/*                                                                         */
+/*    Adobe's code for emulating a CFF stack (body).                       */
+/*                                                                         */
+/*  Copyright 2007-2013 Adobe Systems Incorporated.                        */
+/*                                                                         */
+/*  This software, and all works of authorship, whether in source or       */
+/*  object code form as indicated by the copyright notice(s) included      */
+/*  herein (collectively, the "Work") is made available, and may only be   */
+/*  used, modified, and distributed under the FreeType Project License,    */
+/*  LICENSE.TXT.  Additionally, subject to the terms and conditions of the */
+/*  FreeType Project License, each contributor to the Work hereby grants   */
+/*  to any individual or legal entity exercising permissions granted by    */
+/*  the FreeType Project License and this section (hereafter, "You" or     */
+/*  "Your") a perpetual, worldwide, non-exclusive, no-charge,              */
+/*  royalty-free, irrevocable (except as stated in this section) patent    */
+/*  license to make, have made, use, offer to sell, sell, import, and      */
+/*  otherwise transfer the Work, where such license applies only to those  */
+/*  patent claims licensable by such contributor that are necessarily      */
+/*  infringed by their contribution(s) alone or by combination of their    */
+/*  contribution(s) with the Work to which such contribution(s) was        */
+/*  submitted.  If You institute patent litigation against any entity      */
+/*  (including a cross-claim or counterclaim in a lawsuit) alleging that   */
+/*  the Work or a contribution incorporated within the Work constitutes    */
+/*  direct or contributory patent infringement, then any patent licenses   */
+/*  granted to You under this License for that Work shall terminate as of  */
+/*  the date such litigation is filed.                                     */
+/*                                                                         */
+/*  By using, modifying, or distributing the Work you indicate that you    */
+/*  have read and understood the terms and conditions of the               */
+/*  FreeType Project License as well as those provided in this section,    */
+/*  and you accept them fully.                                             */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include "cf2ft.h"
+#include FT_INTERNAL_DEBUG_H
+
+#include "cf2glue.h"
+#include "cf2font.h"
+#include "cf2stack.h"
+
+#include "cf2error.h"
+
+
+  /* Allocate and initialize an instance of CF2_Stack.       */
+  /* Note: This function returns NULL on error (does not set */
+  /* `error').                                               */
+  FT_LOCAL_DEF( CF2_Stack )
+  cf2_stack_init( FT_Memory  memory,
+                  FT_Error*  e )
+  {
+    FT_Error  error = FT_Err_Ok;     /* for FT_QNEW */
+
+    CF2_Stack  stack = NULL;
+
+
+    if ( !FT_QNEW( stack ) )
+    {
+      /* initialize the structure; FT_QNEW zeroes it */
+      stack->memory = memory;
+      stack->error  = e;
+      stack->top    = &stack->buffer[0]; /* empty stack */
+    }
+
+    return stack;
+  }
+
+
+  FT_LOCAL_DEF( void )
+  cf2_stack_free( CF2_Stack  stack )
+  {
+    if ( stack )
+    {
+      FT_Memory  memory = stack->memory;
+
+
+      /* free the main structure */
+      FT_FREE( stack );
+    }
+  }
+
+
+  FT_LOCAL_DEF( CF2_UInt )
+  cf2_stack_count( CF2_Stack  stack )
+  {
+    return (CF2_UInt)( stack->top - &stack->buffer[0] );
+  }
+
+
+  FT_LOCAL_DEF( void )
+  cf2_stack_pushInt( CF2_Stack  stack,
+                     CF2_Int    val )
+  {
+    if ( stack->top == &stack->buffer[CF2_OPERAND_STACK_SIZE] )
+    {
+      CF2_SET_ERROR( stack->error, Stack_Overflow );
+      return;     /* stack overflow */
+    }
+
+    stack->top->u.i  = val;
+    stack->top->type = CF2_NumberInt;
+    ++stack->top;
+  }
+
+
+  FT_LOCAL_DEF( void )
+  cf2_stack_pushFixed( CF2_Stack  stack,
+                       CF2_Fixed  val )
+  {
+    if ( stack->top == &stack->buffer[CF2_OPERAND_STACK_SIZE] )
+    {
+      CF2_SET_ERROR( stack->error, Stack_Overflow );
+      return;     /* stack overflow */
+    }
+
+    stack->top->u.r  = val;
+    stack->top->type = CF2_NumberFixed;
+    ++stack->top;
+  }
+
+
+  /* this function is only allowed to pop an integer type */
+  FT_LOCAL_DEF( CF2_Int )
+  cf2_stack_popInt( CF2_Stack  stack )
+  {
+    if ( stack->top == &stack->buffer[0] )
+    {
+      CF2_SET_ERROR( stack->error, Stack_Underflow );
+      return 0;   /* underflow */
+    }
+    if ( stack->top[-1].type != CF2_NumberInt )
+    {
+      CF2_SET_ERROR( stack->error, Syntax_Error );
+      return 0;   /* type mismatch */
+    }
+
+    --stack->top;
+
+    return stack->top->u.i;
+  }
+
+
+  /* Note: type mismatch is silently cast */
+  /* TODO: check this */
+  FT_LOCAL_DEF( CF2_Fixed )
+  cf2_stack_popFixed( CF2_Stack  stack )
+  {
+    if ( stack->top == &stack->buffer[0] )
+    {
+      CF2_SET_ERROR( stack->error, Stack_Underflow );
+      return cf2_intToFixed( 0 );    /* underflow */
+    }
+
+    --stack->top;
+
+    switch ( stack->top->type )
+    {
+    case CF2_NumberInt:
+      return cf2_intToFixed( stack->top->u.i );
+    case CF2_NumberFrac:
+      return cf2_fracToFixed( stack->top->u.f );
+    default:
+      return stack->top->u.r;
+    }
+  }
+
+
+  /* Note: type mismatch is silently cast */
+  /* TODO: check this */
+  FT_LOCAL_DEF( CF2_Fixed )
+  cf2_stack_getReal( CF2_Stack  stack,
+                     CF2_UInt   idx )
+  {
+    FT_ASSERT( cf2_stack_count( stack ) <= CF2_OPERAND_STACK_SIZE );
+
+    if ( idx >= cf2_stack_count( stack ) )
+    {
+      CF2_SET_ERROR( stack->error, Stack_Overflow );
+      return cf2_intToFixed( 0 );    /* bounds error */
+    }
+
+    switch ( stack->buffer[idx].type )
+    {
+    case CF2_NumberInt:
+      return cf2_intToFixed( stack->buffer[idx].u.i );
+    case CF2_NumberFrac:
+      return cf2_fracToFixed( stack->buffer[idx].u.f );
+    default:
+      return stack->buffer[idx].u.r;
+    }
+  }
+
+
+  FT_LOCAL_DEF( void )
+  cf2_stack_clear( CF2_Stack  stack )
+  {
+    stack->top = &stack->buffer[0];
+  }
+
+
+/* END */
diff --git a/src/cff/cf2stack.h b/src/cff/cf2stack.h
new file mode 100644
index 0000000..7d6d196
--- /dev/null
+++ b/src/cff/cf2stack.h
@@ -0,0 +1,106 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cf2stack.h                                                             */
+/*                                                                         */
+/*    Adobe's code for emulating a CFF stack (specification).              */
+/*                                                                         */
+/*  Copyright 2007-2013 Adobe Systems Incorporated.                        */
+/*                                                                         */
+/*  This software, and all works of authorship, whether in source or       */
+/*  object code form as indicated by the copyright notice(s) included      */
+/*  herein (collectively, the "Work") is made available, and may only be   */
+/*  used, modified, and distributed under the FreeType Project License,    */
+/*  LICENSE.TXT.  Additionally, subject to the terms and conditions of the */
+/*  FreeType Project License, each contributor to the Work hereby grants   */
+/*  to any individual or legal entity exercising permissions granted by    */
+/*  the FreeType Project License and this section (hereafter, "You" or     */
+/*  "Your") a perpetual, worldwide, non-exclusive, no-charge,              */
+/*  royalty-free, irrevocable (except as stated in this section) patent    */
+/*  license to make, have made, use, offer to sell, sell, import, and      */
+/*  otherwise transfer the Work, where such license applies only to those  */
+/*  patent claims licensable by such contributor that are necessarily      */
+/*  infringed by their contribution(s) alone or by combination of their    */
+/*  contribution(s) with the Work to which such contribution(s) was        */
+/*  submitted.  If You institute patent litigation against any entity      */
+/*  (including a cross-claim or counterclaim in a lawsuit) alleging that   */
+/*  the Work or a contribution incorporated within the Work constitutes    */
+/*  direct or contributory patent infringement, then any patent licenses   */
+/*  granted to You under this License for that Work shall terminate as of  */
+/*  the date such litigation is filed.                                     */
+/*                                                                         */
+/*  By using, modifying, or distributing the Work you indicate that you    */
+/*  have read and understood the terms and conditions of the               */
+/*  FreeType Project License as well as those provided in this section,    */
+/*  and you accept them fully.                                             */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __CF2STACK_H__
+#define __CF2STACK_H__
+
+
+FT_BEGIN_HEADER
+
+
+  /* CFF operand stack; specified maximum of 48 or 192 values */
+  typedef struct  CF2_StackNumber_
+  {
+    union
+    {
+      CF2_Fixed  r;      /* 16.16 fixed point */
+      CF2_Frac   f;      /* 2.30 fixed point (for font matrix) */
+      CF2_Int    i;
+    } u;
+
+    CF2_NumberType  type;
+
+  } CF2_StackNumber;
+
+
+  typedef struct  CF2_StackRec_
+  {
+    FT_Memory         memory;
+    FT_Error*         error;
+    CF2_StackNumber   buffer[CF2_OPERAND_STACK_SIZE];
+    CF2_StackNumber*  top;
+
+  } CF2_StackRec, *CF2_Stack;
+
+
+  FT_LOCAL( CF2_Stack )
+  cf2_stack_init( FT_Memory  memory,
+                  FT_Error*  error );
+  FT_LOCAL( void )
+  cf2_stack_free( CF2_Stack  stack );
+
+  FT_LOCAL( CF2_UInt )
+  cf2_stack_count( CF2_Stack  stack );
+
+  FT_LOCAL( void )
+  cf2_stack_pushInt( CF2_Stack  stack,
+                     CF2_Int    val );
+  FT_LOCAL( void )
+  cf2_stack_pushFixed( CF2_Stack  stack,
+                       CF2_Fixed  val );
+
+  FT_LOCAL( CF2_Int )
+  cf2_stack_popInt( CF2_Stack  stack );
+  FT_LOCAL( CF2_Fixed )
+  cf2_stack_popFixed( CF2_Stack  stack );
+
+  FT_LOCAL( CF2_Fixed )
+  cf2_stack_getReal( CF2_Stack  stack,
+                     CF2_UInt   idx );
+
+  FT_LOCAL( void )
+  cf2_stack_clear( CF2_Stack  stack );
+
+
+FT_END_HEADER
+
+
+#endif /* __CF2STACK_H__ */
+
+
+/* END */
diff --git a/src/cff/cf2types.h b/src/cff/cf2types.h
new file mode 100644
index 0000000..ac6a022
--- /dev/null
+++ b/src/cff/cf2types.h
@@ -0,0 +1,78 @@
+/***************************************************************************/
+/*                                                                         */
+/*  cf2types.h                                                             */
+/*                                                                         */
+/*    Adobe's code for defining data types (specification only).           */
+/*                                                                         */
+/*  Copyright 2011-2013 Adobe Systems Incorporated.                        */
+/*                                                                         */
+/*  This software, and all works of authorship, whether in source or       */
+/*  object code form as indicated by the copyright notice(s) included      */
+/*  herein (collectively, the "Work") is made available, and may only be   */
+/*  used, modified, and distributed under the FreeType Project License,    */
+/*  LICENSE.TXT.  Additionally, subject to the terms and conditions of the */
+/*  FreeType Project License, each contributor to the Work hereby grants   */
+/*  to any individual or legal entity exercising permissions granted by    */
+/*  the FreeType Project License and this section (hereafter, "You" or     */
+/*  "Your") a perpetual, worldwide, non-exclusive, no-charge,              */
+/*  royalty-free, irrevocable (except as stated in this section) patent    */
+/*  license to make, have made, use, offer to sell, sell, import, and      */
+/*  otherwise transfer the Work, where such license applies only to those  */
+/*  patent claims licensable by such contributor that are necessarily      */
+/*  infringed by their contribution(s) alone or by combination of their    */
+/*  contribution(s) with the Work to which such contribution(s) was        */
+/*  submitted.  If You institute patent litigation against any entity      */
+/*  (including a cross-claim or counterclaim in a lawsuit) alleging that   */
+/*  the Work or a contribution incorporated within the Work constitutes    */
+/*  direct or contributory patent infringement, then any patent licenses   */
+/*  granted to You under this License for that Work shall terminate as of  */
+/*  the date such litigation is filed.                                     */
+/*                                                                         */
+/*  By using, modifying, or distributing the Work you indicate that you    */
+/*  have read and understood the terms and conditions of the               */
+/*  FreeType Project License as well as those provided in this section,    */
+/*  and you accept them fully.                                             */
+/*                                                                         */
+/***************************************************************************/
+
+
+#ifndef __CF2TYPES_H__
+#define __CF2TYPES_H__
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+
+
+FT_BEGIN_HEADER
+
+
+  /*
+   * The data models that we expect to support are as follows:
+   *
+   *   name  char short int long long-long pointer example
+   *  -----------------------------------------------------
+   *   ILP32  8    16    32  32     64*      32    32-bit MacOS, x86
+   *   LLP64  8    16    32  32     64       64    x64
+   *   LP64   8    16    32  64     64       64    64-bit MacOS
+   *
+   *    *) type may be supported by emulation on a 32-bit architecture
+   *
+   */
+
+
+  /* integers at least 32 bits wide */
+#define CF2_UInt  FT_UFast
+#define CF2_Int   FT_Fast
+
+
+  /* fixed-float numbers */
+  typedef FT_Int32  CF2_F16Dot16;
+
+
+FT_END_HEADER
+
+
+#endif /* __CF2TYPES_H__ */
+
+
+/* END */
diff --git a/src/cff/cff.c b/src/cff/cff.c
index fccfd44..c3840b5 100644
--- a/src/cff/cff.c
+++ b/src/cff/cff.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType OpenType driver component (body only).                      */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002 by                                           */
+/*  Copyright 1996-2001, 2002, 2013 by                                     */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -19,6 +19,7 @@
 #define FT_MAKE_OPTION_SINGLE_OBJECT
 
 #include <ft2build.h>
+
 #include "cffpic.c"
 #include "cffdrivr.c"
 #include "cffparse.c"
@@ -27,4 +28,14 @@
 #include "cffgload.c"
 #include "cffcmap.c"
 
+#include "cf2arrst.c"
+#include "cf2blues.c"
+#include "cf2error.c"
+#include "cf2font.c"
+#include "cf2ft.c"
+#include "cf2hints.c"
+#include "cf2intrp.c"
+#include "cf2read.c"
+#include "cf2stack.c"
+
 /* END */
diff --git a/src/cff/cffcmap.c b/src/cff/cffcmap.c
index 1298371..f6e03c6 100644
--- a/src/cff/cffcmap.c
+++ b/src/cff/cffcmap.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    CFF character mapping table (cmap) support (body).                   */
 /*                                                                         */
-/*  Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2010 by                  */
+/*  Copyright 2002-2007, 2010, 2013 by                                     */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -16,6 +16,8 @@
 /***************************************************************************/
 
 
+#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
 #include "cffcmap.h"
 #include "cffload.h"
 
@@ -145,7 +147,7 @@
     /* can't build Unicode map for CID-keyed font */
     /* because we don't know glyph names.         */
     if ( !charset->sids )
-      return CFF_Err_No_Unicode_Glyph_Name;
+      return FT_THROW( No_Unicode_Glyph_Name );
 
     return psnames->unicodes_init( memory,
                                    unicodes,
diff --git a/src/cff/cffdrivr.c b/src/cff/cffdrivr.c
index eb4c14e..c8ca96b 100644
--- a/src/cff/cffdrivr.c
+++ b/src/cff/cffdrivr.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    OpenType font driver implementation (body).                          */
 /*                                                                         */
-/*  Copyright 1996-2012 by                                                 */
+/*  Copyright 1996-2013 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -37,6 +37,8 @@
 
 #include FT_SERVICE_XFREE86_NAME_H
 #include FT_SERVICE_GLYPH_DICT_H
+#include FT_SERVICE_PROPERTIES_H
+#include FT_CFF_DRIVER_H
 
 
   /*************************************************************************/
@@ -115,7 +117,7 @@
     if ( sfnt )
       kerning->x = sfnt->get_kerning( face, left_glyph, right_glyph );
 
-    return CFF_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
@@ -160,7 +162,7 @@
 
 
     if ( !slot )
-      return CFF_Err_Invalid_Slot_Handle;
+      return FT_THROW( Invalid_Slot_Handle );
 
     /* check whether we want a scaled outline or bitmap */
     if ( !size )
@@ -174,7 +176,7 @@
     {
       /* these two objects must have the same parent */
       if ( cffsize->face != cffslot->face )
-        return CFF_Err_Invalid_Face_Handle;
+        return FT_THROW( Invalid_Face_Handle );
     }
 
     /* now load the glyph outline if necessary */
@@ -195,7 +197,7 @@
                     FT_Fixed*  advances )
   {
     FT_UInt       nn;
-    FT_Error      error = CFF_Err_Ok;
+    FT_Error      error = FT_Err_Ok;
     FT_GlyphSlot  slot  = face->glyph;
 
 
@@ -239,7 +241,7 @@
                  " cannot get glyph name from CFF & CEF fonts\n"
                  "                   "
                  " without the `PSNames' module\n" ));
-      error = CFF_Err_Missing_Module;
+      error = FT_THROW( Missing_Module );
       goto Exit;
     }
 
@@ -252,7 +254,7 @@
     if ( gname )
       FT_STRCPYN( buffer, gname, buffer_max );
 
-    error = CFF_Err_Ok;
+    error = FT_Err_Ok;
 
   Exit:
     return error;
@@ -298,7 +300,8 @@
   }
 
 
-  FT_DEFINE_SERVICE_GLYPHDICTREC(cff_service_glyph_dict,
+  FT_DEFINE_SERVICE_GLYPHDICTREC(
+    cff_service_glyph_dict,
     (FT_GlyphDict_GetNameFunc)  cff_get_glyph_name,
     (FT_GlyphDict_NameIndexFunc)cff_get_name_index
   )
@@ -321,7 +324,7 @@
                         PS_FontInfoRec*  afont_info )
   {
     CFF_Font  cff   = (CFF_Font)face->extra.data;
-    FT_Error  error = CFF_Err_Ok;
+    FT_Error  error = FT_Err_Ok;
 
 
     if ( cff && cff->font_info == NULL )
@@ -360,7 +363,8 @@
   }
 
 
-  FT_DEFINE_SERVICE_PSINFOREC(cff_service_ps_info,
+  FT_DEFINE_SERVICE_PSINFOREC(
+    cff_service_ps_info,
     (PS_GetFontInfoFunc)   cff_ps_get_font_info,
     (PS_GetFontExtraFunc)  NULL,
     (PS_HasGlyphNamesFunc) cff_ps_has_glyph_names,
@@ -384,7 +388,8 @@
   }
 
 
-  FT_DEFINE_SERVICE_PSFONTNAMEREC(cff_service_ps_name,
+  FT_DEFINE_SERVICE_PSFONTNAMEREC(
+    cff_service_ps_name,
     (FT_PsName_GetFunc)cff_get_ps_name
   )
 
@@ -404,16 +409,17 @@
                      TT_CMapInfo  *cmap_info )
   {
     FT_CMap   cmap  = FT_CMAP( charmap );
-    FT_Error  error = CFF_Err_Ok;
-    FT_Face    face    = FT_CMAP_FACE( cmap );
-    FT_Library library = FT_FACE_LIBRARY( face );
+    FT_Error  error = FT_Err_Ok;
+
+    FT_Face     face    = FT_CMAP_FACE( cmap );
+    FT_Library  library = FT_FACE_LIBRARY( face );
 
 
     cmap_info->language = 0;
     cmap_info->format   = 0;
 
-    if ( cmap->clazz != &FT_CFF_CMAP_ENCODING_CLASS_REC_GET &&
-         cmap->clazz != &FT_CFF_CMAP_UNICODE_CLASS_REC_GET  )
+    if ( cmap->clazz != &CFF_CMAP_ENCODING_CLASS_REC_GET &&
+         cmap->clazz != &CFF_CMAP_UNICODE_CLASS_REC_GET  )
     {
       FT_Module           sfnt    = FT_Get_Module( library, "sfnt" );
       FT_Service_TTCMaps  service =
@@ -429,7 +435,8 @@
   }
 
 
-  FT_DEFINE_SERVICE_TTCMAPSREC(cff_service_get_cmap_info,
+  FT_DEFINE_SERVICE_TTCMAPSREC(
+    cff_service_get_cmap_info,
     (TT_CMap_Info_GetFunc)cff_get_cmap_info
   )
 
@@ -444,7 +451,7 @@
                const char*  *ordering,
                FT_Int       *supplement )
   {
-    FT_Error  error = CFF_Err_Ok;
+    FT_Error  error = FT_Err_Ok;
     CFF_Font  cff   = (CFF_Font)face->extra.data;
 
 
@@ -455,7 +462,7 @@
 
       if ( dict->cid_registry == 0xFFFFU )
       {
-        error = CFF_Err_Invalid_Argument;
+        error = FT_THROW( Invalid_Argument );
         goto Fail;
       }
 
@@ -499,7 +506,7 @@
   cff_get_is_cid( CFF_Face  face,
                   FT_Bool  *is_cid )
   {
-    FT_Error  error = CFF_Err_Ok;
+    FT_Error  error = FT_Err_Ok;
     CFF_Font  cff   = (CFF_Font)face->extra.data;
 
 
@@ -523,7 +530,7 @@
                                 FT_UInt   glyph_index,
                                 FT_UInt  *cid )
   {
-    FT_Error  error = CFF_Err_Ok;
+    FT_Error  error = FT_Err_Ok;
     CFF_Font  cff;
 
 
@@ -537,13 +544,13 @@
 
       if ( dict->cid_registry == 0xFFFFU )
       {
-        error = CFF_Err_Invalid_Argument;
+        error = FT_THROW( Invalid_Argument );
         goto Fail;
       }
 
       if ( glyph_index > cff->num_glyphs )
       {
-        error = CFF_Err_Invalid_Argument;
+        error = FT_THROW( Invalid_Argument );
         goto Fail;
       }
 
@@ -558,13 +565,100 @@
   }
 
 
-  FT_DEFINE_SERVICE_CIDREC(cff_service_cid_info,
+  FT_DEFINE_SERVICE_CIDREC(
+    cff_service_cid_info,
     (FT_CID_GetRegistryOrderingSupplementFunc)cff_get_ros,
     (FT_CID_GetIsInternallyCIDKeyedFunc)      cff_get_is_cid,
     (FT_CID_GetCIDFromGlyphIndexFunc)         cff_get_cid_from_glyph_index
   )
 
 
+  /*
+   *  PROPERTY SERVICE
+   *
+   */
+  static FT_Error
+  cff_property_set( FT_Module    module,         /* CFF_Driver */
+                    const char*  property_name,
+                    const void*  value )
+  {
+    FT_Error    error  = FT_Err_Ok;
+    CFF_Driver  driver = (CFF_Driver)module;
+
+
+    if ( !ft_strcmp( property_name, "hinting-engine" ) )
+    {
+      FT_UInt*  hinting_engine = (FT_UInt*)value;
+
+
+#ifndef CFF_CONFIG_OPTION_OLD_ENGINE
+      if ( *hinting_engine != FT_CFF_HINTING_ADOBE )
+        error = FT_ERR( Unimplemented_Feature );
+      else
+#endif
+        driver->hinting_engine = *hinting_engine;
+
+      return error;
+    }
+    else if ( !ft_strcmp( property_name, "no-stem-darkening" ) )
+    {
+      FT_Bool*  no_stem_darkening = (FT_Bool*)value;
+
+
+      driver->no_stem_darkening = *no_stem_darkening;
+
+      return error;
+    }
+
+    FT_TRACE0(( "cff_property_set: missing property `%s'\n",
+                property_name ));
+    return FT_THROW( Missing_Property );
+  }
+
+
+  static FT_Error
+  cff_property_get( FT_Module    module,         /* CFF_Driver */
+                    const char*  property_name,
+                    const void*  value )
+  {
+    FT_Error    error  = FT_Err_Ok;
+    CFF_Driver  driver = (CFF_Driver)module;
+
+    FT_UInt  hinting_engine    = driver->hinting_engine;
+    FT_Bool  no_stem_darkening = driver->no_stem_darkening;
+
+
+    if ( !ft_strcmp( property_name, "hinting-engine" ) )
+    {
+      FT_UInt*  val = (FT_UInt*)value;
+
+
+      *val = hinting_engine;
+
+      return error;
+    }
+    else if ( !ft_strcmp( property_name, "no-stem-darkening" ) )
+    {
+      FT_Bool*  val = (FT_Bool*)value;
+
+
+      *val = no_stem_darkening;
+
+      return error;
+    }
+
+    FT_TRACE0(( "cff_property_get: missing property `%s'\n",
+                property_name ));
+    return FT_THROW( Missing_Property );
+  }
+
+
+  FT_DEFINE_SERVICE_PROPERTIESREC(
+    cff_service_properties,
+    (FT_Properties_SetFunc)cff_property_set,
+    (FT_Properties_GetFunc)cff_property_get )
+
+
   /*************************************************************************/
   /*************************************************************************/
   /*************************************************************************/
@@ -576,25 +670,31 @@
   /*************************************************************************/
   /*************************************************************************/
   /*************************************************************************/
+
 #ifndef FT_CONFIG_OPTION_NO_GLYPH_NAMES
-  FT_DEFINE_SERVICEDESCREC6(cff_services,
+  FT_DEFINE_SERVICEDESCREC7(
+    cff_services,
     FT_SERVICE_ID_XF86_NAME,            FT_XF86_FORMAT_CFF,
-    FT_SERVICE_ID_POSTSCRIPT_INFO,      &FT_CFF_SERVICE_PS_INFO_GET,
-    FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &FT_CFF_SERVICE_PS_NAME_GET,
-    FT_SERVICE_ID_GLYPH_DICT,           &FT_CFF_SERVICE_GLYPH_DICT_GET,
-    FT_SERVICE_ID_TT_CMAP,              &FT_CFF_SERVICE_GET_CMAP_INFO_GET,
-    FT_SERVICE_ID_CID,                  &FT_CFF_SERVICE_CID_INFO_GET
+    FT_SERVICE_ID_POSTSCRIPT_INFO,      &CFF_SERVICE_PS_INFO_GET,
+    FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &CFF_SERVICE_PS_NAME_GET,
+    FT_SERVICE_ID_GLYPH_DICT,           &CFF_SERVICE_GLYPH_DICT_GET,
+    FT_SERVICE_ID_TT_CMAP,              &CFF_SERVICE_GET_CMAP_INFO_GET,
+    FT_SERVICE_ID_CID,                  &CFF_SERVICE_CID_INFO_GET,
+    FT_SERVICE_ID_PROPERTIES,           &CFF_SERVICE_PROPERTIES_GET
   )
 #else
-  FT_DEFINE_SERVICEDESCREC5(cff_services,
+  FT_DEFINE_SERVICEDESCREC6(
+    cff_services,
     FT_SERVICE_ID_XF86_NAME,            FT_XF86_FORMAT_CFF,
-    FT_SERVICE_ID_POSTSCRIPT_INFO,      &FT_CFF_SERVICE_PS_INFO_GET,
-    FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &FT_CFF_SERVICE_PS_NAME_GET,
-    FT_SERVICE_ID_TT_CMAP,              &FT_CFF_SERVICE_GET_CMAP_INFO_GET,
-    FT_SERVICE_ID_CID,                  &FT_CFF_SERVICE_CID_INFO_GET
+    FT_SERVICE_ID_POSTSCRIPT_INFO,      &CFF_SERVICE_PS_INFO_GET,
+    FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &CFF_SERVICE_PS_NAME_GET,
+    FT_SERVICE_ID_TT_CMAP,              &CFF_SERVICE_GET_CMAP_INFO_GET,
+    FT_SERVICE_ID_CID,                  &CFF_SERVICE_CID_INFO_GET,
+    FT_SERVICE_ID_PROPERTIES,           &CFF_SERVICE_PROPERTIES_GET
   )
 #endif
 
+
   FT_CALLBACK_DEF( FT_Module_Interface )
   cff_get_interface( FT_Module    driver,       /* CFF_Driver */
                      const char*  module_interface )
@@ -604,7 +704,7 @@
     FT_Module_Interface  result;
 
 
-    /* FT_CFF_SERVICES_GET derefers `library' in PIC mode */
+    /* CFF_SERVICES_GET derefers `library' in PIC mode */
 #ifdef FT_CONFIG_OPTION_PIC
     if ( !driver )
       return NULL;
@@ -613,7 +713,7 @@
       return NULL;
 #endif
 
-    result = ft_service_list_lookup( FT_CFF_SERVICES_GET, module_interface );
+    result = ft_service_list_lookup( CFF_SERVICES_GET, module_interface );
     if ( result != NULL )
       return result;
 
@@ -641,7 +741,8 @@
 #define CFF_SIZE_SELECT 0
 #endif
 
-  FT_DEFINE_DRIVER( cff_driver_class,
+  FT_DEFINE_DRIVER(
+    cff_driver_class,
 
       FT_MODULE_FONT_DRIVER       |
       FT_MODULE_DRIVER_SCALABLE   |
@@ -670,9 +771,6 @@
     cff_slot_init,
     cff_slot_done,
 
-    ft_stub_set_char_sizes,  /* FT_CONFIG_OPTION_OLD_INTERNALS */
-    ft_stub_set_pixel_sizes, /* FT_CONFIG_OPTION_OLD_INTERNALS */
-
     cff_glyph_load,
 
     cff_get_kerning,
diff --git a/src/cff/cffgload.c b/src/cff/cffgload.c
index 84847fd..1904ca0 100644
--- a/src/cff/cffgload.c
+++ b/src/cff/cffgload.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    OpenType Glyph Loader (body).                                        */
 /*                                                                         */
-/*  Copyright 1996-2012 by                                                 */
+/*  Copyright 1996-2013 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -21,10 +21,12 @@
 #include FT_INTERNAL_STREAM_H
 #include FT_INTERNAL_SFNT_H
 #include FT_OUTLINE_H
+#include FT_CFF_DRIVER_H
 
 #include "cffobjs.h"
 #include "cffload.h"
 #include "cffgload.h"
+#include "cf2ft.h"      /* for cf2_decoder_parse_charstrings */
 
 #include "cfferrs.h"
 
@@ -39,6 +41,8 @@
 #define FT_COMPONENT  trace_cffgload
 
 
+#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
+
   typedef enum  CFF_Operator_
   {
     cff_op_unknown = 0,
@@ -209,6 +213,8 @@
     2  /* setcurrentpoint */
   };
 
+#endif /* CFF_CONFIG_OPTION_OLD_ENGINE */
+
 
   /*************************************************************************/
   /*************************************************************************/
@@ -412,7 +418,7 @@
     CFF_Builder  *builder = &decoder->builder;
     CFF_Font      cff     = (CFF_Font)builder->face->extra.data;
     CFF_SubFont   sub     = &cff->top_font;
-    FT_Error      error   = CFF_Err_Ok;
+    FT_Error      error   = FT_Err_Ok;
 
 
     /* manage CID fonts */
@@ -424,7 +430,7 @@
       if ( fd_index >= cff->num_subfonts )
       {
         FT_TRACE4(( "cff_decoder_prepare: invalid CID subfont index\n" ));
-        error = CFF_Err_Invalid_File_Format;
+        error = FT_THROW( Invalid_File_Format );
         goto Exit;
       }
 
@@ -455,22 +461,24 @@
     decoder->glyph_width   = sub->private_dict.default_width;
     decoder->nominal_width = sub->private_dict.nominal_width;
 
+    decoder->current_subfont = sub;     /* for Adobe's CFF handler */
+
   Exit:
     return error;
   }
 
 
   /* check that there is enough space for `count' more points */
-  static FT_Error
-  check_points( CFF_Builder*  builder,
-                FT_Int        count )
+  FT_LOCAL_DEF( FT_Error )
+  cff_check_points( CFF_Builder*  builder,
+                    FT_Int        count )
   {
     return FT_GLYPHLOADER_CHECK_POINTS( builder->loader, count, 0 );
   }
 
 
   /* add a new point, do not check space */
-  static void
+  FT_LOCAL_DEF( void )
   cff_builder_add_point( CFF_Builder*  builder,
                          FT_Pos        x,
                          FT_Pos        y,
@@ -484,9 +492,22 @@
       FT_Vector*  point   = outline->points + outline->n_points;
       FT_Byte*    control = (FT_Byte*)outline->tags + outline->n_points;
 
+#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
+      CFF_Driver  driver  = (CFF_Driver)FT_FACE_DRIVER( builder->face );
 
-      point->x = x >> 16;
-      point->y = y >> 16;
+
+      if ( driver->hinting_engine == FT_CFF_HINTING_FREETYPE )
+      {
+        point->x = x >> 16;
+        point->y = y >> 16;
+      }
+      else
+#endif
+      {
+        /* cf2_decoder_parse_charstrings uses 16.16 coordinates */
+        point->x = x >> 10;
+        point->y = y >> 10;
+      }
       *control = (FT_Byte)( flag ? FT_CURVE_TAG_ON : FT_CURVE_TAG_CUBIC );
     }
 
@@ -495,7 +516,7 @@
 
 
   /* check space for a new on-curve point, then add it */
-  static FT_Error
+  FT_LOCAL_DEF( FT_Error )
   cff_builder_add_point1( CFF_Builder*  builder,
                           FT_Pos        x,
                           FT_Pos        y )
@@ -503,7 +524,7 @@
     FT_Error  error;
 
 
-    error = check_points( builder, 1 );
+    error = cff_check_points( builder, 1 );
     if ( !error )
       cff_builder_add_point( builder, x, y, 1 );
 
@@ -522,7 +543,7 @@
     if ( !builder->load_points )
     {
       outline->n_contours++;
-      return CFF_Err_Ok;
+      return FT_Err_Ok;
     }
 
     error = FT_GLYPHLOADER_CHECK_POINTS( builder->loader, 0, 1 );
@@ -540,12 +561,12 @@
 
 
   /* if a path was begun, add its first on-curve point */
-  static FT_Error
+  FT_LOCAL_DEF( FT_Error )
   cff_builder_start_point( CFF_Builder*  builder,
                            FT_Pos        x,
                            FT_Pos        y )
   {
-    FT_Error  error = CFF_Err_Ok;
+    FT_Error  error = FT_Err_Ok;
 
 
     /* test whether we are building a new contour */
@@ -562,7 +583,7 @@
 
 
   /* close the current contour */
-  static void
+  FT_LOCAL_DEF( void )
   cff_builder_close_contour( CFF_Builder*  builder )
   {
     FT_Outline*  outline = builder->current;
@@ -607,7 +628,7 @@
   }
 
 
-  static FT_Int
+  FT_LOCAL_DEF( FT_Int )
   cff_lookup_glyph_by_stdcharcode( CFF_Font  cff,
                                    FT_Int    charcode )
   {
@@ -636,7 +657,7 @@
   }
 
 
-  static FT_Error
+  FT_LOCAL_DEF( FT_Error )
   cff_get_glyph_data( TT_Face    face,
                       FT_UInt    glyph_index,
                       FT_Byte**  pointer,
@@ -672,7 +693,7 @@
   }
 
 
-  static void
+  FT_LOCAL_DEF( void )
   cff_free_glyph_data( TT_Face    face,
                        FT_Byte**  pointer,
                        FT_ULong   length )
@@ -707,6 +728,8 @@
   }
 
 
+#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
+
   static FT_Error
   cff_operator_seac( CFF_Decoder*  decoder,
                      FT_Pos        asb,
@@ -728,7 +751,7 @@
     if ( decoder->seac )
     {
       FT_ERROR(( "cff_operator_seac: invalid nested seac\n" ));
-      return CFF_Err_Syntax_Error;
+      return FT_THROW( Syntax_Error );
     }
 
     adx += decoder->builder.left_bearing.x;
@@ -756,7 +779,7 @@
     {
       FT_ERROR(( "cff_operator_seac:"
                  " invalid seac character code arguments\n" ));
-      return CFF_Err_Syntax_Error;
+      return FT_THROW( Syntax_Error );
     }
 
     /* If we are trying to load a composite glyph, do not load the */
@@ -925,7 +948,7 @@
     limit = zone->limit  = charstring_base + charstring_len;
     ip    = zone->cursor = zone->base;
 
-    error = CFF_Err_Ok;
+    error = FT_Err_Ok;
 
     x = builder->pos_x;
     y = builder->pos_y;
@@ -953,11 +976,14 @@
 
 
         /* this is an operand, push it on the stack */
+
+        /* if we use shifts, all computations are done with unsigned */
+        /* values; the conversion to a signed value is the last step */
         if ( v == 28 )
         {
           if ( ip + 1 >= limit )
             goto Syntax_Error;
-          val = (FT_Short)( ( (FT_Short)ip[0] << 8 ) | ip[1] );
+          val = (FT_Short)( ( (FT_UShort)ip[0] << 8 ) | ip[1] );
           ip += 2;
         }
         else if ( v < 247 )
@@ -978,10 +1004,10 @@
         {
           if ( ip + 3 >= limit )
             goto Syntax_Error;
-          val = ( (FT_Int32)ip[0] << 24 ) |
-                ( (FT_Int32)ip[1] << 16 ) |
-                ( (FT_Int32)ip[2] <<  8 ) |
-                            ip[3];
+          val = (FT_Int32)( ( (FT_UInt32)ip[0] << 24 ) |
+                            ( (FT_UInt32)ip[1] << 16 ) |
+                            ( (FT_UInt32)ip[2] <<  8 ) |
+                              (FT_UInt32)ip[3]         );
           ip    += 4;
           if ( charstring_type == 2 )
             shift = 0;
@@ -989,12 +1015,12 @@
         if ( decoder->top - stack >= CFF_MAX_OPERANDS )
           goto Stack_Overflow;
 
-        val           <<= shift;
+        val             = (FT_Int32)( (FT_UInt32)val << shift );
         *decoder->top++ = val;
 
 #ifdef FT_DEBUG_LEVEL_TRACE
         if ( !( val & 0xFFFFL ) )
-          FT_TRACE4(( " %ld", (FT_Int32)( val >> 16 ) ));
+          FT_TRACE4(( " %hd", (FT_Short)( (FT_UInt32)val >> 16 ) ));
         else
           FT_TRACE4(( " %.2f", val / 65536.0 ));
 #endif
@@ -1411,8 +1437,8 @@
         case cff_op_rlineto:
           FT_TRACE4(( " rlineto\n" ));
 
-          if ( cff_builder_start_point ( builder, x, y ) ||
-               check_points( builder, num_args / 2 )     )
+          if ( cff_builder_start_point( builder, x, y )  ||
+               cff_check_points( builder, num_args / 2 ) )
             goto Fail;
 
           if ( num_args < 2 )
@@ -1446,8 +1472,8 @@
             if ( num_args == 0 )
               break;
 
-            if ( cff_builder_start_point ( builder, x, y ) ||
-                 check_points( builder, num_args )         )
+            if ( cff_builder_start_point( builder, x, y ) ||
+                 cff_check_points( builder, num_args )    )
               goto Fail;
 
             args = stack;
@@ -1480,8 +1506,8 @@
 
             nargs = num_args - num_args % 6;
 
-            if ( cff_builder_start_point ( builder, x, y ) ||
-                 check_points( builder, nargs / 2 )     )
+            if ( cff_builder_start_point( builder, x, y ) ||
+                 cff_check_points( builder, nargs / 2 )   )
               goto Fail;
 
             args -= nargs;
@@ -1529,7 +1555,7 @@
               nargs--;
             }
 
-            if ( check_points( builder, 3 * ( nargs / 4 ) ) )
+            if ( cff_check_points( builder, 3 * ( nargs / 4 ) ) )
               goto Fail;
 
             while ( args < decoder->top )
@@ -1573,7 +1599,7 @@
               nargs--;
             }
 
-            if ( check_points( builder, 3 * ( nargs / 4 ) ) )
+            if ( cff_check_points( builder, 3 * ( nargs / 4 ) ) )
               goto Fail;
 
             while ( args < decoder->top )
@@ -1613,7 +1639,7 @@
             nargs = num_args & ~2;
 
             args -= nargs;
-            if ( check_points( builder, ( nargs / 4 ) * 3 ) )
+            if ( cff_check_points( builder, ( nargs / 4 ) * 3 ) )
               goto Stack_Underflow;
 
             phase = ( op == cff_op_hvcurveto );
@@ -1666,8 +1692,8 @@
             nargs     = num_args & ~1;
             num_lines = ( nargs - 6 ) / 2;
 
-            if ( cff_builder_start_point( builder, x, y ) ||
-                 check_points( builder, num_lines + 3 )   )
+            if ( cff_builder_start_point( builder, x, y )   ||
+                 cff_check_points( builder, num_lines + 3 ) )
               goto Fail;
 
             args -= nargs;
@@ -1711,8 +1737,8 @@
             nargs      = nargs - nargs % 6 + 2;
             num_curves = ( nargs - 2 ) / 6;
 
-            if ( cff_builder_start_point ( builder, x, y ) ||
-                 check_points( builder, num_curves * 3 + 2 ) )
+            if ( cff_builder_start_point( builder, x, y )        ||
+                 cff_check_points( builder, num_curves * 3 + 2 ) )
               goto Fail;
 
             args -= nargs;
@@ -1752,7 +1778,7 @@
             /* -- make sure we have enough space for the start point if it */
             /* needs to be added                                           */
             if ( cff_builder_start_point( builder, x, y ) ||
-                 check_points( builder, 6 )               )
+                 cff_check_points( builder, 6 )           )
               goto Fail;
 
             /* record the starting point's y position for later use */
@@ -1801,7 +1827,7 @@
 
             /* adding six more points; 4 control points, 2 on-curve points */
             if ( cff_builder_start_point( builder, x, y ) ||
-                 check_points( builder, 6 )               )
+                 cff_check_points( builder, 6 )           )
               goto Fail;
 
             /* record the starting point's y-position for later use */
@@ -1854,7 +1880,7 @@
 
             /* adding six more points; 4 control points, 2 on-curve points */
             if ( cff_builder_start_point( builder, x, y ) ||
-                 check_points( builder, 6 )               )
+                 cff_check_points( builder, 6 )           )
               goto Fail;
 
             /* record the starting point's x, y position for later use */
@@ -1917,7 +1943,7 @@
             FT_TRACE4(( " flex\n" ));
 
             if ( cff_builder_start_point( builder, x, y ) ||
-                 check_points( builder, 6 )               )
+                 cff_check_points( builder, 6 )           )
               goto Fail;
 
             for ( count = 6; count > 0; count-- )
@@ -1968,7 +1994,7 @@
           else
           {
             if ( !error )
-              error = CFF_Err_Ok;
+              error = FT_Err_Ok;
 
             cff_builder_close_contour( builder );
 
@@ -2470,7 +2496,7 @@
             FT_ERROR(( " %d", ip[0] ));
           FT_ERROR(( "\n" ));
 
-          return CFF_Err_Unimplemented_Feature;
+          return FT_THROW( Unimplemented_Feature );
         }
 
         decoder->top = args;
@@ -2489,17 +2515,19 @@
 
   Syntax_Error:
     FT_TRACE4(( "cff_decoder_parse_charstrings: syntax error\n" ));
-    return CFF_Err_Invalid_File_Format;
+    return FT_THROW( Invalid_File_Format );
 
   Stack_Underflow:
     FT_TRACE4(( "cff_decoder_parse_charstrings: stack underflow\n" ));
-    return CFF_Err_Too_Few_Arguments;
+    return FT_THROW( Too_Few_Arguments );
 
   Stack_Overflow:
     FT_TRACE4(( "cff_decoder_parse_charstrings: stack overflow\n" ));
-    return CFF_Err_Stack_Overflow;
+    return FT_THROW( Stack_Overflow );
   }
 
+#endif /* CFF_CONFIG_OPTION_OLD_ENGINE */
+
 
   /*************************************************************************/
   /*************************************************************************/
@@ -2526,7 +2554,7 @@
   cff_compute_max_advance( TT_Face  face,
                            FT_Int*  max_advance )
   {
-    FT_Error     error = CFF_Err_Ok;
+    FT_Error     error = FT_Err_Ok;
     CFF_Decoder  decoder;
     FT_Int       glyph_index;
     CFF_Font     cff = (CFF_Font)face->other;
@@ -2564,12 +2592,12 @@
       }
 
       /* ignore the error if one has occurred -- skip to next glyph */
-      error = CFF_Err_Ok;
+      error = FT_Err_Ok;
     }
 
     *max_advance = decoder.builder.advance.x;
 
-    return CFF_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
@@ -2585,7 +2613,7 @@
     FT_Error     error;
     CFF_Decoder  decoder;
     TT_Face      face = (TT_Face)glyph->root.face;
-    FT_Bool      hinting, force_scaling;
+    FT_Bool      hinting, scaled, force_scaling;
     CFF_Font     cff  = (CFF_Font)face->extra.data;
 
     FT_Matrix    font_matrix;
@@ -2606,11 +2634,11 @@
         glyph_index = cff_charset_cid_to_gindex( &cff->charset,
                                                  glyph_index );
         if ( glyph_index == 0 )
-          return CFF_Err_Invalid_Argument;
+          return FT_THROW( Invalid_Argument );
       }
     }
     else if ( glyph_index >= cff->num_glyphs )
-      return CFF_Err_Invalid_Argument;
+      return FT_THROW( Invalid_Argument );
 
     if ( load_flags & FT_LOAD_NO_RECURSE )
       load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
@@ -2653,6 +2681,11 @@
 
         if ( !error )
         {
+          FT_Bool    has_vertical_info;
+          FT_UShort  advance;
+          FT_Short   dummy;
+
+
           glyph->root.outline.n_points   = 0;
           glyph->root.outline.n_contours = 0;
 
@@ -2679,6 +2712,39 @@
             glyph->root.bitmap_left = metrics.horiBearingX;
             glyph->root.bitmap_top  = metrics.horiBearingY;
           }
+
+          /* compute linear advance widths */
+
+          ( (SFNT_Service)face->sfnt )->get_metrics( face, 0,
+                                                     glyph_index,
+                                                     &dummy,
+                                                     &advance );
+          glyph->root.linearHoriAdvance = advance;
+
+          has_vertical_info = FT_BOOL(
+                                face->vertical_info                   &&
+                                face->vertical.number_Of_VMetrics > 0 );
+
+          /* get the vertical metrics from the vtmx table if we have one */
+          if ( has_vertical_info )
+          {
+            ( (SFNT_Service)face->sfnt )->get_metrics( face, 1,
+                                                       glyph_index,
+                                                       &dummy,
+                                                       &advance );
+            glyph->root.linearVertAdvance = advance;
+          }
+          else
+          {
+            /* make up vertical ones */
+            if ( face->os2.version != 0xFFFFU )
+              glyph->root.linearVertAdvance = (FT_Pos)
+                ( face->os2.sTypoAscender - face->os2.sTypoDescender );
+            else
+              glyph->root.linearVertAdvance = (FT_Pos)
+                ( face->horizontal.Ascender - face->horizontal.Descender );
+          }
+
           return error;
         }
       }
@@ -2688,7 +2754,7 @@
 
     /* return immediately if we only want the embedded bitmaps */
     if ( load_flags & FT_LOAD_SBITS_ONLY )
-      return CFF_Err_Invalid_Argument;
+      return FT_THROW( Invalid_Argument );
 
     /* if we have a CID subfont, use its matrix (which has already */
     /* been multiplied with the root matrix)                       */
@@ -2700,6 +2766,7 @@
       FT_Byte   fd_index = cff_fd_select_get( &cff->fd_select,
                                               glyph_index );
 
+
       if ( fd_index >= cff->num_subfonts )
         fd_index = (FT_Byte)( cff->num_subfonts - 1 );
 
@@ -2727,12 +2794,21 @@
     glyph->root.outline.n_points   = 0;
     glyph->root.outline.n_contours = 0;
 
-    hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE   ) == 0 &&
-                       ( load_flags & FT_LOAD_NO_HINTING ) == 0 );
+    /* top-level code ensures that FT_LOAD_NO_HINTING is set */
+    /* if FT_LOAD_NO_SCALE is active                         */
+    hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_HINTING ) == 0 );
+    scaled  = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE   ) == 0 );
 
+    glyph->hint        = hinting;
+    glyph->scaled      = scaled;
     glyph->root.format = FT_GLYPH_FORMAT_OUTLINE;  /* by default */
 
     {
+#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
+      CFF_Driver  driver = (CFF_Driver)FT_FACE_DRIVER( face );
+#endif
+
+
       FT_Byte*  charstring;
       FT_ULong  charstring_len;
 
@@ -2756,9 +2832,26 @@
       if ( error )
         goto Glyph_Build_Finished;
 
-      error = cff_decoder_parse_charstrings( &decoder,
-                                             charstring,
-                                             charstring_len );
+#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
+      /* choose which CFF renderer to use */
+      if ( driver->hinting_engine == FT_CFF_HINTING_FREETYPE )
+        error = cff_decoder_parse_charstrings( &decoder,
+                                               charstring,
+                                               charstring_len );
+      else
+#endif
+      {
+        error = cf2_decoder_parse_charstrings( &decoder,
+                                               charstring,
+                                               charstring_len );
+
+        /* Adobe's engine uses 16.16 numbers everywhere;              */
+        /* as a consequence, glyphs larger than 2000ppem get rejected */
+        if ( FT_ERR_EQ( error, Glyph_Too_Big ) )
+        {
+          /* XXX to be implemented */
+        }
+      }
 
       cff_free_glyph_data( face, &charstring, charstring_len );
 
@@ -2856,14 +2949,8 @@
         glyph->root.linearHoriAdvance           = decoder.glyph_width;
         glyph->root.internal->glyph_transformed = 0;
 
-#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
-        has_vertical_info = FT_BOOL( face->vertical_info                   &&
-                                     face->vertical.number_Of_VMetrics > 0 &&
-                                     face->vertical.long_metrics           );
-#else
         has_vertical_info = FT_BOOL( face->vertical_info                   &&
                                      face->vertical.number_Of_VMetrics > 0 );
-#endif
 
         /* get the vertical metrics from the vtmx table if we have one */
         if ( has_vertical_info )
diff --git a/src/cff/cffgload.h b/src/cff/cffgload.h
index 38937be..41df7db 100644
--- a/src/cff/cffgload.h
+++ b/src/cff/cffgload.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    OpenType Glyph Loader (specification).                               */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003, 2004, 2006, 2007, 2008, 2009 by       */
+/*  Copyright 1996-2004, 2006-2009, 2013 by                                */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -106,6 +106,41 @@
   } CFF_Builder;
 
 
+  FT_LOCAL( FT_Error )
+  cff_check_points( CFF_Builder*  builder,
+                    FT_Int        count );
+
+  FT_LOCAL( void )
+  cff_builder_add_point( CFF_Builder*  builder,
+                         FT_Pos        x,
+                         FT_Pos        y,
+                         FT_Byte       flag );
+  FT_LOCAL( FT_Error )
+  cff_builder_add_point1( CFF_Builder*  builder,
+                          FT_Pos        x,
+                          FT_Pos        y );
+  FT_LOCAL( FT_Error )
+  cff_builder_start_point( CFF_Builder*  builder,
+                           FT_Pos        x,
+                           FT_Pos        y );
+  FT_LOCAL( void )
+  cff_builder_close_contour( CFF_Builder*  builder );
+
+
+  FT_LOCAL( FT_Int )
+  cff_lookup_glyph_by_stdcharcode( CFF_Font  cff,
+                                   FT_Int    charcode );
+  FT_LOCAL( FT_Error )
+  cff_get_glyph_data( TT_Face    face,
+                      FT_UInt    glyph_index,
+                      FT_Byte**  pointer,
+                      FT_ULong*  length );
+  FT_LOCAL( void )
+  cff_free_glyph_data( TT_Face    face,
+                       FT_Byte**  pointer,
+                       FT_ULong   length );
+
+
   /* execution context charstring zone */
 
   typedef struct  CFF_Decoder_Zone_
@@ -156,6 +191,8 @@
 
     FT_Bool            seac;
 
+    CFF_SubFont        current_subfont; /* for current glyph_index */
+
   } CFF_Decoder;
 
 
@@ -181,10 +218,12 @@
 
 #endif /* 0 */
 
+#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
   FT_LOCAL( FT_Error )
   cff_decoder_parse_charstrings( CFF_Decoder*  decoder,
                                  FT_Byte*      charstring_base,
                                  FT_ULong      charstring_len );
+#endif
 
   FT_LOCAL( FT_Error )
   cff_slot_load( CFF_GlyphSlot  glyph,
diff --git a/src/cff/cffload.c b/src/cff/cffload.c
index 2be6ba0..64b4971 100644
--- a/src/cff/cffload.c
+++ b/src/cff/cffload.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    OpenType and CFF data/program tables loader (body).                  */
 /*                                                                         */
-/*  Copyright 1996-2011 by                                                 */
+/*  Copyright 1996-2013 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -250,7 +250,7 @@
 
       if ( offsize < 1 || offsize > 4 )
       {
-        error = CFF_Err_Invalid_Table;
+        error = FT_THROW( Invalid_Table );
         goto Exit;
       }
 
@@ -269,7 +269,7 @@
 
       if ( size == 0 )
       {
-        error = CFF_Err_Invalid_Table;
+        error = FT_THROW( Invalid_Table );
         goto Exit;
       }
 
@@ -318,7 +318,7 @@
   static FT_Error
   cff_index_load_offsets( CFF_Index  idx )
   {
-    FT_Error   error  = CFF_Err_Ok;
+    FT_Error   error  = FT_Err_Ok;
     FT_Stream  stream = idx->stream;
     FT_Memory  memory = stream->memory;
 
@@ -384,9 +384,10 @@
                           FT_Byte***  table,
                           FT_Byte**   pool )
   {
-    FT_Error   error     = CFF_Err_Ok;
+    FT_Error   error     = FT_Err_Ok;
     FT_Memory  memory    = idx->stream->memory;
-    FT_Byte**  t = NULL;
+
+    FT_Byte**  t         = NULL;
     FT_Byte*   new_bytes = NULL;
 
 
@@ -471,7 +472,7 @@
                             FT_Byte**  pbytes,
                             FT_ULong*  pbyte_len )
   {
-    FT_Error  error = CFF_Err_Ok;
+    FT_Error  error = FT_Err_Ok;
 
 
     if ( idx && idx->count > element )
@@ -556,7 +557,7 @@
       }
     }
     else
-      error = CFF_Err_Invalid_Argument;
+      error = FT_THROW( Invalid_Argument );
 
   Exit:
     return error;
@@ -696,7 +697,7 @@
       break;
 
     default:    /* hmm... that's wrong */
-      error = CFF_Err_Invalid_File_Format;
+      error = FT_THROW( Invalid_File_Format );
     }
 
   Exit:
@@ -780,7 +781,7 @@
                             FT_UInt      num_glyphs,
                             FT_Memory    memory )
   {
-    FT_Error   error   = CFF_Err_Ok;
+    FT_Error   error   = FT_Err_Ok;
     FT_UInt    i;
     FT_Long    j;
     FT_UShort  max_cid = 0;
@@ -859,7 +860,7 @@
                     FT_Bool      invert )
   {
     FT_Memory  memory = stream->memory;
-    FT_Error   error  = CFF_Err_Ok;
+    FT_Error   error  = FT_Err_Ok;
     FT_UShort  glyph_sid;
 
 
@@ -943,7 +944,7 @@
 
       default:
         FT_ERROR(( "cff_charset_load: invalid table format\n" ));
-        error = CFF_Err_Invalid_File_Format;
+        error = FT_THROW( Invalid_File_Format );
         goto Exit;
       }
     }
@@ -966,7 +967,7 @@
         {
           FT_ERROR(( "cff_charset_load: implicit charset larger than\n"
                      "predefined charset (Adobe ISO-Latin)\n" ));
-          error = CFF_Err_Invalid_File_Format;
+          error = FT_THROW( Invalid_File_Format );
           goto Exit;
         }
 
@@ -984,7 +985,7 @@
         {
           FT_ERROR(( "cff_charset_load: implicit charset larger than\n"
                      "predefined charset (Adobe Expert)\n" ));
-          error = CFF_Err_Invalid_File_Format;
+          error = FT_THROW( Invalid_File_Format );
           goto Exit;
         }
 
@@ -1002,7 +1003,7 @@
         {
           FT_ERROR(( "cff_charset_load: implicit charset larger than\n"
                      "predefined charset (Adobe Expert Subset)\n" ));
-          error = CFF_Err_Invalid_File_Format;
+          error = FT_THROW( Invalid_File_Format );
           goto Exit;
         }
 
@@ -1016,7 +1017,7 @@
         break;
 
       default:
-        error = CFF_Err_Invalid_File_Format;
+        error = FT_THROW( Invalid_File_Format );
         goto Exit;
       }
     }
@@ -1057,7 +1058,7 @@
                      FT_ULong      base_offset,
                      FT_ULong      offset )
   {
-    FT_Error   error = CFF_Err_Ok;
+    FT_Error   error = FT_Err_Ok;
     FT_UInt    count;
     FT_UInt    j;
     FT_UShort  glyph_sid;
@@ -1067,7 +1068,7 @@
     /* Check for charset->sids.  If we do not have this, we fail. */
     if ( !charset->sids )
     {
-      error = CFF_Err_Invalid_File_Format;
+      error = FT_THROW( Invalid_File_Format );
       goto Exit;
     }
 
@@ -1187,7 +1188,7 @@
 
       default:
         FT_ERROR(( "cff_encoding_load: invalid table format\n" ));
-        error = CFF_Err_Invalid_File_Format;
+        error = FT_THROW( Invalid_File_Format );
         goto Exit;
       }
 
@@ -1280,7 +1281,7 @@
 
       default:
         FT_ERROR(( "cff_encoding_load: invalid table format\n" ));
-        error = CFF_Err_Invalid_File_Format;
+        error = FT_THROW( Invalid_File_Format );
         goto Exit;
       }
     }
@@ -1313,7 +1314,7 @@
     /* set defaults */
     FT_MEM_ZERO( top, sizeof ( *top ) );
 
-    top->underline_position  = -100L << 16;
+    top->underline_position  = -( 100L << 16 );
     top->underline_thickness = 50L << 16;
     top->charstring_type     = 2;
     top->font_matrix.xx      = 0x10000L;
@@ -1439,6 +1440,7 @@
     FT_ULong         base_offset;
     CFF_FontRecDict  dict;
     CFF_IndexRec     string_index;
+    FT_Int           subfont_index;
 
 
     FT_ZERO( font );
@@ -1459,7 +1461,7 @@
          font->absolute_offsize > 4 )
     {
       FT_TRACE2(( "  not a CFF font header\n" ));
-      error = CFF_Err_Unknown_File_Format;
+      error = FT_THROW( Unknown_File_Format );
       goto Exit;
     }
 
@@ -1483,13 +1485,35 @@
 
     font->num_strings = string_index.count;
 
-    /* well, we don't really forget the `disabled' fonts... */
-    font->num_faces = font->name_index.count;
-    if ( face_index >= (FT_Int)font->num_faces )
+    if ( pure_cff )
     {
-      FT_ERROR(( "cff_font_load: incorrect face index = %d\n",
-                 face_index ));
-      error = CFF_Err_Invalid_Argument;
+      /* well, we don't really forget the `disabled' fonts... */
+      subfont_index = face_index;
+
+      if ( subfont_index >= (FT_Int)font->name_index.count )
+      {
+        FT_ERROR(( "cff_font_load:"
+                   " invalid subfont index for pure CFF font (%d)\n",
+                   subfont_index ));
+        error = FT_THROW( Invalid_Argument );
+        goto Exit;
+      }
+
+      font->num_faces = font->name_index.count;
+    }
+    else
+    {
+      subfont_index = 0;
+
+      if ( font->name_index.count > 1 )
+      {
+        FT_ERROR(( "cff_font_load:"
+                   " invalid CFF font with multiple subfonts\n"
+                   "              "
+                   " in SFNT wrapper\n" ));
+        error = FT_THROW( Invalid_File_Format );
+        goto Exit;
+      }
     }
 
     /* in case of a font format check, simply exit now */
@@ -1500,7 +1524,7 @@
     FT_TRACE4(( "parsing top-level\n" ));
     error = cff_subfont_load( &font->top_font,
                               &font->font_dict_index,
-                              face_index,
+                              subfont_index,
                               stream,
                               base_offset,
                               library );
@@ -1576,7 +1600,7 @@
     if ( dict->charstrings_offset == 0 )
     {
       FT_ERROR(( "cff_font_load: no charstrings offset\n" ));
-      error = CFF_Err_Invalid_File_Format;
+      error = FT_THROW( Invalid_File_Format );
       goto Exit;
     }
 
@@ -1615,7 +1639,7 @@
 
     /* get the font name (/CIDFontName for CID-keyed fonts, */
     /* /FontName otherwise)                                 */
-    font->font_name = cff_index_get_name( font, face_index );
+    font->font_name = cff_index_get_name( font, subfont_index );
 
   Exit:
     cff_index_done( &string_index );
@@ -1660,6 +1684,12 @@
     FT_FREE( font->global_subrs );
     FT_FREE( font->strings );
     FT_FREE( font->string_pool );
+
+    if ( font->cf2_instance.finalizer )
+    {
+      font->cf2_instance.finalizer( font->cf2_instance.data );
+      FT_FREE( font->cf2_instance.data );
+    }
   }
 
 
diff --git a/src/cff/cffobjs.c b/src/cff/cffobjs.c
index 6ad0e50..dd750d1 100644
--- a/src/cff/cffobjs.c
+++ b/src/cff/cffobjs.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    OpenType objects manager (body).                                     */
 /*                                                                         */
-/*  Copyright 1996-2012 by                                                 */
+/*  Copyright 1996-2013 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -17,6 +17,7 @@
 
 
 #include <ft2build.h>
+
 #include FT_INTERNAL_DEBUG_H
 #include FT_INTERNAL_CALC_H
 #include FT_INTERNAL_STREAM_H
@@ -24,12 +25,15 @@
 #include FT_TRUETYPE_IDS_H
 #include FT_TRUETYPE_TAGS_H
 #include FT_INTERNAL_SFNT_H
+#include FT_CFF_DRIVER_H
+
 #include "cffobjs.h"
 #include "cffload.h"
 #include "cffcmap.h"
-#include "cfferrs.h"
 #include "cffpic.h"
 
+#include "cfferrs.h"
+
 
   /*************************************************************************/
   /*                                                                       */
@@ -153,7 +157,7 @@
   cff_size_init( FT_Size  cffsize )         /* CFF_Size */
   {
     CFF_Size           size  = (CFF_Size)cffsize;
-    FT_Error           error = CFF_Err_Ok;
+    FT_Error           error = FT_Err_Ok;
     PSH_Globals_Funcs  funcs = cff_size_get_globals_funcs( size );
 
 
@@ -253,7 +257,7 @@
       }
     }
 
-    return CFF_Err_Ok;
+    return FT_Err_Ok;
   }
 
 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
@@ -325,7 +329,7 @@
       }
     }
 
-    return CFF_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
@@ -367,7 +371,7 @@
       }
     }
 
-    return CFF_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
@@ -401,7 +405,7 @@
   remove_subset_prefix( FT_String*  name )
   {
     FT_Int32  idx             = 0;
-    FT_Int32  length          = strlen( name ) + 1;
+    FT_Int32  length          = (FT_Int32)strlen( name ) + 1;
     FT_Bool   continue_search = 1;
 
 
@@ -438,8 +442,8 @@
     FT_Int32  family_name_length, style_name_length;
 
 
-    family_name_length = strlen( family_name );
-    style_name_length  = strlen( style_name );
+    family_name_length = (FT_Int32)strlen( family_name );
+    style_name_length  = (FT_Int32)strlen( style_name );
 
     if ( family_name_length > style_name_length )
     {
@@ -496,7 +500,7 @@
     if ( !sfnt )
     {
       FT_ERROR(( "cff_face_init: cannot access `sfnt' module\n" ));
-      error = CFF_Err_Missing_Module;
+      error = FT_THROW( Missing_Module );
       goto Exit;
     }
 
@@ -518,21 +522,13 @@
       if ( face->format_tag != TTAG_OTTO )  /* `OTTO'; OpenType/CFF font */
       {
         FT_TRACE2(( "  not an OpenType/CFF font\n" ));
-        error = CFF_Err_Unknown_File_Format;
+        error = FT_THROW( Unknown_File_Format );
         goto Exit;
       }
 
       /* if we are performing a simple font format check, exit immediately */
       if ( face_index < 0 )
-        return CFF_Err_Ok;
-
-      /* UNDOCUMENTED!  A CFF in an SFNT can have only a single font. */
-      if ( face_index > 0 )
-      {
-        FT_ERROR(( "cff_face_init: invalid face index\n" ));
-        error = CFF_Err_Invalid_Argument;
-        goto Exit;
-      }
+        return FT_Err_Ok;
 
       sfnt_format = 1;
 
@@ -544,7 +540,8 @@
         pure_cff = 0;
 
         /* load font directory */
-        error = sfnt->load_face( stream, face, 0, num_params, params );
+        error = sfnt->load_face( stream, face, face_index,
+                                 num_params, params );
         if ( error )
           goto Exit;
       }
@@ -554,10 +551,6 @@
         error = sfnt->load_cmap( face, stream );
         if ( error )
           goto Exit;
-
-        /* XXX: we don't load the GPOS table, as OpenType Layout     */
-        /* support will be added later to a layout library on top of */
-        /* FreeType 2                                                */
       }
 
       /* now load the CFF part of the file */
@@ -570,7 +563,7 @@
       /* rewind to start of file; we are going to load a pure-CFF font */
       if ( FT_STREAM_SEEK( 0 ) )
         goto Exit;
-      error = CFF_Err_Ok;
+      error = FT_Err_Ok;
     }
 
     /* now load and parse the CFF table in the file */
@@ -611,7 +604,7 @@
                    " cannot open CFF & CEF fonts\n"
                    "              "
                    " without the `PSNames' module\n" ));
-        error = CFF_Err_Missing_Module;
+        error = FT_THROW( Missing_Module );
         goto Exit;
       }
 
@@ -968,9 +961,10 @@
 
         nn = (FT_UInt)cffface->num_charmaps;
 
-        error = FT_CMap_New( &FT_CFF_CMAP_UNICODE_CLASS_REC_GET, NULL,
+        error = FT_CMap_New( &CFF_CMAP_UNICODE_CLASS_REC_GET, NULL,
                              &cmaprec, NULL );
-        if ( error && FT_Err_No_Unicode_Glyph_Name != error )
+        if ( error                                      &&
+             FT_ERR_NEQ( error, No_Unicode_Glyph_Name ) )
           goto Exit;
         error = FT_Err_Ok;
 
@@ -1000,19 +994,19 @@
           {
             cmaprec.encoding_id = TT_ADOBE_ID_STANDARD;
             cmaprec.encoding    = FT_ENCODING_ADOBE_STANDARD;
-            clazz               = &FT_CFF_CMAP_ENCODING_CLASS_REC_GET;
+            clazz               = &CFF_CMAP_ENCODING_CLASS_REC_GET;
           }
           else if ( encoding->offset == 1 )
           {
             cmaprec.encoding_id = TT_ADOBE_ID_EXPERT;
             cmaprec.encoding    = FT_ENCODING_ADOBE_EXPERT;
-            clazz               = &FT_CFF_CMAP_ENCODING_CLASS_REC_GET;
+            clazz               = &CFF_CMAP_ENCODING_CLASS_REC_GET;
           }
           else
           {
             cmaprec.encoding_id = TT_ADOBE_ID_CUSTOM;
             cmaprec.encoding    = FT_ENCODING_ADOBE_CUSTOM;
-            clazz               = &FT_CFF_CMAP_ENCODING_CLASS_REC_GET;
+            clazz               = &CFF_CMAP_ENCODING_CLASS_REC_GET;
           }
 
           error = FT_CMap_New( clazz, NULL, &cmaprec, NULL );
@@ -1056,16 +1050,25 @@
 
 
   FT_LOCAL_DEF( FT_Error )
-  cff_driver_init( FT_Module  module )
+  cff_driver_init( FT_Module  module )        /* CFF_Driver */
   {
-    FT_UNUSED( module );
+    CFF_Driver  driver = (CFF_Driver)module;
 
-    return CFF_Err_Ok;
+
+    /* set default property values */
+#ifdef CFF_CONFIG_OPTION_OLD_ENGINE
+    driver->hinting_engine    = FT_CFF_HINTING_FREETYPE;
+#else
+    driver->hinting_engine    = FT_CFF_HINTING_ADOBE;
+#endif
+    driver->no_stem_darkening = FALSE;
+
+    return FT_Err_Ok;
   }
 
 
   FT_LOCAL_DEF( void )
-  cff_driver_done( FT_Module  module )
+  cff_driver_done( FT_Module  module )        /* CFF_Driver */
   {
     FT_UNUSED( module );
   }
diff --git a/src/cff/cffobjs.h b/src/cff/cffobjs.h
index 3c81cee..b375c20 100644
--- a/src/cff/cffobjs.h
+++ b/src/cff/cffobjs.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    OpenType objects manager (specification).                            */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003, 2004, 2006, 2007, 2008 by             */
+/*  Copyright 1996-2004, 2006-2008, 2013 by                                */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -112,12 +112,14 @@
 
   /***********************************************************************/
   /*                                                                     */
-  /* TrueType driver class.                                              */
+  /* CFF driver class.                                                   */
   /*                                                                     */
   typedef struct  CFF_DriverRec_
   {
     FT_DriverRec  root;
-    void*         extension_component;
+
+    FT_UInt  hinting_engine;
+    FT_Bool  no_stem_darkening;
 
   } CFF_DriverRec;
 
@@ -167,10 +169,10 @@
   /* Driver functions                                                      */
   /*                                                                       */
   FT_LOCAL( FT_Error )
-  cff_driver_init( FT_Module  module );
+  cff_driver_init( FT_Module  module );         /* CFF_Driver */
 
   FT_LOCAL( void )
-  cff_driver_done( FT_Module  module );
+  cff_driver_done( FT_Module  module );         /* CFF_Driver */
 
 
 FT_END_HEADER
diff --git a/src/cff/cffparse.c b/src/cff/cffparse.c
index 61fa87c..9622212 100644
--- a/src/cff/cffparse.c
+++ b/src/cff/cffparse.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    CFF token stream parser (body)                                       */
 /*                                                                         */
-/*  Copyright 1996-2004, 2007-2011 by                                      */
+/*  Copyright 1996-2004, 2007-2013 by                                      */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -65,7 +65,7 @@
       if ( p + 2 > limit )
         goto Bad;
 
-      val = (FT_Short)( ( (FT_Int)p[0] << 8 ) | p[1] );
+      val = (FT_Short)( ( (FT_UShort)p[0] << 8 ) | p[1] );
       p  += 2;
     }
     else if ( v == 29 )
@@ -73,10 +73,10 @@
       if ( p + 4 > limit )
         goto Bad;
 
-      val = ( (FT_Long)p[0] << 24 ) |
-            ( (FT_Long)p[1] << 16 ) |
-            ( (FT_Long)p[2] <<  8 ) |
-                       p[3];
+      val = (FT_Long)( ( (FT_ULong)p[0] << 24 ) |
+                       ( (FT_ULong)p[1] << 16 ) |
+                       ( (FT_ULong)p[2] <<  8 ) |
+                         (FT_ULong)p[3]         );
       p += 4;
     }
     else if ( v < 247 )
@@ -105,6 +105,7 @@
 
   Bad:
     val = 0;
+    FT_TRACE4(( "!!!END OF DATA:!!!" ));
     goto Exit;
   }
 
@@ -136,7 +137,7 @@
     FT_UInt   phase;
 
     FT_Long   result, number, exponent;
-    FT_Int    sign = 0, exponent_sign = 0;
+    FT_Int    sign = 0, exponent_sign = 0, have_overflow = 0;
     FT_Long   exponent_add, integer_length, fraction_length;
 
 
@@ -165,7 +166,7 @@
 
         /* Make sure we don't read past the end. */
         if ( p >= limit )
-          goto Exit;
+          goto Bad;
       }
 
       /* Get the nibble. */
@@ -202,7 +203,7 @@
 
           /* Make sure we don't read past the end. */
           if ( p >= limit )
-            goto Exit;
+            goto Bad;
         }
 
         /* Get the nibble. */
@@ -241,7 +242,7 @@
 
           /* Make sure we don't read past the end. */
           if ( p >= limit )
-            goto Exit;
+            goto Bad;
         }
 
         /* Get the nibble. */
@@ -250,17 +251,28 @@
         if ( nib >= 10 )
           break;
 
-        exponent = exponent * 10 + nib;
-
         /* Arbitrarily limit exponent. */
         if ( exponent > 1000 )
-          goto Exit;
+          have_overflow = 1;
+        else
+          exponent = exponent * 10 + nib;
       }
 
       if ( exponent_sign )
         exponent = -exponent;
     }
 
+    if ( !number )
+      goto Exit;
+
+    if ( have_overflow )
+    {
+      if ( exponent_sign )
+        goto Underflow;
+      else
+        goto Overflow;
+    }
+
     /* We don't check `power_ten' and `exponent_add'. */
     exponent += power_ten + exponent_add;
 
@@ -286,20 +298,25 @@
 
             /* Make `scaling' as small as possible. */
             new_fraction_length = FT_MIN( exponent, 5 );
-            exponent           -= new_fraction_length;
             shift               = new_fraction_length - fraction_length;
 
-            number *= power_tens[shift];
-            if ( number > 0x7FFFL )
+            if ( shift > 0 )
             {
-              number   /= 10;
-              exponent += 1;
+              exponent -= new_fraction_length;
+              number   *= power_tens[shift];
+              if ( number > 0x7FFFL )
+              {
+                number   /= 10;
+                exponent += 1;
+              }
             }
+            else
+              exponent -= fraction_length;
           }
           else
             exponent -= fraction_length;
 
-          result   = number << 16;
+          result   = (FT_Long)( (FT_ULong)number << 16 );
           *scaling = exponent;
         }
       }
@@ -322,9 +339,10 @@
       integer_length  += exponent;
       fraction_length -= exponent;
 
-      /* Check for overflow and underflow. */
-      if ( FT_ABS( integer_length ) > 5 )
-        goto Exit;
+      if ( integer_length > 5 )
+        goto Overflow;
+      if ( integer_length < -5 )
+        goto Underflow;
 
       /* Remove non-significant digits. */
       if ( integer_length < 0 )
@@ -353,17 +371,32 @@
         number *= power_tens[-fraction_length];
 
         if ( number > 0x7FFFL )
-          goto Exit;
+          goto Overflow;
 
-        result = number << 16;
+        result = (FT_Long)( (FT_ULong)number << 16 );
       }
     }
 
+  Exit:
     if ( sign )
       result = -result;
 
-  Exit:
     return result;
+
+  Overflow:
+    result = 0x7FFFFFFFL;
+    FT_TRACE4(( "!!!OVERFLOW:!!!" ));
+    goto Exit;
+
+  Underflow:
+    result = 0;
+    FT_TRACE4(( "!!!UNDERFLOW:!!!" ));
+    goto Exit;
+
+  Bad:
+    result = 0;
+    FT_TRACE4(( "!!!END OF DATA:!!!" ));
+    goto Exit;
   }
 
 
@@ -378,10 +411,44 @@
 
   /* read a floating point number, either integer or real */
   static FT_Fixed
+  do_fixed( FT_Byte**  d,
+            FT_Long    scaling )
+  {
+    if ( **d == 30 )
+      return cff_parse_real( d[0], d[1], scaling, NULL );
+    else
+    {
+      FT_Long  val = cff_parse_integer( d[0], d[1] );
+
+
+      if ( scaling )
+        val *= power_tens[scaling];
+
+      if ( val > 0x7FFF )
+      {
+        val = 0x7FFFFFFFL;
+        goto Overflow;
+      }
+      else if ( val < -0x7FFF )
+      {
+        val = -0x7FFFFFFFL;
+        goto Overflow;
+      }
+
+      return (FT_Long)( (FT_ULong)val << 16 );
+
+    Overflow:
+      FT_TRACE4(( "!!!OVERFLOW:!!!" ));
+      return val;
+    }
+  }
+
+
+  /* read a floating point number, either integer or real */
+  static FT_Fixed
   cff_parse_fixed( FT_Byte**  d )
   {
-    return **d == 30 ? cff_parse_real( d[0], d[1], 0, NULL )
-                     : cff_parse_integer( d[0], d[1] ) << 16;
+    return do_fixed( d, 0 );
   }
 
 
@@ -391,9 +458,7 @@
   cff_parse_fixed_scaled( FT_Byte**  d,
                           FT_Long    scaling )
   {
-    return **d == 30 ? cff_parse_real( d[0], d[1], scaling, NULL )
-                     : ( cff_parse_integer( d[0], d[1] ) *
-                           power_tens[scaling] ) << 16;
+    return do_fixed( d, scaling );
   }
 
 
@@ -436,7 +501,7 @@
       else
       {
         *scaling = 0;
-        return number << 16;
+        return (FT_Long)( (FT_ULong)number << 16 );
       }
     }
   }
@@ -450,7 +515,7 @@
     FT_Vector*       offset = &dict->font_offset;
     FT_ULong*        upm    = &dict->units_per_em;
     FT_Byte**        data   = parser->stack;
-    FT_Error         error  = CFF_Err_Stack_Underflow;
+    FT_Error         error  = FT_ERR( Stack_Underflow );
 
 
     if ( parser->top >= parser->stack + 6 )
@@ -458,7 +523,7 @@
       FT_Long  scaling;
 
 
-      error = CFF_Err_Ok;
+      error = FT_Err_Ok;
 
       dict->has_font_matrix = TRUE;
 
@@ -523,7 +588,7 @@
     FT_Error         error;
 
 
-    error = CFF_Err_Stack_Underflow;
+    error = FT_ERR( Stack_Underflow );
 
     if ( parser->top >= parser->stack + 4 )
     {
@@ -531,7 +596,7 @@
       bbox->yMin = FT_RoundFix( cff_parse_fixed( data++ ) );
       bbox->xMax = FT_RoundFix( cff_parse_fixed( data++ ) );
       bbox->yMax = FT_RoundFix( cff_parse_fixed( data   ) );
-      error = CFF_Err_Ok;
+      error = FT_Err_Ok;
 
       FT_TRACE4(( " [%d %d %d %d]\n",
                   bbox->xMin / 65536,
@@ -552,7 +617,7 @@
     FT_Error         error;
 
 
-    error = CFF_Err_Stack_Underflow;
+    error = FT_ERR( Stack_Underflow );
 
     if ( parser->top >= parser->stack + 2 )
     {
@@ -561,7 +626,7 @@
       FT_TRACE4(( " %lu %lu\n",
                   dict->private_size, dict->private_offset ));
 
-      error = CFF_Err_Ok;
+      error = FT_Err_Ok;
     }
 
     return error;
@@ -576,7 +641,7 @@
     FT_Error         error;
 
 
-    error = CFF_Err_Stack_Underflow;
+    error = FT_ERR( Stack_Underflow );
 
     if ( parser->top >= parser->stack + 3 )
     {
@@ -588,7 +653,7 @@
       if ( dict->cid_supplement < 0 )
         FT_TRACE1(( "cff_parse_cid_ros: negative supplement %d is found\n",
                    dict->cid_supplement ));
-      error = CFF_Err_Ok;
+      error = FT_Err_Ok;
 
       FT_TRACE4(( " %d %d %d\n",
                   dict->cid_registry,
@@ -730,7 +795,7 @@
   FT_Create_Class_cff_field_handlers( FT_Library           library,
                                       CFF_Field_Handler**  output_class )
   {
-    CFF_Field_Handler*  clazz;
+    CFF_Field_Handler*  clazz  = NULL;
     FT_Error            error;
     FT_Memory           memory = library->memory;
 
@@ -857,7 +922,7 @@
 
     *output_class = clazz;
 
-    return CFF_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
@@ -870,7 +935,7 @@
                   FT_Byte*    limit )
   {
     FT_Byte*    p       = start;
-    FT_Error    error   = CFF_Err_Ok;
+    FT_Error    error   = FT_Err_Ok;
     FT_Library  library = parser->library;
     FT_UNUSED( library );
 
@@ -944,7 +1009,7 @@
         }
         code = code | parser->object_code;
 
-        for ( field = FT_CFF_FIELD_HANDLERS_GET; field->kind; field++ )
+        for ( field = CFF_FIELD_HANDLERS_GET; field->kind; field++ )
         {
           if ( field->code == (FT_Int)code )
           {
@@ -1096,15 +1161,15 @@
     return error;
 
   Stack_Overflow:
-    error = CFF_Err_Invalid_Argument;
+    error = FT_THROW( Invalid_Argument );
     goto Exit;
 
   Stack_Underflow:
-    error = CFF_Err_Invalid_Argument;
+    error = FT_THROW( Invalid_Argument );
     goto Exit;
 
   Syntax_Error:
-    error = CFF_Err_Invalid_Argument;
+    error = FT_THROW( Invalid_Argument );
     goto Exit;
   }
 
diff --git a/src/cff/cffpic.c b/src/cff/cffpic.c
index 1c19d58..f22e4f0 100644
--- a/src/cff/cffpic.c
+++ b/src/cff/cffpic.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType position independent code services for cff module.      */
 /*                                                                         */
-/*  Copyright 2009, 2010 by                                                */
+/*  Copyright 2009, 2010, 2012, 2013 by                                    */
 /*  Oran Agra and Mickey Gabel.                                            */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -23,65 +23,51 @@
 #include "cffpic.h"
 #include "cfferrs.h"
 
+
 #ifdef FT_CONFIG_OPTION_PIC
 
   /* forward declaration of PIC init functions from cffdrivr.c */
   FT_Error
-  FT_Create_Class_cff_services(
-    FT_Library           library,
-    FT_ServiceDescRec**  output_class );
-
+  FT_Create_Class_cff_services( FT_Library           library,
+                                FT_ServiceDescRec**  output_class );
   void
-  FT_Destroy_Class_cff_services(
-    FT_Library          library,
-    FT_ServiceDescRec*  clazz );
-
+  FT_Destroy_Class_cff_services( FT_Library          library,
+                                 FT_ServiceDescRec*  clazz );
   void
-  FT_Init_Class_cff_service_ps_info(
-    FT_Library             library,
-    FT_Service_PsInfoRec*  clazz );
-
+  FT_Init_Class_cff_service_ps_info( FT_Library             library,
+                                     FT_Service_PsInfoRec*  clazz );
   void
-  FT_Init_Class_cff_service_glyph_dict(
-    FT_Library                library,
-    FT_Service_GlyphDictRec*  clazz );
-
+  FT_Init_Class_cff_service_glyph_dict( FT_Library                library,
+                                        FT_Service_GlyphDictRec*  clazz );
   void
-  FT_Init_Class_cff_service_ps_name(
-    FT_Library                 library,
-    FT_Service_PsFontNameRec*  clazz );
-
+  FT_Init_Class_cff_service_ps_name( FT_Library                 library,
+                                     FT_Service_PsFontNameRec*  clazz );
   void
-  FT_Init_Class_cff_service_get_cmap_info(
-    FT_Library              library,
-    FT_Service_TTCMapsRec*  clazz );
-
+  FT_Init_Class_cff_service_get_cmap_info( FT_Library              library,
+                                           FT_Service_TTCMapsRec*  clazz );
   void
-  FT_Init_Class_cff_service_cid_info(
-    FT_Library          library,
-    FT_Service_CIDRec*  clazz );
+  FT_Init_Class_cff_service_cid_info( FT_Library          library,
+                                      FT_Service_CIDRec*  clazz );
 
   /* forward declaration of PIC init functions from cffparse.c */
   FT_Error
-  FT_Create_Class_cff_field_handlers(
-    FT_Library           library,
-    CFF_Field_Handler**  output_class );
-
+  FT_Create_Class_cff_field_handlers( FT_Library           library,
+                                      CFF_Field_Handler**  output_class );
   void
-  FT_Destroy_Class_cff_field_handlers(
-    FT_Library          library,
-    CFF_Field_Handler*  clazz );
+  FT_Destroy_Class_cff_field_handlers( FT_Library          library,
+                                       CFF_Field_Handler*  clazz );
+
 
   void
   cff_driver_class_pic_free( FT_Library  library )
   {
     FT_PIC_Container*  pic_container = &library->pic_container;
-    FT_Memory  memory = library->memory;
+    FT_Memory          memory        = library->memory;
 
 
     if ( pic_container->cff )
     {
-      CffModulePIC*  container = ( CffModulePIC* )pic_container->cff;
+      CffModulePIC*  container = (CffModulePIC*)pic_container->cff;
 
 
       if ( container->cff_services )
@@ -102,8 +88,8 @@
   cff_driver_class_pic_init( FT_Library  library )
   {
     FT_PIC_Container*  pic_container = &library->pic_container;
-    FT_Error           error         = CFF_Err_Ok;
-    CffModulePIC*      container;
+    FT_Error           error         = FT_Err_Ok;
+    CffModulePIC*      container     = NULL;
     FT_Memory          memory        = library->memory;
 
 
@@ -113,15 +99,18 @@
     FT_MEM_SET( container, 0, sizeof ( *container ) );
     pic_container->cff = container;
 
-    /* initialize pointer table - this is how the module usually expects this data */
+    /* initialize pointer table -                       */
+    /* this is how the module usually expects this data */
     error = FT_Create_Class_cff_services( library,
                                           &container->cff_services );
     if ( error )
       goto Exit;
+
     error = FT_Create_Class_cff_field_handlers(
               library, &container->cff_field_handlers );
     if ( error )
       goto Exit;
+
     FT_Init_Class_cff_service_ps_info(
       library, &container->cff_service_ps_info );
     FT_Init_Class_cff_service_glyph_dict(
@@ -136,7 +125,8 @@
       library, &container->cff_cmap_encoding_class_rec );
     FT_Init_Class_cff_cmap_unicode_class_rec(
       library, &container->cff_cmap_unicode_class_rec );
-Exit:
+
+  Exit:
     if ( error )
       cff_driver_class_pic_free( library );
     return error;
diff --git a/src/cff/cffpic.h b/src/cff/cffpic.h
index 342edd8..50bab4c 100644
--- a/src/cff/cffpic.h
+++ b/src/cff/cffpic.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType position independent code services for cff module.      */
 /*                                                                         */
-/*  Copyright 2009 by                                                      */
+/*  Copyright 2009, 2012, 2013 by                                          */
 /*  Oran Agra and Mickey Gabel.                                            */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -24,16 +24,19 @@
 
 #include FT_INTERNAL_PIC_H
 
+
 #ifndef FT_CONFIG_OPTION_PIC
-#define FT_CFF_SERVICE_PS_INFO_GET         cff_service_ps_info
-#define FT_CFF_SERVICE_GLYPH_DICT_GET      cff_service_glyph_dict
-#define FT_CFF_SERVICE_PS_NAME_GET         cff_service_ps_name
-#define FT_CFF_SERVICE_GET_CMAP_INFO_GET   cff_service_get_cmap_info
-#define FT_CFF_SERVICE_CID_INFO_GET        cff_service_cid_info
-#define FT_CFF_SERVICES_GET                cff_services
-#define FT_CFF_CMAP_ENCODING_CLASS_REC_GET cff_cmap_encoding_class_rec
-#define FT_CFF_CMAP_UNICODE_CLASS_REC_GET  cff_cmap_unicode_class_rec
-#define FT_CFF_FIELD_HANDLERS_GET          cff_field_handlers
+
+#define CFF_SERVICE_PS_INFO_GET          cff_service_ps_info
+#define CFF_SERVICE_GLYPH_DICT_GET       cff_service_glyph_dict
+#define CFF_SERVICE_PS_NAME_GET          cff_service_ps_name
+#define CFF_SERVICE_GET_CMAP_INFO_GET    cff_service_get_cmap_info
+#define CFF_SERVICE_CID_INFO_GET         cff_service_cid_info
+#define CFF_SERVICE_PROPERTIES_GET       cff_service_properties
+#define CFF_SERVICES_GET                 cff_services
+#define CFF_CMAP_ENCODING_CLASS_REC_GET  cff_cmap_encoding_class_rec
+#define CFF_CMAP_UNICODE_CLASS_REC_GET   cff_cmap_unicode_class_rec
+#define CFF_FIELD_HANDLERS_GET           cff_field_handlers
 
 #else /* FT_CONFIG_OPTION_PIC */
 
@@ -43,30 +46,48 @@
 #include FT_SERVICE_POSTSCRIPT_NAME_H
 #include FT_SERVICE_TT_CMAP_H
 #include FT_SERVICE_CID_H
+#include FT_SERVICE_PROPERTIES_H
 
-  typedef struct CffModulePIC_
+
+  typedef struct  CffModulePIC_
   {
-    FT_ServiceDescRec* cff_services;
-    CFF_Field_Handler* cff_field_handlers;
-    FT_Service_PsInfoRec cff_service_ps_info;
-    FT_Service_GlyphDictRec cff_service_glyph_dict;
-    FT_Service_PsFontNameRec cff_service_ps_name;
-    FT_Service_TTCMapsRec  cff_service_get_cmap_info;
-    FT_Service_CIDRec  cff_service_cid_info;
-    FT_CMap_ClassRec cff_cmap_encoding_class_rec;
-    FT_CMap_ClassRec cff_cmap_unicode_class_rec;
+    FT_ServiceDescRec*        cff_services;
+    CFF_Field_Handler*        cff_field_handlers;
+    FT_Service_PsInfoRec      cff_service_ps_info;
+    FT_Service_GlyphDictRec   cff_service_glyph_dict;
+    FT_Service_PsFontNameRec  cff_service_ps_name;
+    FT_Service_TTCMapsRec     cff_service_get_cmap_info;
+    FT_Service_CIDRec         cff_service_cid_info;
+    FT_Service_PropertiesRec  cff_service_properties;
+    FT_CMap_ClassRec          cff_cmap_encoding_class_rec;
+    FT_CMap_ClassRec          cff_cmap_unicode_class_rec;
+
   } CffModulePIC;
 
-#define GET_PIC(lib)                       ((CffModulePIC*)((lib)->pic_container.cff))
-#define FT_CFF_SERVICE_PS_INFO_GET         (GET_PIC(library)->cff_service_ps_info)
-#define FT_CFF_SERVICE_GLYPH_DICT_GET      (GET_PIC(library)->cff_service_glyph_dict)
-#define FT_CFF_SERVICE_PS_NAME_GET         (GET_PIC(library)->cff_service_ps_name)
-#define FT_CFF_SERVICE_GET_CMAP_INFO_GET   (GET_PIC(library)->cff_service_get_cmap_info)
-#define FT_CFF_SERVICE_CID_INFO_GET        (GET_PIC(library)->cff_service_cid_info)
-#define FT_CFF_SERVICES_GET                (GET_PIC(library)->cff_services)
-#define FT_CFF_CMAP_ENCODING_CLASS_REC_GET (GET_PIC(library)->cff_cmap_encoding_class_rec)
-#define FT_CFF_CMAP_UNICODE_CLASS_REC_GET  (GET_PIC(library)->cff_cmap_unicode_class_rec)
-#define FT_CFF_FIELD_HANDLERS_GET          (GET_PIC(library)->cff_field_handlers)
+
+#define GET_PIC( lib )                                    \
+          ( (CffModulePIC*)( (lib)->pic_container.cff ) )
+
+#define CFF_SERVICE_PS_INFO_GET                       \
+          ( GET_PIC( library )->cff_service_ps_info )
+#define CFF_SERVICE_GLYPH_DICT_GET                       \
+          ( GET_PIC( library )->cff_service_glyph_dict )
+#define CFF_SERVICE_PS_NAME_GET                       \
+          ( GET_PIC( library )->cff_service_ps_name )
+#define CFF_SERVICE_GET_CMAP_INFO_GET                       \
+          ( GET_PIC( library )->cff_service_get_cmap_info )
+#define CFF_SERVICE_CID_INFO_GET                       \
+          ( GET_PIC( library )->cff_service_cid_info )
+#define CFF_SERVICE_PROPERTIES_GET                       \
+          ( GET_PIC( library )->cff_service_properties )
+#define CFF_SERVICES_GET                       \
+          ( GET_PIC( library )->cff_services )
+#define CFF_CMAP_ENCODING_CLASS_REC_GET                       \
+          ( GET_PIC( library )->cff_cmap_encoding_class_rec )
+#define CFF_CMAP_UNICODE_CLASS_REC_GET                       \
+          ( GET_PIC( library )->cff_cmap_unicode_class_rec )
+#define CFF_FIELD_HANDLERS_GET                       \
+          ( GET_PIC( library )->cff_field_handlers )
 
   /* see cffpic.c for the implementation */
   void
diff --git a/src/cff/cfftypes.h b/src/cff/cfftypes.h
index 7c99036..8727446 100644
--- a/src/cff/cfftypes.h
+++ b/src/cff/cfftypes.h
@@ -5,7 +5,7 @@
 /*    Basic OpenType/CFF type definitions and interface (specification     */
 /*    only).                                                               */
 /*                                                                         */
-/*  Copyright 1996-2003, 2006-2008, 2010-2011 by                           */
+/*  Copyright 1996-2003, 2006-2008, 2010-2011, 2013 by                     */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -270,6 +270,9 @@
     FT_String*       registry;
     FT_String*       ordering;
 
+    /* since version 2.4.12 */
+    FT_Generic       cf2_instance;
+
   } CFF_FontRec, *CFF_Font;
 
 
diff --git a/src/pfr/pfrload.c b/src/pfr/pfrload.c
new file mode 100644
index 0000000..c19fceb
--- /dev/null
+++ b/src/pfr/pfrload.c
@@ -0,0 +1,941 @@
+/***************************************************************************/
+/*                                                                         */
+/*  pfrload.c                                                              */
+/*                                                                         */
+/*    FreeType PFR loader (body).                                          */
+/*                                                                         */
+/*  Copyright 2002-2005, 2007, 2009, 2010, 2013 by                         */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include "pfrload.h"
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_STREAM_H
+
+#include "pfrerror.h"
+
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_pfr
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                          EXTRA ITEMS                          *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  FT_LOCAL_DEF( FT_Error )
+  pfr_extra_items_skip( FT_Byte*  *pp,
+                        FT_Byte*   limit )
+  {
+    return pfr_extra_items_parse( pp, limit, NULL, NULL );
+  }
+
+
+  FT_LOCAL_DEF( FT_Error )
+  pfr_extra_items_parse( FT_Byte*       *pp,
+                         FT_Byte*        limit,
+                         PFR_ExtraItem   item_list,
+                         FT_Pointer      item_data )
+  {
+    FT_Error  error = FT_Err_Ok;
+    FT_Byte*  p     = *pp;
+    FT_UInt   num_items, item_type, item_size;
+
+
+    PFR_CHECK( 1 );
+    num_items = PFR_NEXT_BYTE( p );
+
+    for ( ; num_items > 0; num_items-- )
+    {
+      PFR_CHECK( 2 );
+      item_size = PFR_NEXT_BYTE( p );
+      item_type = PFR_NEXT_BYTE( p );
+
+      PFR_CHECK( item_size );
+
+      if ( item_list )
+      {
+        PFR_ExtraItem  extra = item_list;
+
+
+        for ( extra = item_list; extra->parser != NULL; extra++ )
+        {
+          if ( extra->type == item_type )
+          {
+            error = extra->parser( p, p + item_size, item_data );
+            if ( error ) goto Exit;
+
+            break;
+          }
+        }
+      }
+
+      p += item_size;
+    }
+
+  Exit:
+    *pp = p;
+    return error;
+
+  Too_Short:
+    FT_ERROR(( "pfr_extra_items_parse: invalid extra items table\n" ));
+    error = FT_THROW( Invalid_Table );
+    goto Exit;
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /*****                                                               *****/
+  /*****                          PFR HEADER                           *****/
+  /*****                                                               *****/
+  /*************************************************************************/
+  /*************************************************************************/
+
+   static const FT_Frame_Field  pfr_header_fields[] =
+   {
+#undef  FT_STRUCTURE
+#define FT_STRUCTURE  PFR_HeaderRec
+
+     FT_FRAME_START( 58 ),
+       FT_FRAME_ULONG ( signature ),
+       FT_FRAME_USHORT( version ),
+       FT_FRAME_USHORT( signature2 ),
+       FT_FRAME_USHORT( header_size ),
+
+       FT_FRAME_USHORT( log_dir_size ),
+       FT_FRAME_USHORT( log_dir_offset ),
+
+       FT_FRAME_USHORT( log_font_max_size ),
+       FT_FRAME_UOFF3 ( log_font_section_size ),
+       FT_FRAME_UOFF3 ( log_font_section_offset ),
+
+       FT_FRAME_USHORT( phy_font_max_size ),
+       FT_FRAME_UOFF3 ( phy_font_section_size ),
+       FT_FRAME_UOFF3 ( phy_font_section_offset ),
+
+       FT_FRAME_USHORT( gps_max_size ),
+       FT_FRAME_UOFF3 ( gps_section_size ),
+       FT_FRAME_UOFF3 ( gps_section_offset ),
+
+       FT_FRAME_BYTE  ( max_blue_values ),
+       FT_FRAME_BYTE  ( max_x_orus ),
+       FT_FRAME_BYTE  ( max_y_orus ),
+
+       FT_FRAME_BYTE  ( phy_font_max_size_high ),
+       FT_FRAME_BYTE  ( color_flags ),
+
+       FT_FRAME_UOFF3 ( bct_max_size ),
+       FT_FRAME_UOFF3 ( bct_set_max_size ),
+       FT_FRAME_UOFF3 ( phy_bct_set_max_size ),
+
+       FT_FRAME_USHORT( num_phy_fonts ),
+       FT_FRAME_BYTE  ( max_vert_stem_snap ),
+       FT_FRAME_BYTE  ( max_horz_stem_snap ),
+       FT_FRAME_USHORT( max_chars ),
+     FT_FRAME_END
+   };
+
+
+  FT_LOCAL_DEF( FT_Error )
+  pfr_header_load( PFR_Header  header,
+                   FT_Stream   stream )
+  {
+    FT_Error  error;
+
+
+    /* read header directly */
+    if ( !FT_STREAM_SEEK( 0 )                                &&
+         !FT_STREAM_READ_FIELDS( pfr_header_fields, header ) )
+    {
+      /* make a few adjustments to the header */
+      header->phy_font_max_size +=
+        (FT_UInt32)header->phy_font_max_size_high << 16;
+    }
+
+    return error;
+  }
+
+
+  FT_LOCAL_DEF( FT_Bool )
+  pfr_header_check( PFR_Header  header )
+  {
+    FT_Bool  result = 1;
+
+
+    /* check signature and header size */
+    if ( header->signature  != 0x50465230L ||   /* "PFR0" */
+         header->version     > 4           ||
+         header->header_size < 58          ||
+         header->signature2 != 0x0d0a      )    /* CR/LF  */
+    {
+      result = 0;
+    }
+    return  result;
+  }
+
+
+  /***********************************************************************/
+  /***********************************************************************/
+  /*****                                                             *****/
+  /*****                    PFR LOGICAL FONTS                        *****/
+  /*****                                                             *****/
+  /***********************************************************************/
+  /***********************************************************************/
+
+
+  FT_LOCAL_DEF( FT_Error )
+  pfr_log_font_count( FT_Stream  stream,
+                      FT_UInt32  section_offset,
+                      FT_UInt   *acount )
+  {
+    FT_Error  error;
+    FT_UInt   count;
+    FT_UInt   result = 0;
+
+
+    if ( FT_STREAM_SEEK( section_offset ) || FT_READ_USHORT( count ) )
+      goto Exit;
+
+    result = count;
+
+  Exit:
+    *acount = result;
+    return error;
+  }
+
+
+  FT_LOCAL_DEF( FT_Error )
+  pfr_log_font_load( PFR_LogFont  log_font,
+                     FT_Stream    stream,
+                     FT_UInt      idx,
+                     FT_UInt32    section_offset,
+                     FT_Bool      size_increment )
+  {
+    FT_UInt    num_log_fonts;
+    FT_UInt    flags;
+    FT_UInt32  offset;
+    FT_UInt32  size;
+    FT_Error   error;
+
+
+    if ( FT_STREAM_SEEK( section_offset ) ||
+         FT_READ_USHORT( num_log_fonts )  )
+      goto Exit;
+
+    if ( idx >= num_log_fonts )
+      return FT_THROW( Invalid_Argument );
+
+    if ( FT_STREAM_SKIP( idx * 5 ) ||
+         FT_READ_USHORT( size )    ||
+         FT_READ_UOFF3 ( offset )  )
+      goto Exit;
+
+    /* save logical font size and offset */
+    log_font->size   = size;
+    log_font->offset = offset;
+
+    /* now, check the rest of the table before loading it */
+    {
+      FT_Byte*  p;
+      FT_Byte*  limit;
+      FT_UInt   local;
+
+
+      if ( FT_STREAM_SEEK( offset ) || FT_FRAME_ENTER( size ) )
+        goto Exit;
+
+      p     = stream->cursor;
+      limit = p + size;
+
+      PFR_CHECK(13);
+
+      log_font->matrix[0] = PFR_NEXT_LONG( p );
+      log_font->matrix[1] = PFR_NEXT_LONG( p );
+      log_font->matrix[2] = PFR_NEXT_LONG( p );
+      log_font->matrix[3] = PFR_NEXT_LONG( p );
+
+      flags = PFR_NEXT_BYTE( p );
+
+      local = 0;
+      if ( flags & PFR_LOG_STROKE )
+      {
+        local++;
+        if ( flags & PFR_LOG_2BYTE_STROKE )
+          local++;
+
+        if ( (flags & PFR_LINE_JOIN_MASK) == PFR_LINE_JOIN_MITER )
+          local += 3;
+      }
+      if ( flags & PFR_LOG_BOLD )
+      {
+        local++;
+        if ( flags & PFR_LOG_2BYTE_BOLD )
+          local++;
+      }
+
+      PFR_CHECK( local );
+
+      if ( flags & PFR_LOG_STROKE )
+      {
+        log_font->stroke_thickness = ( flags & PFR_LOG_2BYTE_STROKE )
+                                     ? PFR_NEXT_SHORT( p )
+                                     : PFR_NEXT_BYTE( p );
+
+        if ( ( flags & PFR_LINE_JOIN_MASK ) == PFR_LINE_JOIN_MITER )
+          log_font->miter_limit = PFR_NEXT_LONG( p );
+      }
+
+      if ( flags & PFR_LOG_BOLD )
+      {
+        log_font->bold_thickness = ( flags & PFR_LOG_2BYTE_BOLD )
+                                   ? PFR_NEXT_SHORT( p )
+                                   : PFR_NEXT_BYTE( p );
+      }
+
+      if ( flags & PFR_LOG_EXTRA_ITEMS )
+      {
+        error = pfr_extra_items_skip( &p, limit );
+        if (error) goto Fail;
+      }
+
+      PFR_CHECK(5);
+      log_font->phys_size   = PFR_NEXT_USHORT( p );
+      log_font->phys_offset = PFR_NEXT_ULONG( p );
+      if ( size_increment )
+      {
+        PFR_CHECK( 1 );
+        log_font->phys_size += (FT_UInt32)PFR_NEXT_BYTE( p ) << 16;
+      }
+    }
+
+  Fail:
+    FT_FRAME_EXIT();
+
+  Exit:
+    return error;
+
+  Too_Short:
+    FT_ERROR(( "pfr_log_font_load: invalid logical font table\n" ));
+    error = FT_THROW( Invalid_Table );
+    goto Fail;
+  }
+
+
+  /***********************************************************************/
+  /***********************************************************************/
+  /*****                                                             *****/
+  /*****                    PFR PHYSICAL FONTS                       *****/
+  /*****                                                             *****/
+  /***********************************************************************/
+  /***********************************************************************/
+
+
+  /* load bitmap strikes lists */
+  FT_CALLBACK_DEF( FT_Error )
+  pfr_extra_item_load_bitmap_info( FT_Byte*     p,
+                                   FT_Byte*     limit,
+                                   PFR_PhyFont  phy_font )
+  {
+    FT_Memory   memory = phy_font->memory;
+    PFR_Strike  strike;
+    FT_UInt     flags0;
+    FT_UInt     n, count, size1;
+    FT_Error    error = FT_Err_Ok;
+
+
+    PFR_CHECK( 5 );
+
+    p += 3;  /* skip bctSize */
+    flags0 = PFR_NEXT_BYTE( p );
+    count  = PFR_NEXT_BYTE( p );
+
+    /* re-allocate when needed */
+    if ( phy_font->num_strikes + count > phy_font->max_strikes )
+    {
+      FT_UInt  new_max = FT_PAD_CEIL( phy_font->num_strikes + count, 4 );
+
+
+      if ( FT_RENEW_ARRAY( phy_font->strikes,
+                           phy_font->num_strikes,
+                           new_max ) )
+        goto Exit;
+
+      phy_font->max_strikes = new_max;
+    }
+
+    size1 = 1 + 1 + 1 + 2 + 2 + 1;
+    if ( flags0 & PFR_STRIKE_2BYTE_XPPM )
+      size1++;
+
+    if ( flags0 & PFR_STRIKE_2BYTE_YPPM )
+      size1++;
+
+    if ( flags0 & PFR_STRIKE_3BYTE_SIZE )
+      size1++;
+
+    if ( flags0 & PFR_STRIKE_3BYTE_OFFSET )
+      size1++;
+
+    if ( flags0 & PFR_STRIKE_2BYTE_COUNT )
+      size1++;
+
+    strike = phy_font->strikes + phy_font->num_strikes;
+
+    PFR_CHECK( count * size1 );
+
+    for ( n = 0; n < count; n++, strike++ )
+    {
+      strike->x_ppm       = ( flags0 & PFR_STRIKE_2BYTE_XPPM )
+                            ? PFR_NEXT_USHORT( p )
+                            : PFR_NEXT_BYTE( p );
+
+      strike->y_ppm       = ( flags0 & PFR_STRIKE_2BYTE_YPPM )
+                            ? PFR_NEXT_USHORT( p )
+                            : PFR_NEXT_BYTE( p );
+
+      strike->flags       = PFR_NEXT_BYTE( p );
+
+      strike->bct_size    = ( flags0 & PFR_STRIKE_3BYTE_SIZE )
+                            ? PFR_NEXT_ULONG( p )
+                            : PFR_NEXT_USHORT( p );
+
+      strike->bct_offset  = ( flags0 & PFR_STRIKE_3BYTE_OFFSET )
+                            ? PFR_NEXT_ULONG( p )
+                            : PFR_NEXT_USHORT( p );
+
+      strike->num_bitmaps = ( flags0 & PFR_STRIKE_2BYTE_COUNT )
+                            ? PFR_NEXT_USHORT( p )
+                            : PFR_NEXT_BYTE( p );
+    }
+
+    phy_font->num_strikes += count;
+
+  Exit:
+    return error;
+
+  Too_Short:
+    error = FT_THROW( Invalid_Table );
+    FT_ERROR(( "pfr_extra_item_load_bitmap_info:"
+               " invalid bitmap info table\n" ));
+    goto Exit;
+  }
+
+
+  /* Load font ID.  This is a so-called "unique" name that is rather
+   * long and descriptive (like "Tiresias ScreenFont v7.51").
+   *
+   * Note that a PFR font's family name is contained in an *undocumented*
+   * string of the "auxiliary data" portion of a physical font record.  This
+   * may also contain the "real" style name!
+   *
+   * If no family name is present, the font ID is used instead for the
+   * family.
+   */
+  FT_CALLBACK_DEF( FT_Error )
+  pfr_extra_item_load_font_id( FT_Byte*     p,
+                               FT_Byte*     limit,
+                               PFR_PhyFont  phy_font )
+  {
+    FT_Error    error  = FT_Err_Ok;
+    FT_Memory   memory = phy_font->memory;
+    FT_PtrDist  len    = limit - p;
+
+
+    if ( phy_font->font_id != NULL )
+      goto Exit;
+
+    if ( FT_ALLOC( phy_font->font_id, len + 1 ) )
+      goto Exit;
+
+    /* copy font ID name, and terminate it for safety */
+    FT_MEM_COPY( phy_font->font_id, p, len );
+    phy_font->font_id[len] = 0;
+
+  Exit:
+    return error;
+  }
+
+
+  /* load stem snap tables */
+  FT_CALLBACK_DEF( FT_Error )
+  pfr_extra_item_load_stem_snaps( FT_Byte*     p,
+                                  FT_Byte*     limit,
+                                  PFR_PhyFont  phy_font )
+  {
+    FT_UInt    count, num_vert, num_horz;
+    FT_Int*    snaps  = NULL;
+    FT_Error   error  = FT_Err_Ok;
+    FT_Memory  memory = phy_font->memory;
+
+
+    if ( phy_font->vertical.stem_snaps != NULL )
+      goto Exit;
+
+    PFR_CHECK( 1 );
+    count = PFR_NEXT_BYTE( p );
+
+    num_vert = count & 15;
+    num_horz = count >> 4;
+    count    = num_vert + num_horz;
+
+    PFR_CHECK( count * 2 );
+
+    if ( FT_NEW_ARRAY( snaps, count ) )
+      goto Exit;
+
+    phy_font->vertical.stem_snaps = snaps;
+    phy_font->horizontal.stem_snaps = snaps + num_vert;
+
+    for ( ; count > 0; count--, snaps++ )
+      *snaps = FT_NEXT_SHORT( p );
+
+  Exit:
+    return error;
+
+  Too_Short:
+    error = FT_THROW( Invalid_Table );
+    FT_ERROR(( "pfr_exta_item_load_stem_snaps:"
+               " invalid stem snaps table\n" ));
+    goto Exit;
+  }
+
+
+
+  /* load kerning pair data */
+  FT_CALLBACK_DEF( FT_Error )
+  pfr_extra_item_load_kerning_pairs( FT_Byte*     p,
+                                     FT_Byte*     limit,
+                                     PFR_PhyFont  phy_font )
+  {
+    PFR_KernItem  item   = NULL;
+    FT_Error      error  = FT_Err_Ok;
+    FT_Memory     memory = phy_font->memory;
+
+
+    FT_TRACE2(( "pfr_extra_item_load_kerning_pairs()\n" ));
+
+    if ( FT_NEW( item ) )
+      goto Exit;
+
+    PFR_CHECK( 4 );
+
+    item->pair_count = PFR_NEXT_BYTE( p );
+    item->base_adj   = PFR_NEXT_SHORT( p );
+    item->flags      = PFR_NEXT_BYTE( p );
+    item->offset     = phy_font->offset + ( p - phy_font->cursor );
+
+#ifndef PFR_CONFIG_NO_CHECKS
+    item->pair_size = 3;
+
+    if ( item->flags & PFR_KERN_2BYTE_CHAR )
+      item->pair_size += 2;
+
+    if ( item->flags & PFR_KERN_2BYTE_ADJ )
+      item->pair_size += 1;
+
+    PFR_CHECK( item->pair_count * item->pair_size );
+#endif
+
+    /* load first and last pairs into the item to speed up */
+    /* lookup later...                                     */
+    if ( item->pair_count > 0 )
+    {
+      FT_UInt   char1, char2;
+      FT_Byte*  q;
+
+
+      if ( item->flags & PFR_KERN_2BYTE_CHAR )
+      {
+        q     = p;
+        char1 = PFR_NEXT_USHORT( q );
+        char2 = PFR_NEXT_USHORT( q );
+
+        item->pair1 = PFR_KERN_INDEX( char1, char2 );
+
+        q = p + item->pair_size * ( item->pair_count - 1 );
+        char1 = PFR_NEXT_USHORT( q );
+        char2 = PFR_NEXT_USHORT( q );
+
+        item->pair2 = PFR_KERN_INDEX( char1, char2 );
+      }
+      else
+      {
+        q     = p;
+        char1 = PFR_NEXT_BYTE( q );
+        char2 = PFR_NEXT_BYTE( q );
+
+        item->pair1 = PFR_KERN_INDEX( char1, char2 );
+
+        q = p + item->pair_size * ( item->pair_count - 1 );
+        char1 = PFR_NEXT_BYTE( q );
+        char2 = PFR_NEXT_BYTE( q );
+
+        item->pair2 = PFR_KERN_INDEX( char1, char2 );
+      }
+
+      /* add new item to the current list */
+      item->next                 = NULL;
+      *phy_font->kern_items_tail = item;
+      phy_font->kern_items_tail  = &item->next;
+      phy_font->num_kern_pairs  += item->pair_count;
+    }
+    else
+    {
+      /* empty item! */
+      FT_FREE( item );
+    }
+
+  Exit:
+    return error;
+
+  Too_Short:
+    FT_FREE( item );
+
+    error = FT_THROW( Invalid_Table );
+    FT_ERROR(( "pfr_extra_item_load_kerning_pairs:"
+               " invalid kerning pairs table\n" ));
+    goto Exit;
+  }
+
+
+
+  static const PFR_ExtraItemRec  pfr_phy_font_extra_items[] =
+  {
+    { 1, (PFR_ExtraItem_ParseFunc)pfr_extra_item_load_bitmap_info },
+    { 2, (PFR_ExtraItem_ParseFunc)pfr_extra_item_load_font_id },
+    { 3, (PFR_ExtraItem_ParseFunc)pfr_extra_item_load_stem_snaps },
+    { 4, (PFR_ExtraItem_ParseFunc)pfr_extra_item_load_kerning_pairs },
+    { 0, NULL }
+  };
+
+
+  /* Loads a name from the auxiliary data.  Since this extracts undocumented
+   * strings from the font file, we need to be careful here.
+   */
+  static FT_Error
+  pfr_aux_name_load( FT_Byte*     p,
+                     FT_UInt      len,
+                     FT_Memory    memory,
+                     FT_String*  *astring )
+  {
+    FT_Error    error  = FT_Err_Ok;
+    FT_String*  result = NULL;
+    FT_UInt     n, ok;
+
+
+    if ( len > 0 && p[len - 1] == 0 )
+      len--;
+
+    /* check that each character is ASCII for making sure not to
+       load garbage
+     */
+    ok = ( len > 0 );
+    for ( n = 0; n < len; n++ )
+      if ( p[n] < 32 || p[n] > 127 )
+      {
+        ok = 0;
+        break;
+      }
+
+    if ( ok )
+    {
+      if ( FT_ALLOC( result, len + 1 ) )
+        goto Exit;
+
+      FT_MEM_COPY( result, p, len );
+      result[len] = 0;
+    }
+  Exit:
+    *astring = result;
+    return error;
+  }
+
+
+  FT_LOCAL_DEF( void )
+  pfr_phy_font_done( PFR_PhyFont  phy_font,
+                     FT_Memory    memory )
+  {
+    FT_FREE( phy_font->font_id );
+    FT_FREE( phy_font->family_name );
+    FT_FREE( phy_font->style_name );
+
+    FT_FREE( phy_font->vertical.stem_snaps );
+    phy_font->vertical.num_stem_snaps = 0;
+
+    phy_font->horizontal.stem_snaps     = NULL;
+    phy_font->horizontal.num_stem_snaps = 0;
+
+    FT_FREE( phy_font->strikes );
+    phy_font->num_strikes = 0;
+    phy_font->max_strikes = 0;
+
+    FT_FREE( phy_font->chars );
+    phy_font->num_chars    = 0;
+    phy_font->chars_offset = 0;
+
+    FT_FREE( phy_font->blue_values );
+    phy_font->num_blue_values = 0;
+
+    {
+      PFR_KernItem  item, next;
+
+
+      item = phy_font->kern_items;
+      while ( item )
+      {
+        next = item->next;
+        FT_FREE( item );
+        item = next;
+      }
+      phy_font->kern_items      = NULL;
+      phy_font->kern_items_tail = NULL;
+    }
+
+    phy_font->num_kern_pairs = 0;
+  }
+
+
+  FT_LOCAL_DEF( FT_Error )
+  pfr_phy_font_load( PFR_PhyFont  phy_font,
+                     FT_Stream    stream,
+                     FT_UInt32    offset,
+                     FT_UInt32    size )
+  {
+    FT_Error   error;
+    FT_Memory  memory = stream->memory;
+    FT_UInt    flags;
+    FT_ULong   num_aux;
+    FT_Byte*   p;
+    FT_Byte*   limit;
+
+
+    phy_font->memory = memory;
+    phy_font->offset = offset;
+
+    phy_font->kern_items      = NULL;
+    phy_font->kern_items_tail = &phy_font->kern_items;
+
+    if ( FT_STREAM_SEEK( offset ) || FT_FRAME_ENTER( size ) )
+      goto Exit;
+
+    phy_font->cursor = stream->cursor;
+
+    p     = stream->cursor;
+    limit = p + size;
+
+    PFR_CHECK( 15 );
+    phy_font->font_ref_number    = PFR_NEXT_USHORT( p );
+    phy_font->outline_resolution = PFR_NEXT_USHORT( p );
+    phy_font->metrics_resolution = PFR_NEXT_USHORT( p );
+    phy_font->bbox.xMin          = PFR_NEXT_SHORT( p );
+    phy_font->bbox.yMin          = PFR_NEXT_SHORT( p );
+    phy_font->bbox.xMax          = PFR_NEXT_SHORT( p );
+    phy_font->bbox.yMax          = PFR_NEXT_SHORT( p );
+    phy_font->flags      = flags = PFR_NEXT_BYTE( p );
+
+    /* get the standard advance for non-proportional fonts */
+    if ( !(flags & PFR_PHY_PROPORTIONAL) )
+    {
+      PFR_CHECK( 2 );
+      phy_font->standard_advance = PFR_NEXT_SHORT( p );
+    }
+
+    /* load the extra items when present */
+    if ( flags & PFR_PHY_EXTRA_ITEMS )
+    {
+      error =  pfr_extra_items_parse( &p, limit,
+                                      pfr_phy_font_extra_items, phy_font );
+
+      if ( error )
+        goto Fail;
+    }
+
+    /* In certain fonts, the auxiliary bytes contain interesting  */
+    /* information. These are not in the specification but can be */
+    /* guessed by looking at the content of a few PFR0 fonts.     */
+    PFR_CHECK( 3 );
+    num_aux = PFR_NEXT_ULONG( p );
+
+    if ( num_aux > 0 )
+    {
+      FT_Byte*  q = p;
+      FT_Byte*  q2;
+
+
+      PFR_CHECK( num_aux );
+      p += num_aux;
+
+      while ( num_aux > 0 )
+      {
+        FT_UInt  length, type;
+
+
+        if ( q + 4 > p )
+          break;
+
+        length = PFR_NEXT_USHORT( q );
+        if ( length < 4 || length > num_aux )
+          break;
+
+        q2   = q + length - 2;
+        type = PFR_NEXT_USHORT( q );
+
+        switch ( type )
+        {
+        case 1:
+          /* this seems to correspond to the font's family name,
+           * padded to 16-bits with one zero when necessary
+           */
+          error = pfr_aux_name_load( q, length - 4U, memory,
+                                     &phy_font->family_name );
+          if ( error )
+            goto Exit;
+          break;
+
+        case 2:
+          if ( q + 32 > q2 )
+            break;
+
+          q += 10;
+          phy_font->ascent  = PFR_NEXT_SHORT( q );
+          phy_font->descent = PFR_NEXT_SHORT( q );
+          phy_font->leading = PFR_NEXT_SHORT( q );
+          q += 16;
+          break;
+
+        case 3:
+          /* this seems to correspond to the font's style name,
+           * padded to 16-bits with one zero when necessary
+           */
+          error = pfr_aux_name_load( q, length - 4U, memory,
+                                     &phy_font->style_name );
+          if ( error )
+            goto Exit;
+          break;
+
+        default:
+          ;
+        }
+
+        q        = q2;
+        num_aux -= length;
+      }
+    }
+
+    /* read the blue values */
+    {
+      FT_UInt  n, count;
+
+
+      PFR_CHECK( 1 );
+      phy_font->num_blue_values = count = PFR_NEXT_BYTE( p );
+
+      PFR_CHECK( count * 2 );
+
+      if ( FT_NEW_ARRAY( phy_font->blue_values, count ) )
+        goto Fail;
+
+      for ( n = 0; n < count; n++ )
+        phy_font->blue_values[n] = PFR_NEXT_SHORT( p );
+    }
+
+    PFR_CHECK( 8 );
+    phy_font->blue_fuzz  = PFR_NEXT_BYTE( p );
+    phy_font->blue_scale = PFR_NEXT_BYTE( p );
+
+    phy_font->vertical.standard   = PFR_NEXT_USHORT( p );
+    phy_font->horizontal.standard = PFR_NEXT_USHORT( p );
+
+    /* read the character descriptors */
+    {
+      FT_UInt  n, count, Size;
+
+
+      phy_font->num_chars    = count = PFR_NEXT_USHORT( p );
+      phy_font->chars_offset = offset + ( p - stream->cursor );
+
+      if ( FT_NEW_ARRAY( phy_font->chars, count ) )
+        goto Fail;
+
+      Size = 1 + 1 + 2;
+      if ( flags & PFR_PHY_2BYTE_CHARCODE )
+        Size += 1;
+
+      if ( flags & PFR_PHY_PROPORTIONAL )
+        Size += 2;
+
+      if ( flags & PFR_PHY_ASCII_CODE )
+        Size += 1;
+
+      if ( flags & PFR_PHY_2BYTE_GPS_SIZE )
+        Size += 1;
+
+      if ( flags & PFR_PHY_3BYTE_GPS_OFFSET )
+        Size += 1;
+
+      PFR_CHECK( count * Size );
+
+      for ( n = 0; n < count; n++ )
+      {
+        PFR_Char  cur = &phy_font->chars[n];
+
+
+        cur->char_code = ( flags & PFR_PHY_2BYTE_CHARCODE )
+                         ? PFR_NEXT_USHORT( p )
+                         : PFR_NEXT_BYTE( p );
+
+        cur->advance   = ( flags & PFR_PHY_PROPORTIONAL )
+                         ? PFR_NEXT_SHORT( p )
+                         : (FT_Int) phy_font->standard_advance;
+
+#if 0
+        cur->ascii     = ( flags & PFR_PHY_ASCII_CODE )
+                         ? PFR_NEXT_BYTE( p )
+                         : 0;
+#else
+        if ( flags & PFR_PHY_ASCII_CODE )
+          p += 1;
+#endif
+        cur->gps_size  = ( flags & PFR_PHY_2BYTE_GPS_SIZE )
+                         ? PFR_NEXT_USHORT( p )
+                         : PFR_NEXT_BYTE( p );
+
+        cur->gps_offset = ( flags & PFR_PHY_3BYTE_GPS_OFFSET )
+                          ? PFR_NEXT_ULONG( p )
+                          : PFR_NEXT_USHORT( p );
+      }
+    }
+
+    /* that's it! */
+
+  Fail:
+    FT_FRAME_EXIT();
+
+    /* save position of bitmap info */
+    phy_font->bct_offset = FT_STREAM_POS();
+    phy_font->cursor     = NULL;
+
+  Exit:
+    return error;
+
+  Too_Short:
+    error = FT_THROW( Invalid_Table );
+    FT_ERROR(( "pfr_phy_font_load: invalid physical font table\n" ));
+    goto Fail;
+  }
+
+
+/* END */
diff --git a/src/psaux/afmparse.c b/src/psaux/afmparse.c
index 5f3f9e6..6a40e11 100644
--- a/src/psaux/afmparse.c
+++ b/src/psaux/afmparse.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    AFM parser (body).                                                   */
 /*                                                                         */
-/*  Copyright 2006-2010, 2012 by                                           */
+/*  Copyright 2006-2010, 2012, 2013 by                                     */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -17,6 +17,7 @@
 
 #include <ft2build.h>
 #include FT_FREETYPE_H
+#include FT_INTERNAL_DEBUG_H
 #include FT_INTERNAL_POSTSCRIPT_AUX_H
 
 #include "afmparse.h"
@@ -119,7 +120,6 @@
   afm_stream_read_one( AFM_Stream  stream )
   {
     char*  str;
-    int    ch;
 
 
     afm_stream_skip_spaces( stream );
@@ -130,7 +130,9 @@
 
     while ( 1 )
     {
-      ch = AFM_GETC();
+      int  ch = AFM_GETC();
+
+
       if ( AFM_IS_SPACE( ch ) )
         break;
       else if ( AFM_IS_NEWLINE( ch ) )
@@ -159,7 +161,6 @@
   afm_stream_read_string( AFM_Stream  stream )
   {
     char*  str;
-    int    ch;
 
 
     afm_stream_skip_spaces( stream );
@@ -171,7 +172,9 @@
     /* scan to eol */
     while ( 1 )
     {
-      ch = AFM_GETC();
+      int  ch = AFM_GETC();
+
+
       if ( AFM_IS_NEWLINE( ch ) )
       {
         stream->status = AFM_STREAM_STATUS_EOL;
@@ -545,7 +548,7 @@
     parser->FontInfo  = NULL;
     parser->get_index = NULL;
 
-    return PSaux_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
@@ -572,10 +575,10 @@
     {
       *aint = val.u.i;
 
-      return PSaux_Err_Ok;
+      return FT_Err_Ok;
     }
     else
-      return PSaux_Err_Syntax_Error;
+      return FT_THROW( Syntax_Error );
   }
 
 
@@ -637,7 +640,7 @@
       case AFM_TOKEN_ENDKERNDATA:
       case AFM_TOKEN_ENDFONTMETRICS:
         fi->NumTrackKern = n + 1;
-        return PSaux_Err_Ok;
+        return FT_Err_Ok;
 
       case AFM_TOKEN_UNKNOWN:
         break;
@@ -648,7 +651,7 @@
     }
 
   Fail:
-    return PSaux_Err_Syntax_Error;
+    return FT_THROW( Syntax_Error );
   }
 
 
@@ -753,7 +756,7 @@
         ft_qsort( fi->KernPairs, fi->NumKernPair,
                   sizeof ( AFM_KernPairRec ),
                   afm_compare_kern_pairs );
-        return PSaux_Err_Ok;
+        return FT_Err_Ok;
 
       case AFM_TOKEN_UNKNOWN:
         break;
@@ -764,7 +767,7 @@
     }
 
   Fail:
-    return PSaux_Err_Syntax_Error;
+    return FT_THROW( Syntax_Error );
   }
 
 
@@ -795,7 +798,7 @@
 
       case AFM_TOKEN_ENDKERNDATA:
       case AFM_TOKEN_ENDFONTMETRICS:
-        return PSaux_Err_Ok;
+        return FT_Err_Ok;
 
       case AFM_TOKEN_UNKNOWN:
         break;
@@ -806,7 +809,7 @@
     }
 
   Fail:
-    return PSaux_Err_Syntax_Error;
+    return FT_THROW( Syntax_Error );
   }
 
 
@@ -832,11 +835,11 @@
 
 
       if ( token == end_section || token == AFM_TOKEN_ENDFONTMETRICS )
-        return PSaux_Err_Ok;
+        return FT_Err_Ok;
     }
 
   Fail:
-    return PSaux_Err_Syntax_Error;
+    return FT_THROW( Syntax_Error );
   }
 
 
@@ -845,19 +848,19 @@
   {
     FT_Memory     memory = parser->memory;
     AFM_FontInfo  fi     = parser->FontInfo;
-    FT_Error      error  = PSaux_Err_Syntax_Error;
+    FT_Error      error  = FT_ERR( Syntax_Error );
     char*         key;
     FT_Offset     len;
     FT_Int        metrics_sets = 0;
 
 
     if ( !fi )
-      return PSaux_Err_Invalid_Argument;
+      return FT_THROW( Invalid_Argument );
 
     key = afm_parser_next_key( parser, 1, &len );
     if ( !key || len != 16                              ||
          ft_strncmp( key, "StartFontMetrics", 16 ) != 0 )
-      return PSaux_Err_Unknown_File_Format;
+      return FT_THROW( Unknown_File_Format );
 
     while ( ( key = afm_parser_next_key( parser, 1, &len ) ) != 0 )
     {
@@ -872,7 +875,7 @@
 
         if ( metrics_sets != 0 && metrics_sets != 2 )
         {
-          error = PSaux_Err_Unimplemented_Feature;
+          error = FT_THROW( Unimplemented_Feature );
 
           goto Fail;
         }
@@ -938,7 +941,7 @@
         /* fall through since we only support kern data */
 
       case AFM_TOKEN_ENDFONTMETRICS:
-        return PSaux_Err_Ok;
+        return FT_Err_Ok;
 
       default:
         break;
diff --git a/src/psaux/psconv.c b/src/psaux/psconv.c
index 9ea7fb9..d0d8861 100644
--- a/src/psaux/psconv.c
+++ b/src/psaux/psconv.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Some convenience conversions (body).                                 */
 /*                                                                         */
-/*  Copyright 2006, 2008, 2009, 2012 by                                    */
+/*  Copyright 2006, 2008, 2009, 2012-2013 by                               */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -18,11 +18,22 @@
 
 #include <ft2build.h>
 #include FT_INTERNAL_POSTSCRIPT_AUX_H
+#include FT_INTERNAL_DEBUG_H
 
 #include "psconv.h"
 #include "psauxerr.h"
 
 
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_psconv
+
+
   /* The following array is used by various functions to quickly convert */
   /* digits (both decimal and non-decimal) into numbers.                 */
 
@@ -69,18 +80,29 @@
 #endif /* 'A' == 193 */
 
 
-  FT_LOCAL_DEF( FT_Int )
+  FT_LOCAL_DEF( FT_Long )
   PS_Conv_Strtol( FT_Byte**  cursor,
                   FT_Byte*   limit,
-                  FT_Int     base )
+                  FT_Long    base )
   {
     FT_Byte*  p = *cursor;
-    FT_Int    num = 0;
-    FT_Bool   sign = 0;
+
+    FT_Long   num           = 0;
+    FT_Bool   sign          = 0;
+    FT_Bool   have_overflow = 0;
+
+    FT_Long   num_limit;
+    FT_Char   c_limit;
 
 
-    if ( p >= limit || base < 2 || base > 36 )
+    if ( p >= limit )
+      goto Bad;
+
+    if ( base < 2 || base > 36 )
+    {
+      FT_TRACE4(( "!!!INVALID BASE:!!!" ));
       return 0;
+    }
 
     if ( *p == '-' || *p == '+' )
     {
@@ -88,9 +110,12 @@
 
       p++;
       if ( p == limit )
-        return 0;
+        goto Bad;
     }
 
+    num_limit = 0x7FFFFFFFL / base;
+    c_limit   = (FT_Char)( 0x7FFFFFFFL % base );
+
     for ( ; p < limit; p++ )
     {
       FT_Char  c;
@@ -104,54 +129,84 @@
       if ( c < 0 || c >= base )
         break;
 
-      num = num * base + c;
+      if ( num > num_limit || ( num == num_limit && c > c_limit ) )
+        have_overflow = 1;
+      else
+        num = num * base + c;
+    }
+
+    *cursor = p;
+
+    if ( have_overflow )
+    {
+      num = 0x7FFFFFFFL;
+      FT_TRACE4(( "!!!OVERFLOW:!!!" ));
     }
 
     if ( sign )
       num = -num;
 
+    return num;
+
+  Bad:
+    FT_TRACE4(( "!!!END OF DATA:!!!" ));
+    return 0;
+  }
+
+
+  FT_LOCAL_DEF( FT_Long )
+  PS_Conv_ToInt( FT_Byte**  cursor,
+                 FT_Byte*   limit )
+
+  {
+    FT_Byte*  p = *cursor;
+    FT_Byte*  curp;
+
+    FT_Long   num;
+
+
+    curp = p;
+    num  = PS_Conv_Strtol( &p, limit, 10 );
+
+    if ( p == curp )
+      return 0;
+
+    if ( p < limit && *p == '#' )
+    {
+      p++;
+
+      curp = p;
+      num  = PS_Conv_Strtol( &p, limit, num );
+
+      if ( p == curp )
+        return 0;
+    }
+
     *cursor = p;
 
     return num;
   }
 
 
-  FT_LOCAL_DEF( FT_Int )
-  PS_Conv_ToInt( FT_Byte**  cursor,
-                 FT_Byte*   limit )
-
-  {
-    FT_Byte*  p;
-    FT_Int    num;
-
-
-    num = PS_Conv_Strtol( cursor, limit, 10 );
-    p   = *cursor;
-
-    if ( p < limit && *p == '#' )
-    {
-      *cursor = p + 1;
-
-      return PS_Conv_Strtol( cursor, limit, num );
-    }
-    else
-      return num;
-  }
-
-
   FT_LOCAL_DEF( FT_Fixed )
   PS_Conv_ToFixed( FT_Byte**  cursor,
                    FT_Byte*   limit,
-                   FT_Int     power_ten )
+                   FT_Long    power_ten )
   {
     FT_Byte*  p = *cursor;
-    FT_Fixed  integral;
-    FT_Long   decimal = 0, divider = 1;
-    FT_Bool   sign = 0;
+    FT_Byte*  curp;
+
+    FT_Fixed  integral = 0;
+    FT_Long   decimal  = 0;
+    FT_Long   divider  = 1;
+
+    FT_Bool   sign           = 0;
+    FT_Bool   have_overflow  = 0;
+    FT_Bool   have_underflow = 0;
 
 
     if ( p >= limit )
-      return 0;
+      goto Bad;
 
     if ( *p == '-' || *p == '+' )
     {
@@ -159,13 +214,23 @@
 
       p++;
       if ( p == limit )
-        return 0;
+        goto Bad;
     }
 
+    /* read the integer part */
     if ( *p != '.' )
-      integral = PS_Conv_ToInt( &p, limit ) << 16;
-    else
-      integral = 0;
+    {
+      curp     = p;
+      integral = PS_Conv_ToInt( &p, limit );
+
+      if ( p == curp )
+        return 0;
+
+      if ( integral > 0x7FFF )
+        have_overflow = 1;
+      else
+        integral = (FT_Fixed)( (FT_UInt32)integral << 16 );
+    }
 
     /* read the decimal part */
     if ( p < limit && *p == '.' )
@@ -185,18 +250,14 @@
         if ( c < 0 || c >= 10 )
           break;
 
-        if ( !integral && power_ten > 0 )
+        if ( decimal < 0xCCCCCCCL )
         {
-          power_ten--;
           decimal = decimal * 10 + c;
-        }
-        else
-        {
-          if ( divider < 10000000L )
-          {
-            decimal = decimal * 10 + c;
+
+          if ( !integral && power_ten > 0 )
+            power_ten--;
+          else
             divider *= 10;
-          }
         }
       }
     }
@@ -204,33 +265,94 @@
     /* read exponent, if any */
     if ( p + 1 < limit && ( *p == 'e' || *p == 'E' ) )
     {
+      FT_Long  exponent;
+
+
       p++;
-      power_ten += PS_Conv_ToInt( &p, limit );
+
+      curp     = p;
+      exponent = PS_Conv_ToInt( &p, limit );
+
+      if ( curp == p )
+        return 0;
+
+      /* arbitrarily limit exponent */
+      if ( exponent > 1000 )
+        have_overflow = 1;
+      else if ( exponent < -1000 )
+        have_underflow = 1;
+      else
+        power_ten += exponent;
     }
 
+    *cursor = p;
+
+    if ( !integral && !decimal )
+      return 0;
+
+    if ( have_overflow )
+      goto Overflow;
+    if ( have_underflow )
+      goto Underflow;
+
     while ( power_ten > 0 )
     {
+      if ( integral >= 0xCCCCCCCL )
+        goto Overflow;
       integral *= 10;
-      decimal  *= 10;
+
+      if ( decimal >= 0xCCCCCCCL )
+      {
+        if ( divider == 1 )
+          goto Overflow;
+        divider /= 10;
+      }
+      else
+        decimal *= 10;
+
       power_ten--;
     }
 
     while ( power_ten < 0 )
     {
       integral /= 10;
-      divider  *= 10;
+      if ( divider < 0xCCCCCCCL )
+        divider *= 10;
+      else
+        decimal /= 10;
+
+      if ( !integral && !decimal )
+        goto Underflow;
+
       power_ten++;
     }
 
     if ( decimal )
-      integral += FT_DivFix( decimal, divider );
+    {
+      decimal = FT_DivFix( decimal, divider );
+      /* it's not necessary to check this addition for overflow */
+      /* due to the structure of the real number representation */
+      integral += decimal;
+    }
 
+  Exit:
     if ( sign )
       integral = -integral;
 
-    *cursor = p;
-
     return integral;
+
+  Bad:
+    FT_TRACE4(( "!!!END OF DATA:!!!" ));
+    return 0;
+
+  Overflow:
+    integral = 0x7FFFFFFFL;
+    FT_TRACE4(( "!!!OVERFLOW:!!!" ));
+    goto Exit;
+
+  Underflow:
+    FT_TRACE4(( "!!!UNDERFLOW:!!!" ));
+    return 0;
   }
 
 
diff --git a/src/psaux/psconv.h b/src/psaux/psconv.h
index 84854ba..d91c762 100644
--- a/src/psaux/psconv.h
+++ b/src/psaux/psconv.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Some convenience conversions (specification).                        */
 /*                                                                         */
-/*  Copyright 2006 by                                                      */
+/*  Copyright 2006, 2012 by                                                */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -26,20 +26,20 @@
 FT_BEGIN_HEADER
 
 
-  FT_LOCAL( FT_Int )
+  FT_LOCAL( FT_Long )
   PS_Conv_Strtol( FT_Byte**  cursor,
                   FT_Byte*   limit,
-                  FT_Int     base );
+                  FT_Long    base );
 
 
-  FT_LOCAL( FT_Int )
+  FT_LOCAL( FT_Long )
   PS_Conv_ToInt( FT_Byte**  cursor,
                  FT_Byte*   limit );
 
   FT_LOCAL( FT_Fixed )
   PS_Conv_ToFixed( FT_Byte**  cursor,
                    FT_Byte*   limit,
-                   FT_Int     power_ten );
+                   FT_Long    power_ten );
 
 #if 0
   FT_LOCAL( FT_UInt )
diff --git a/src/psaux/psobjs.c b/src/psaux/psobjs.c
index 06df6e6..dd976d3 100644
--- a/src/psaux/psobjs.c
+++ b/src/psaux/psobjs.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Auxiliary functions for PostScript fonts (body).                     */
 /*                                                                         */
-/*  Copyright 1996-2012 by                                                 */
+/*  Copyright 1996-2013 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -113,8 +113,8 @@
 
 
   static FT_Error
-  reallocate_t1_table( PS_Table  table,
-                       FT_Long   new_size )
+  reallocate_t1_table( PS_Table   table,
+                       FT_Offset  new_size )
   {
     FT_Memory  memory   = table->memory;
     FT_Byte*   old_base = table->block;
@@ -138,7 +138,7 @@
 
     table->capacity = new_size;
 
-    return PSaux_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
@@ -173,13 +173,13 @@
     if ( idx < 0 || idx >= table->max_elems )
     {
       FT_ERROR(( "ps_table_add: invalid index\n" ));
-      return PSaux_Err_Invalid_Argument;
+      return FT_THROW( Invalid_Argument );
     }
 
     if ( length < 0 )
     {
       FT_ERROR(( "ps_table_add: invalid length\n" ));
-      return PSaux_Err_Invalid_Argument;
+      return FT_THROW( Invalid_Argument );
     }
 
     /* grow the base block if needed */
@@ -216,7 +216,7 @@
     FT_MEM_COPY( table->block + table->cursor, object, length );
 
     table->cursor += length;
-    return PSaux_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
@@ -341,7 +341,7 @@
   {
     FT_Byte*      cur   = *acur;
     FT_Int        embed = 0;
-    FT_Error      error = PSaux_Err_Invalid_File_Format;
+    FT_Error      error = FT_ERR( Invalid_File_Format );
     unsigned int  i;
 
 
@@ -397,7 +397,7 @@
         embed--;
         if ( embed == 0 )
         {
-          error = PSaux_Err_Ok;
+          error = FT_Err_Ok;
           break;
         }
       }
@@ -416,7 +416,7 @@
                FT_Byte*   limit )
   {
     FT_Byte*  cur = *acur;
-    FT_Error  err =  PSaux_Err_Ok;
+    FT_Error  err =  FT_Err_Ok;
 
 
     while ( ++cur < limit )
@@ -433,7 +433,7 @@
     if ( cur < limit && *cur != '>' )
     {
       FT_ERROR(( "skip_string: missing closing delimiter `>'\n" ));
-      err = PSaux_Err_Invalid_File_Format;
+      err = FT_THROW( Invalid_File_Format );
     }
     else
       cur++;
@@ -456,12 +456,12 @@
   {
     FT_Byte*  cur;
     FT_Int    embed = 0;
-    FT_Error  error = PSaux_Err_Ok;
+    FT_Error  error = FT_Err_Ok;
 
 
     FT_ASSERT( **acur == '{' );
 
-    for ( cur = *acur; cur < limit && error == PSaux_Err_Ok; ++cur )
+    for ( cur = *acur; cur < limit && error == FT_Err_Ok; ++cur )
     {
       switch ( *cur )
       {
@@ -494,7 +494,7 @@
 
   end:
     if ( embed != 0 )
-      error = PSaux_Err_Invalid_File_Format;
+      error = FT_THROW( Invalid_File_Format );
 
     *acur = cur;
 
@@ -519,7 +519,7 @@
 
     FT_Byte*  cur   = parser->cursor;
     FT_Byte*  limit = parser->limit;
-    FT_Error  error = PSaux_Err_Ok;
+    FT_Error  error = FT_Err_Ok;
 
 
     skip_spaces( &cur, limit );             /* this also skips comments */
@@ -567,7 +567,7 @@
       {
         FT_ERROR(( "ps_parser_skip_PS_token:"
                    " unexpected closing delimiter `>'\n" ));
-        error = PSaux_Err_Invalid_File_Format;
+        error = FT_THROW( Invalid_File_Format );
         goto Exit;
       }
       cur++;
@@ -597,7 +597,7 @@
                  " but invalid at this point\n",
                  *cur ));
 
-      error = PSaux_Err_Invalid_File_Format;
+      error = FT_THROW( Invalid_File_Format );
     }
 
     parser->error  = error;
@@ -644,7 +644,7 @@
       token->type  = T1_TOKEN_TYPE_STRING;
       token->start = cur;
 
-      if ( skip_literal_string( &cur, limit ) == PSaux_Err_Ok )
+      if ( skip_literal_string( &cur, limit ) == FT_Err_Ok )
         token->limit = cur;
       break;
 
@@ -653,7 +653,7 @@
       token->type  = T1_TOKEN_TYPE_ARRAY;
       token->start = cur;
 
-      if ( skip_procedure( &cur, limit ) == PSaux_Err_Ok )
+      if ( skip_procedure( &cur, limit ) == FT_Err_Ok )
         token->limit = cur;
       break;
 
@@ -1027,12 +1027,13 @@
                         FT_UInt         max_objects,
                         FT_ULong*       pflags )
   {
-    T1_TokenRec  token;
-    FT_Byte*     cur;
-    FT_Byte*     limit;
-    FT_UInt      count;
-    FT_UInt      idx;
-    FT_Error     error;
+    T1_TokenRec   token;
+    FT_Byte*      cur;
+    FT_Byte*      limit;
+    FT_UInt       count;
+    FT_UInt       idx;
+    FT_Error      error;
+    T1_FieldType  type;
 
 
     /* this also skips leading whitespace */
@@ -1045,8 +1046,10 @@
     cur   = token.start;
     limit = token.limit;
 
+    type = field->type;
+
     /* we must detect arrays in /FontBBox */
-    if ( field->type == T1_FIELD_TYPE_BBOX )
+    if ( type == T1_FIELD_TYPE_BBOX )
     {
       T1_TokenRec  token2;
       FT_Byte*     old_cur   = parser->cursor;
@@ -1062,17 +1065,21 @@
       parser->limit  = old_limit;
 
       if ( token2.type == T1_TOKEN_TYPE_ARRAY )
+      {
+        type = T1_FIELD_TYPE_MM_BBOX;
         goto FieldArray;
+      }
     }
     else if ( token.type == T1_TOKEN_TYPE_ARRAY )
     {
+      count = max_objects;
+
     FieldArray:
       /* if this is an array and we have no blend, an error occurs */
       if ( max_objects == 0 )
         goto Fail;
 
-      count = max_objects;
-      idx   = 1;
+      idx = 1;
 
       /* don't include delimiters */
       cur++;
@@ -1088,7 +1095,7 @@
 
       skip_spaces( &cur, limit );
 
-      switch ( field->type )
+      switch ( type )
       {
       case T1_FIELD_TYPE_BOOL:
         val = ps_tobool( &cur, limit );
@@ -1160,7 +1167,7 @@
                        "                     "
                        " but found token of type %d instead\n",
                        token.type ));
-            error = PSaux_Err_Invalid_File_Format;
+            error = FT_THROW( Invalid_File_Format );
             goto Exit;
           }
 
@@ -1197,7 +1204,7 @@
           {
             FT_ERROR(( "ps_parser_load_field:"
                        " expected four integers in bounding box\n" ));
-            error = PSaux_Err_Invalid_File_Format;
+            error = FT_THROW( Invalid_File_Format );
             goto Exit;
           }
 
@@ -1208,6 +1215,54 @@
         }
         break;
 
+      case T1_FIELD_TYPE_MM_BBOX:
+        {
+          FT_Memory  memory = parser->memory;
+          FT_Fixed*  temp;
+          FT_Int     result;
+          FT_UInt    i;
+
+
+          if ( FT_NEW_ARRAY( temp, max_objects * 4 ) )
+            goto Exit;
+
+          for ( i = 0; i < 4; i++ )
+          {
+            result = ps_tofixedarray( &cur, limit, max_objects,
+                                      temp + i * max_objects, 0 );
+            if ( result < 0 )
+            {
+              FT_ERROR(( "ps_parser_load_field:"
+                         " expected %d integers in the %s subarray\n"
+                         "                     "
+                         " of /FontBBox in the /Blend dictionary\n",
+                         max_objects,
+                         i == 0 ? "first"
+                                : ( i == 1 ? "second"
+                                           : ( i == 2 ? "third"
+                                                      : "fourth" ) ) ));
+              error = FT_THROW( Invalid_File_Format );
+              goto Exit;
+            }
+
+            skip_spaces( &cur, limit );
+          }
+
+          for ( i = 0; i < max_objects; i++ )
+          {
+            FT_BBox*  bbox = (FT_BBox*)objects[i];
+
+
+            bbox->xMin = FT_RoundFix( temp[i                  ] );
+            bbox->yMin = FT_RoundFix( temp[i +     max_objects] );
+            bbox->xMax = FT_RoundFix( temp[i + 2 * max_objects] );
+            bbox->yMax = FT_RoundFix( temp[i + 3 * max_objects] );
+          }
+
+          FT_FREE( temp );
+        }
+        break;
+
       default:
         /* an error occurred */
         goto Fail;
@@ -1221,13 +1276,13 @@
     FT_UNUSED( pflags );
 #endif
 
-    error = PSaux_Err_Ok;
+    error = FT_Err_Ok;
 
   Exit:
     return error;
 
   Fail:
-    error = PSaux_Err_Invalid_File_Format;
+    error = FT_THROW( Invalid_File_Format );
     goto Exit;
   }
 
@@ -1245,7 +1300,7 @@
     T1_TokenRec  elements[T1_MAX_TABLE_ELEMENTS];
     T1_Token     token;
     FT_Int       num_elements;
-    FT_Error     error = PSaux_Err_Ok;
+    FT_Error     error = FT_Err_Ok;
     FT_Byte*     old_cursor;
     FT_Byte*     old_limit;
     T1_FieldRec  fieldrec = *(T1_Field)field;
@@ -1260,7 +1315,7 @@
                               T1_MAX_TABLE_ELEMENTS, &num_elements );
     if ( num_elements < 0 )
     {
-      error = PSaux_Err_Ignore;
+      error = FT_ERR( Ignore );
       goto Exit;
     }
     if ( (FT_UInt)num_elements > field->array_max )
@@ -1317,7 +1372,7 @@
                       FT_Long*   pnum_bytes,
                       FT_Bool    delimiters )
   {
-    FT_Error  error = PSaux_Err_Ok;
+    FT_Error  error = FT_Err_Ok;
     FT_Byte*  cur;
 
 
@@ -1332,7 +1387,7 @@
       if ( *cur != '<' )
       {
         FT_ERROR(( "ps_parser_to_bytes: Missing starting delimiter `<'\n" ));
-        error = PSaux_Err_Invalid_File_Format;
+        error = FT_THROW( Invalid_File_Format );
         goto Exit;
       }
 
@@ -1349,7 +1404,7 @@
       if ( cur < parser->limit && *cur != '>' )
       {
         FT_ERROR(( "ps_parser_to_bytes: Missing closing delimiter `>'\n" ));
-        error = PSaux_Err_Invalid_File_Format;
+        error = FT_THROW( Invalid_File_Format );
         goto Exit;
       }
 
@@ -1419,7 +1474,7 @@
                   FT_Byte*   limit,
                   FT_Memory  memory )
   {
-    parser->error  = PSaux_Err_Ok;
+    parser->error  = FT_Err_Ok;
     parser->base   = base;
     parser->limit  = limit;
     parser->cursor = base;
@@ -1592,13 +1647,13 @@
     if ( !outline )
     {
       FT_ERROR(( "t1_builder_add_contour: no outline to add points to\n" ));
-      return PSaux_Err_Invalid_File_Format;
+      return FT_THROW( Invalid_File_Format );
     }
 
     if ( !builder->load_points )
     {
       outline->n_contours++;
-      return PSaux_Err_Ok;
+      return FT_Err_Ok;
     }
 
     error = FT_GLYPHLOADER_CHECK_POINTS( builder->loader, 0, 1 );
@@ -1621,13 +1676,13 @@
                           FT_Pos      x,
                           FT_Pos      y )
   {
-    FT_Error  error = PSaux_Err_Invalid_File_Format;
+    FT_Error  error = FT_ERR( Invalid_File_Format );
 
 
     /* test whether we are building a new contour */
 
     if ( builder->parse_state == T1_Parse_Have_Path )
-      error = PSaux_Err_Ok;
+      error = FT_Err_Ok;
     else
     {
       builder->parse_state = T1_Parse_Have_Path;
diff --git a/src/psaux/t1decode.c b/src/psaux/t1decode.c
index ea67841..6ce370b 100644
--- a/src/psaux/t1decode.c
+++ b/src/psaux/t1decode.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    PostScript Type 1 decoding routines (body).                          */
 /*                                                                         */
-/*  Copyright 2000-2011 by                                                 */
+/*  Copyright 2000-2013 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -205,7 +205,13 @@
     if ( decoder->seac )
     {
       FT_ERROR(( "t1operator_seac: invalid nested seac\n" ));
-      return PSaux_Err_Syntax_Error;
+      return FT_THROW( Syntax_Error );
+    }
+
+    if ( decoder->builder.metrics_only )
+    {
+      FT_ERROR(( "t1operator_seac: unexpected seac\n" ));
+      return FT_THROW( Syntax_Error );
     }
 
     /* seac weirdness */
@@ -222,7 +228,7 @@
     {
       FT_ERROR(( "t1operator_seac:"
                  " glyph names table not available in this font\n" ));
-      return PSaux_Err_Syntax_Error;
+      return FT_THROW( Syntax_Error );
     }
 
 #ifdef FT_CONFIG_OPTION_INCREMENTAL
@@ -243,7 +249,7 @@
     {
       FT_ERROR(( "t1operator_seac:"
                  " invalid seac character code arguments\n" ));
-      return PSaux_Err_Syntax_Error;
+      return FT_THROW( Syntax_Error );
     }
 
     /* if we are trying to load a composite glyph, do not load the */
@@ -409,7 +415,7 @@
     limit = zone->limit  = charstring_base + charstring_len;
     ip    = zone->cursor = zone->base;
 
-    error = PSaux_Err_Ok;
+    error = FT_Err_Ok;
 
     x = orig_x = builder->pos_x;
     y = orig_y = builder->pos_y;
@@ -559,10 +565,10 @@
           goto Syntax_Error;
         }
 
-        value = (FT_Int32)( ( (FT_Long)ip[0] << 24 ) |
-                            ( (FT_Long)ip[1] << 16 ) |
-                            ( (FT_Long)ip[2] << 8  ) |
-                                       ip[3]         );
+        value = (FT_Int32)( ( (FT_UInt32)ip[0] << 24 ) |
+                            ( (FT_UInt32)ip[1] << 16 ) |
+                            ( (FT_UInt32)ip[2] << 8  ) |
+                              (FT_UInt32)ip[3]         );
         ip += 4;
 
         /* According to the specification, values > 32000 or < -32000 must */
@@ -585,7 +591,7 @@
         else
         {
           if ( !large_int )
-            value <<= 16;
+            value = (FT_Int32)( (FT_UInt32)value << 16 );
         }
 
         break;
@@ -605,13 +611,13 @@
             }
 
             if ( ip[-2] < 251 )
-              value =  ( ( (FT_Int32)ip[-2] - 247 ) << 8 ) + ip[-1] + 108;
+              value =    ( ( ip[-2] - 247 ) * 256 ) + ip[-1] + 108;
             else
-              value = -( ( ( (FT_Int32)ip[-2] - 251 ) << 8 ) + ip[-1] + 108 );
+              value = -( ( ( ip[-2] - 251 ) * 256 ) + ip[-1] + 108 );
           }
 
           if ( !large_int )
-            value <<= 16;
+            value = (FT_Int32)( (FT_UInt32)value << 16 );
         }
         else
         {
@@ -750,9 +756,9 @@
           decoder->flex_state        = 1;
           decoder->num_flex_vectors  = 0;
           if ( ( error = t1_builder_start_point( builder, x, y ) )
-                 != PSaux_Err_Ok                                   ||
+                 != FT_Err_Ok                                   ||
                ( error = t1_builder_check_points( builder, 6 ) )
-                 != PSaux_Err_Ok                                   )
+                 != FT_Err_Ok                                   )
             goto Fail;
           break;
 
@@ -1123,7 +1129,7 @@
           FT_TRACE4(( "\n" ));
 
           /* return now! */
-          return PSaux_Err_Ok;
+          return FT_Err_Ok;
 
         case op_hsbw:
           FT_TRACE4(( " hsbw" ));
@@ -1143,7 +1149,7 @@
           /* the glyph's metrics (lsb + advance width), not load the   */
           /* rest of it; so exit immediately                           */
           if ( builder->metrics_only )
-            return PSaux_Err_Ok;
+            return FT_Err_Ok;
 
           break;
 
@@ -1172,7 +1178,7 @@
           /* the glyph's metrics (lsb + advance width), not load the   */
           /* rest of it; so exit immediately                           */
           if ( builder->metrics_only )
-            return PSaux_Err_Ok;
+            return FT_Err_Ok;
 
           break;
 
@@ -1191,7 +1197,7 @@
           FT_TRACE4(( " hlineto" ));
 
           if ( ( error = t1_builder_start_point( builder, x, y ) )
-                 != PSaux_Err_Ok )
+                 != FT_Err_Ok )
             goto Fail;
 
           x += top[0];
@@ -1213,9 +1219,9 @@
           FT_TRACE4(( " hvcurveto" ));
 
           if ( ( error = t1_builder_start_point( builder, x, y ) )
-                 != PSaux_Err_Ok                                   ||
+                 != FT_Err_Ok                                   ||
                ( error = t1_builder_check_points( builder, 3 ) )
-                 != PSaux_Err_Ok                                   )
+                 != FT_Err_Ok                                   )
             goto Fail;
 
           x += top[0];
@@ -1231,7 +1237,7 @@
           FT_TRACE4(( " rlineto" ));
 
           if ( ( error = t1_builder_start_point( builder, x, y ) )
-                 != PSaux_Err_Ok )
+                 != FT_Err_Ok )
             goto Fail;
 
           x += top[0];
@@ -1239,7 +1245,7 @@
 
         Add_Line:
           if ( ( error = t1_builder_add_point1( builder, x, y ) )
-                 != PSaux_Err_Ok )
+                 != FT_Err_Ok )
             goto Fail;
           break;
 
@@ -1260,9 +1266,9 @@
           FT_TRACE4(( " rrcurveto" ));
 
           if ( ( error = t1_builder_start_point( builder, x, y ) )
-                 != PSaux_Err_Ok                                   ||
+                 != FT_Err_Ok                                   ||
                ( error = t1_builder_check_points( builder, 3 ) )
-                 != PSaux_Err_Ok                                   )
+                 != FT_Err_Ok                                   )
             goto Fail;
 
           x += top[0];
@@ -1282,9 +1288,9 @@
           FT_TRACE4(( " vhcurveto" ));
 
           if ( ( error = t1_builder_start_point( builder, x, y ) )
-                 != PSaux_Err_Ok                                   ||
+                 != FT_Err_Ok                                   ||
                ( error = t1_builder_check_points( builder, 3 ) )
-                 != PSaux_Err_Ok                                   )
+                 != FT_Err_Ok                                   )
             goto Fail;
 
           y += top[0];
@@ -1300,7 +1306,7 @@
           FT_TRACE4(( " vlineto" ));
 
           if ( ( error = t1_builder_start_point( builder, x, y ) )
-                 != PSaux_Err_Ok )
+                 != FT_Err_Ok )
             goto Fail;
 
           y += top[0];
@@ -1539,10 +1545,10 @@
     return error;
 
   Syntax_Error:
-    return PSaux_Err_Syntax_Error;
+    return FT_THROW( Syntax_Error );
 
   Stack_Underflow:
-    return PSaux_Err_Stack_Underflow;
+    return FT_THROW( Stack_Underflow );
   }
 
 
@@ -1579,7 +1585,7 @@
       {
         FT_ERROR(( "t1_decoder_init:"
                    " the `psnames' module is not available\n" ));
-        return PSaux_Err_Unimplemented_Feature;
+        return FT_THROW( Unimplemented_Feature );
       }
 
       decoder->psnames = psnames;
@@ -1599,7 +1605,7 @@
 
     decoder->funcs          = t1_decoder_funcs;
 
-    return PSaux_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
diff --git a/src/pshinter/pshalgo.c b/src/pshinter/pshalgo.c
index d798978..343472d 100644
--- a/src/pshinter/pshalgo.c
+++ b/src/pshinter/pshalgo.c
@@ -4,8 +4,7 @@
 /*                                                                         */
 /*    PostScript hinting algorithm (body).                                 */
 /*                                                                         */
-/*  Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010   */
-/*            by                                                           */
+/*  Copyright 2001-2010, 2012, 2013 by                                     */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used        */
@@ -402,13 +401,13 @@
                    FT_Fixed        delta,
                    FT_Int          dimension )
   {
-    PSH_Hint  hint;
-    FT_UInt   count;
+    FT_UInt  count;
 
 
     for ( count = 0; count < table->max_hints; count++ )
     {
-      hint = table->hints + count;
+      PSH_Hint  hint = table->hints + count;
+
 
       hint->cur_pos = FT_MulFix( hint->org_pos, scale ) + delta;
       hint->cur_len = FT_MulFix( hint->org_len, scale );
@@ -563,7 +562,7 @@
               else if ( len > 0 )
               {
                 /* This is a very small stem; we simply align it to the
-                 * pixel grid, trying to find the minimal displacement.
+                 * pixel grid, trying to find the minimum displacement.
                  *
                  * left               = pos
                  * right              = pos + len
@@ -1162,8 +1161,8 @@
     int     result = PSH_DIR_NONE;
 
 
-    ax = ( dx >= 0 ) ? dx : -dx;
-    ay = ( dy >= 0 ) ? dy : -dy;
+    ax = FT_ABS( dx );
+    ay = FT_ABS( dy );
 
     if ( ay * 12 < ax )
     {
@@ -2194,7 +2193,7 @@
 
     /* something to do? */
     if ( outline->n_points == 0 || outline->n_contours == 0 )
-      return PSH_Err_Ok;
+      return FT_Err_Ok;
 
 #ifdef DEBUG_HINTER
 
diff --git a/src/pshinter/pshalgo.h b/src/pshinter/pshalgo.h
index 1a248a7..c70f31e 100644
--- a/src/pshinter/pshalgo.h
+++ b/src/pshinter/pshalgo.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    PostScript hinting algorithm (specification).                        */
 /*                                                                         */
-/*  Copyright 2001, 2002, 2003, 2008 by                                    */
+/*  Copyright 2001-2003, 2008, 2013 by                                     */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -22,7 +22,6 @@
 
 #include "pshrec.h"
 #include "pshglob.h"
-#include FT_TRIGONOMETRY_H
 
 
 FT_BEGIN_HEADER
@@ -168,8 +167,6 @@
     FT_UInt      flags2;
     FT_Char      dir_in;
     FT_Char      dir_out;
-    FT_Angle     angle_in;
-    FT_Angle     angle_out;
     PSH_Hint     hint;
     FT_Pos       org_u;
     FT_Pos       org_v;
@@ -186,12 +183,6 @@
   } PSH_PointRec;
 
 
-#define PSH_POINT_EQUAL_ORG( a, b )  ( (a)->org_u == (b)->org_u && \
-                                       (a)->org_v == (b)->org_v )
-
-#define PSH_POINT_ANGLE( a, b )  FT_Atan2( (b)->org_u - (a)->org_u,  \
-                                           (b)->org_v - (a)->org_v )
-
   typedef struct  PSH_ContourRec_
   {
     PSH_Point  start;
diff --git a/src/pshinter/pshglob.c b/src/pshinter/pshglob.c
index 31231ad..9285efc 100644
--- a/src/pshinter/pshglob.c
+++ b/src/pshinter/pshglob.c
@@ -5,7 +5,7 @@
 /*    PostScript hinter global hinting management (body).                  */
 /*    Inspired by the new auto-hinter module.                              */
 /*                                                                         */
-/*  Copyright 2001, 2002, 2003, 2004, 2006, 2010 by                        */
+/*  Copyright 2001-2004, 2006, 2010, 2012 by                               */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used        */
@@ -522,6 +522,28 @@
   }
 
 
+  /* calculate the maximum height of given blue zones */
+  static FT_Short
+  psh_calc_max_height( FT_UInt          num,
+                       const FT_Short*  values,
+                       FT_Short         cur_max )
+  {
+    FT_UInt  count;
+
+
+    for ( count = 0; count < num; count += 2 )
+    {
+      FT_Short  cur_height = values[count + 1] - values[count];
+
+
+      if ( cur_height > cur_max )
+        cur_max = cur_height;
+    }
+
+    return cur_max;
+  }
+
+
   FT_LOCAL_DEF( void )
   psh_blues_snap_stem( PSH_Blues      blues,
                        FT_Int         stem_top,
@@ -684,7 +706,32 @@
                            priv->family_blues, priv->num_family_other_blues,
                            priv->family_other_blues, priv->blue_fuzz, 1 );
 
-      globals->blues.blue_scale = priv->blue_scale;
+      /* limit the BlueScale value to `1 / max_of_blue_zone_heights' */
+      {
+        FT_Fixed  max_scale;
+        FT_Short  max_height = 1;
+
+
+        max_height = psh_calc_max_height( priv->num_blue_values,
+                                          priv->blue_values,
+                                          max_height );
+        max_height = psh_calc_max_height( priv->num_other_blues,
+                                          priv->other_blues,
+                                          max_height );
+        max_height = psh_calc_max_height( priv->num_family_blues,
+                                          priv->family_blues,
+                                          max_height );
+        max_height = psh_calc_max_height( priv->num_family_other_blues,
+                                          priv->family_other_blues,
+                                          max_height );
+
+        /* BlueScale is scaled 1000 times */
+        max_scale = FT_DivFix( 1000, max_height );
+        globals->blues.blue_scale = priv->blue_scale < max_scale
+                                      ? priv->blue_scale
+                                      : max_scale;
+      }
+
       globals->blues.blue_shift = priv->blue_shift;
       globals->blues.blue_fuzz  = priv->blue_fuzz;
 
diff --git a/src/pshinter/pshmod.c b/src/pshinter/pshmod.c
index 91da5d7..cdeaca1 100644
--- a/src/pshinter/pshmod.c
+++ b/src/pshinter/pshmod.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType PostScript hinter module implementation (body).             */
 /*                                                                         */
-/*  Copyright 2001, 2002, 2007 by                                          */
+/*  Copyright 2001, 2002, 2007, 2009, 2012 by                              */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -93,14 +93,15 @@
   }
 
 
-  FT_DEFINE_PSHINTER_INTERFACE(pshinter_interface,
+  FT_DEFINE_PSHINTER_INTERFACE(
+    pshinter_interface,
     pshinter_get_globals_funcs,
     pshinter_get_t1_funcs,
-    pshinter_get_t2_funcs
-  )
+    pshinter_get_t2_funcs )
 
 
-  FT_DEFINE_MODULE(pshinter_module_class,
+  FT_DEFINE_MODULE(
+    pshinter_module_class,
 
     0,
     sizeof ( PS_Hinter_ModuleRec ),
@@ -108,11 +109,11 @@
     0x10000L,
     0x20000L,
 
-    &FTPSHINTER_INTERFACE_GET,            /* module-specific interface */
+    &PSHINTER_INTERFACE_GET,              /* module-specific interface */
 
     (FT_Module_Constructor)ps_hinter_init,
     (FT_Module_Destructor) ps_hinter_done,
-    (FT_Module_Requester)  0        /* no additional interface for now */
-  )
+    (FT_Module_Requester)  NULL )   /* no additional interface for now */
+
 
 /* END */
diff --git a/src/pshinter/pshpic.c b/src/pshinter/pshpic.c
index 1e0f9a9..568f4ac 100644
--- a/src/pshinter/pshpic.c
+++ b/src/pshinter/pshpic.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType position independent code services for pshinter module. */
 /*                                                                         */
-/*  Copyright 2009, 2010 by                                                */
+/*  Copyright 2009, 2010, 2012, 2013 by                                    */
 /*  Oran Agra and Mickey Gabel.                                            */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -22,6 +22,7 @@
 #include "pshpic.h"
 #include "pshnterr.h"
 
+
 #ifdef FT_CONFIG_OPTION_PIC
 
   /* forward declaration of PIC init functions from pshmod.c */
@@ -33,7 +34,7 @@
   pshinter_module_class_pic_free( FT_Library  library )
   {
     FT_PIC_Container*  pic_container = &library->pic_container;
-    FT_Memory  memory = library->memory;
+    FT_Memory          memory        = library->memory;
 
 
     if ( pic_container->pshinter )
@@ -48,13 +49,13 @@
   pshinter_module_class_pic_init( FT_Library  library )
   {
     FT_PIC_Container*  pic_container = &library->pic_container;
-    FT_Error           error         = PSH_Err_Ok;
-    PSHinterPIC*       container;
+    FT_Error           error         = FT_Err_Ok;
+    PSHinterPIC*       container     = NULL;
     FT_Memory          memory        = library->memory;
 
 
     /* allocate pointer, clear and set global container pointer */
-    if ( FT_ALLOC ( container, sizeof ( *container ) ) )
+    if ( FT_ALLOC( container, sizeof ( *container ) ) )
       return error;
     FT_MEM_SET( container, 0, sizeof ( *container ) );
     pic_container->pshinter = container;
@@ -63,13 +64,13 @@
     FT_Init_Class_pshinter_interface(
       library, &container->pshinter_interface );
 
-/*Exit:*/
-    if( error )
+    if ( error )
       pshinter_module_class_pic_free( library );
+
     return error;
   }
 
-
 #endif /* FT_CONFIG_OPTION_PIC */
 
+
 /* END */
diff --git a/src/pshinter/pshpic.h b/src/pshinter/pshpic.h
index c10bdd9..b46f853 100644
--- a/src/pshinter/pshpic.h
+++ b/src/pshinter/pshpic.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType position independent code services for pshinter module. */
 /*                                                                         */
-/*  Copyright 2009 by                                                      */
+/*  Copyright 2009, 2012, 2013 by                                          */
 /*  Oran Agra and Mickey Gabel.                                            */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -24,21 +24,25 @@
 
 #include FT_INTERNAL_PIC_H
 
+
 #ifndef FT_CONFIG_OPTION_PIC
 
-#define FTPSHINTER_INTERFACE_GET        pshinter_interface
+#define PSHINTER_INTERFACE_GET  pshinter_interface
 
 #else /* FT_CONFIG_OPTION_PIC */
 
 #include FT_INTERNAL_POSTSCRIPT_HINTS_H
 
-  typedef struct PSHinterPIC_
+  typedef struct  PSHinterPIC_
   {
-    PSHinter_Interface pshinter_interface;
+    PSHinter_Interface  pshinter_interface;
+
   } PSHinterPIC;
 
-#define GET_PIC(lib)                    ((PSHinterPIC*)((lib)->pic_container.autofit))
-#define FTPSHINTER_INTERFACE_GET        (GET_PIC(library)->pshinter_interface)
+
+#define GET_PIC( lib )  ( (PSHinterPIC*)( (lib)->pic_container.pshinter ) )
+
+#define PSHINTER_INTERFACE_GET  ( GET_PIC( library )->pshinter_interface )
 
   /* see pshpic.c for the implementation */
   void
diff --git a/src/pshinter/pshrec.c b/src/pshinter/pshrec.c
index 0910cc5..cd66ea8 100644
--- a/src/pshinter/pshrec.c
+++ b/src/pshinter/pshrec.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType PostScript hints recorder (body).                           */
 /*                                                                         */
-/*  Copyright 2001, 2002, 2003, 2004, 2007, 2009 by                        */
+/*  Copyright 2001-2004, 2007, 2009, 2013 by                               */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -64,7 +64,7 @@
   {
     FT_UInt   old_max = table->max_hints;
     FT_UInt   new_max = count;
-    FT_Error  error   = PSH_Err_Ok;
+    FT_Error  error   = FT_Err_Ok;
 
 
     if ( new_max > old_max )
@@ -83,7 +83,7 @@
                        FT_Memory      memory,
                        PS_Hint       *ahint )
   {
-    FT_Error  error = PSH_Err_Ok;
+    FT_Error  error = FT_Err_Ok;
     FT_UInt   count;
     PS_Hint   hint = 0;
 
@@ -139,7 +139,7 @@
   {
     FT_UInt   old_max = ( mask->max_bits + 7 ) >> 3;
     FT_UInt   new_max = ( count          + 7 ) >> 3;
-    FT_Error  error   = PSH_Err_Ok;
+    FT_Error  error   = FT_Err_Ok;
 
 
     if ( new_max > old_max )
@@ -186,7 +186,7 @@
                    FT_Int     idx,
                    FT_Memory  memory )
   {
-    FT_Error  error = PSH_Err_Ok;
+    FT_Error  error = FT_Err_Ok;
     FT_Byte*  p;
 
 
@@ -236,7 +236,7 @@
   {
     FT_UInt   old_max = table->max_masks;
     FT_UInt   new_max = count;
-    FT_Error  error   = PSH_Err_Ok;
+    FT_Error  error   = FT_Err_Ok;
 
 
     if ( new_max > old_max )
@@ -256,7 +256,7 @@
                        PS_Mask       *amask )
   {
     FT_UInt   count;
-    FT_Error  error = PSH_Err_Ok;
+    FT_Error  error = FT_Err_Ok;
     PS_Mask   mask  = 0;
 
 
@@ -287,7 +287,7 @@
                       FT_Memory      memory,
                       PS_Mask       *amask )
   {
-    FT_Error  error = PSH_Err_Ok;
+    FT_Error  error = FT_Err_Ok;
     FT_UInt   count;
     PS_Mask   mask;
 
@@ -316,7 +316,7 @@
                           FT_UInt         bit_count,
                           FT_Memory       memory )
   {
-    FT_Error  error = PSH_Err_Ok;
+    FT_Error  error;
     PS_Mask   mask;
 
 
@@ -384,7 +384,7 @@
     FT_UInt   count;
 
 
-    count = ( count1 <= count2 ) ? count1 : count2;
+    count = FT_MIN( count1, count2 );
     for ( ; count >= 8; count -= 8 )
     {
       if ( p1[0] & p2[0] )
@@ -409,7 +409,7 @@
                        FT_Memory      memory )
   {
     FT_UInt   temp;
-    FT_Error  error = PSH_Err_Ok;
+    FT_Error  error = FT_Err_Ok;
 
 
     /* swap index1 and index2 so that index1 < index2 */
@@ -499,7 +499,7 @@
                            FT_Memory      memory )
   {
     FT_Int    index1, index2;
-    FT_Error  error = PSH_Err_Ok;
+    FT_Error  error = FT_Err_Ok;
 
 
     for ( index1 = table->num_masks - 1; index1 > 0; index1-- )
@@ -561,7 +561,7 @@
                              FT_Memory     memory )
   {
     PS_Mask   mask;
-    FT_Error  error = PSH_Err_Ok;
+    FT_Error  error = FT_Err_Ok;
 
 
     /* get last hint mask */
@@ -583,12 +583,13 @@
                          FT_UInt       end_point )
   {
     FT_UInt  count = dim->masks.num_masks;
-    PS_Mask  mask;
 
 
     if ( count > 0 )
     {
-      mask            = dim->masks.masks + count - 1;
+      PS_Mask  mask = dim->masks.masks + count - 1;
+
+
       mask->end_point = end_point;
     }
   }
@@ -621,7 +622,7 @@
                               FT_UInt         end_point,
                               FT_Memory       memory )
   {
-    FT_Error  error = PSH_Err_Ok;
+    FT_Error  error;
 
 
     /* reset current mask, if any */
@@ -646,7 +647,7 @@
                            FT_Memory     memory,
                            FT_Int       *aindex )
   {
-    FT_Error  error = PSH_Err_Ok;
+    FT_Error  error = FT_Err_Ok;
     FT_UInt   flags = 0;
 
 
@@ -717,7 +718,7 @@
                             FT_Int        hint3,
                             FT_Memory     memory )
   {
-    FT_Error  error   = PSH_Err_Ok;
+    FT_Error  error   = FT_Err_Ok;
     FT_UInt   count   = dim->counters.num_masks;
     PS_Mask   counter = dim->counters.masks;
 
@@ -791,7 +792,7 @@
     ps_dimension_done( &hints->dimension[0], memory );
     ps_dimension_done( &hints->dimension[1], memory );
 
-    hints->error  = PSH_Err_Ok;
+    hints->error  = FT_Err_Ok;
     hints->memory = 0;
   }
 
@@ -802,7 +803,7 @@
   {
     FT_MEM_ZERO( hints, sizeof ( *hints ) );
     hints->memory = memory;
-    return PSH_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
@@ -815,7 +816,7 @@
     {
     case PS_HINT_TYPE_1:
     case PS_HINT_TYPE_2:
-      hints->error     = PSH_Err_Ok;
+      hints->error     = FT_Err_Ok;
       hints->hint_type = hint_type;
 
       ps_dimension_init( &hints->dimension[0] );
@@ -823,7 +824,7 @@
       break;
 
     default:
-      hints->error     = PSH_Err_Invalid_Argument;
+      hints->error     = FT_THROW( Invalid_Argument );
       hints->hint_type = hint_type;
 
       FT_TRACE0(( "ps_hints_open: invalid charstring type\n" ));
@@ -894,7 +895,7 @@
                     FT_Int     dimension,
                     FT_Fixed*  stems )
   {
-    FT_Error  error = PSH_Err_Ok;
+    FT_Error  error = FT_Err_Ok;
 
 
     if ( !hints->error )
@@ -938,7 +939,7 @@
       else
       {
         FT_ERROR(( "ps_hints_t1stem3: called with invalid hint type\n" ));
-        error = PSH_Err_Invalid_Argument;
+        error = FT_THROW( Invalid_Argument );
         goto Fail;
       }
     }
@@ -956,7 +957,7 @@
   ps_hints_t1reset( PS_Hints  hints,
                     FT_UInt   end_point )
   {
-    FT_Error  error = PSH_Err_Ok;
+    FT_Error  error = FT_Err_Ok;
 
 
     if ( !hints->error )
@@ -979,7 +980,7 @@
       else
       {
         /* invalid hint type */
-        error = PSH_Err_Invalid_Argument;
+        error = FT_THROW( Invalid_Argument );
         goto Fail;
       }
     }
diff --git a/src/psnames/psmodule.c b/src/psnames/psmodule.c
index 3619174..0a5bcb7 100644
--- a/src/psnames/psmodule.c
+++ b/src/psnames/psmodule.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    PSNames module implementation (body).                                */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003, 2005, 2006, 2007, 2008 by             */
+/*  Copyright 1996-2003, 2005-2008, 2012, 2013 by                          */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -17,6 +17,7 @@
 
 
 #include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
 #include FT_INTERNAL_OBJECTS_H
 #include FT_SERVICE_POSTSCRIPT_CMAPS_H
 
@@ -369,7 +370,7 @@
         /* No unicode chars here! */
         FT_FREE( table->maps );
         if ( !error )
-          error = PSnames_Err_No_Unicode_Glyph_Name;
+          error = FT_THROW( No_Unicode_Glyph_Name );
       }
       else
       {
@@ -377,7 +378,7 @@
         if ( count < num_glyphs / 2 )
         {
           (void)FT_RENEW_ARRAY( table->maps, num_glyphs, count );
-          error = PSnames_Err_Ok;
+          error = FT_Err_Ok;
         }
 
         /* Sort the table in increasing order of unicode values, */
@@ -521,7 +522,9 @@
 
 
 #ifdef FT_CONFIG_OPTION_ADOBE_GLYPH_LIST
-  FT_DEFINE_SERVICE_PSCMAPSREC(pscmaps_interface,
+
+  FT_DEFINE_SERVICE_PSCMAPSREC(
+    pscmaps_interface,
     (PS_Unicode_ValueFunc)     ps_unicode_value,
     (PS_Unicodes_InitFunc)     ps_unicodes_init,
     (PS_Unicodes_CharIndexFunc)ps_unicodes_char_index,
@@ -531,39 +534,36 @@
     (PS_Adobe_Std_StringsFunc) ps_get_standard_strings,
 
     t1_standard_encoding,
-    t1_expert_encoding
-  )
+    t1_expert_encoding )
 
 #else
 
-  FT_DEFINE_SERVICE_PSCMAPSREC(pscmaps_interface,
-    0,
-    0,
-    0,
-    0,
+  FT_DEFINE_SERVICE_PSCMAPSREC(
+    pscmaps_interface,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
 
     (PS_Macintosh_NameFunc)    ps_get_macintosh_name,
     (PS_Adobe_Std_StringsFunc) ps_get_standard_strings,
 
     t1_standard_encoding,
-    t1_expert_encoding
-  )
+    t1_expert_encoding )
 
 #endif /* FT_CONFIG_OPTION_ADOBE_GLYPH_LIST */
 
 
-  FT_DEFINE_SERVICEDESCREC1(pscmaps_services,
-    FT_SERVICE_ID_POSTSCRIPT_CMAPS, &FT_PSCMAPS_INTERFACE_GET
-  )
-
-
+  FT_DEFINE_SERVICEDESCREC1(
+    pscmaps_services,
+    FT_SERVICE_ID_POSTSCRIPT_CMAPS, &PSCMAPS_INTERFACE_GET )
 
 
   static FT_Pointer
   psnames_get_service( FT_Module    module,
                        const char*  service_id )
   {
-    /* FT_PSCMAPS_SERVICES_GET derefers `library' in PIC mode */
+    /* PSCMAPS_SERVICES_GET derefers `library' in PIC mode */
 #ifdef FT_CONFIG_OPTION_PIC
     FT_Library  library;
 
@@ -577,19 +577,20 @@
     FT_UNUSED( module );
 #endif
 
-    return ft_service_list_lookup( FT_PSCMAPS_SERVICES_GET, service_id );
+    return ft_service_list_lookup( PSCMAPS_SERVICES_GET, service_id );
   }
 
 #endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */
 
 
 #ifndef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
-#define PUT_PS_NAMES_SERVICE(a) 0
+#define PUT_PS_NAMES_SERVICE( a )  NULL
 #else
-#define PUT_PS_NAMES_SERVICE(a) a
+#define PUT_PS_NAMES_SERVICE( a )  a
 #endif
 
-  FT_DEFINE_MODULE(psnames_module_class,
+  FT_DEFINE_MODULE(
+    psnames_module_class,
 
     0,  /* this is not a font driver, nor a renderer */
     sizeof ( FT_ModuleRec ),
@@ -598,12 +599,11 @@
     0x10000L,   /* driver version                      */
     0x20000L,   /* driver requires FreeType 2 or above */
 
-    PUT_PS_NAMES_SERVICE((void*)&FT_PSCMAPS_INTERFACE_GET),   /* module specific interface */
-    (FT_Module_Constructor)0,
-    (FT_Module_Destructor) 0,
-    (FT_Module_Requester)  PUT_PS_NAMES_SERVICE(psnames_get_service)
-  )
-
+    PUT_PS_NAMES_SERVICE(
+      (void*)&PSCMAPS_INTERFACE_GET ),   /* module specific interface */
+    (FT_Module_Constructor)NULL,
+    (FT_Module_Destructor) NULL,
+    (FT_Module_Requester)  PUT_PS_NAMES_SERVICE( psnames_get_service ) )
 
 
 /* END */
diff --git a/src/psnames/pspic.c b/src/psnames/pspic.c
index 467ab73..3820f65 100644
--- a/src/psnames/pspic.c
+++ b/src/psnames/pspic.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType position independent code services for psnames module.  */
 /*                                                                         */
-/*  Copyright 2009, 2010 by                                                */
+/*  Copyright 2009, 2010, 2012, 2013 by                                    */
 /*  Oran Agra and Mickey Gabel.                                            */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -22,6 +22,7 @@
 #include "pspic.h"
 #include "psnamerr.h"
 
+
 #ifdef FT_CONFIG_OPTION_PIC
 
   /* forward declaration of PIC init functions from psmodule.c */
@@ -36,11 +37,12 @@
   FT_Init_Class_pscmaps_interface( FT_Library              library,
                                    FT_Service_PsCMapsRec*  clazz );
 
+
   void
   psnames_module_class_pic_free( FT_Library  library )
   {
     FT_PIC_Container*  pic_container = &library->pic_container;
-    FT_Memory  memory = library->memory;
+    FT_Memory          memory        = library->memory;
 
 
     if ( pic_container->psnames )
@@ -48,7 +50,7 @@
       PSModulePIC*  container = (PSModulePIC*)pic_container->psnames;
 
 
-      if(container->pscmaps_services)
+      if ( container->pscmaps_services )
         FT_Destroy_Class_pscmaps_services( library,
                                            container->pscmaps_services );
       container->pscmaps_services = NULL;
@@ -62,18 +64,19 @@
   psnames_module_class_pic_init( FT_Library  library )
   {
     FT_PIC_Container*  pic_container = &library->pic_container;
-    FT_Error           error         = PSnames_Err_Ok;
-    PSModulePIC*       container;
+    FT_Error           error         = FT_Err_Ok;
+    PSModulePIC*       container     = NULL;
     FT_Memory          memory        = library->memory;
 
 
     /* allocate pointer, clear and set global container pointer */
-    if ( FT_ALLOC ( container, sizeof ( *container ) ) )
+    if ( FT_ALLOC( container, sizeof ( *container ) ) )
       return error;
     FT_MEM_SET( container, 0, sizeof ( *container ) );
     pic_container->psnames = container;
 
-    /* initialize pointer table - this is how the module usually expects this data */
+    /* initialize pointer table -                       */
+    /* this is how the module usually expects this data */
     error = FT_Create_Class_pscmaps_services(
               library, &container->pscmaps_services );
     if ( error )
@@ -81,7 +84,7 @@
     FT_Init_Class_pscmaps_interface( library,
                                      &container->pscmaps_interface );
 
-Exit:
+  Exit:
     if ( error )
       psnames_module_class_pic_free( library );
     return error;
diff --git a/src/psnames/pspic.h b/src/psnames/pspic.h
index 1169b89..6ff002c 100644
--- a/src/psnames/pspic.h
+++ b/src/psnames/pspic.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType position independent code services for psnames module.  */
 /*                                                                         */
-/*  Copyright 2009 by                                                      */
+/*  Copyright 2009, 2012 by                                                */
 /*  Oran Agra and Mickey Gabel.                                            */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -25,22 +25,27 @@
 #include FT_INTERNAL_PIC_H
 
 #ifndef FT_CONFIG_OPTION_PIC
-#define FT_PSCMAPS_SERVICES_GET     pscmaps_services
-#define FT_PSCMAPS_INTERFACE_GET    pscmaps_interface
+
+#define PSCMAPS_SERVICES_GET   pscmaps_services
+#define PSCMAPS_INTERFACE_GET  pscmaps_interface
 
 #else /* FT_CONFIG_OPTION_PIC */
 
 #include FT_SERVICE_POSTSCRIPT_CMAPS_H
 
-  typedef struct PSModulePIC_
+  typedef struct  PSModulePIC_
   {
-    FT_ServiceDescRec* pscmaps_services;
-    FT_Service_PsCMapsRec pscmaps_interface;
+    FT_ServiceDescRec*     pscmaps_services;
+    FT_Service_PsCMapsRec  pscmaps_interface;
+
   } PSModulePIC;
 
-#define GET_PIC(lib)                ((PSModulePIC*)((lib)->pic_container.psnames))
-#define FT_PSCMAPS_SERVICES_GET     (GET_PIC(library)->pscmaps_services)
-#define FT_PSCMAPS_INTERFACE_GET    (GET_PIC(library)->pscmaps_interface)
+
+#define GET_PIC( lib )                                     \
+          ( (PSModulePIC*)((lib)->pic_container.psnames) )
+#define PSCMAPS_SERVICES_GET   ( GET_PIC( library )->pscmaps_services )
+#define PSCMAPS_INTERFACE_GET  ( GET_PIC( library )->pscmaps_interface )
+
 
   /* see pspic.c for the implementation */
   void
diff --git a/src/raster/ftmisc.h b/src/raster/ftmisc.h
index 7773924..703155a 100644
--- a/src/raster/ftmisc.h
+++ b/src/raster/ftmisc.h
@@ -115,6 +115,27 @@
     return ( s > 0 ) ? d : -d;
   }
 
+
+  static FT_Long
+  FT_MulDiv_No_Round( FT_Long  a,
+                      FT_Long  b,
+                      FT_Long  c )
+  {
+    FT_Int   s;
+    FT_Long  d;
+
+
+    s = 1;
+    if ( a < 0 ) { a = -a; s = -1; }
+    if ( b < 0 ) { b = -b; s = -s; }
+    if ( c < 0 ) { c = -c; s = -s; }
+
+    d = (FT_Long)( c > 0 ? (FT_Int64)a * b / c
+                         : 0x7FFFFFFFL );
+
+    return ( s > 0 ) ? d : -d;
+  }
+
 #endif /* __FTMISC_H__ */
 
 
diff --git a/src/raster/ftraster.c b/src/raster/ftraster.c
index f85845e..4865994 100644
--- a/src/raster/ftraster.c
+++ b/src/raster/ftraster.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType glyph rasterizer (body).                                */
 /*                                                                         */
-/*  Copyright 1996-2003, 2005, 2007-2012 by                                */
+/*  Copyright 1996-2003, 2005, 2007-2013 by                                */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -60,7 +60,7 @@
 
 #include <ft2build.h>
 #include "ftraster.h"
-#include FT_INTERNAL_CALC_H   /* for FT_MulDiv only */
+#include FT_INTERNAL_CALC_H   /* for FT_MulDiv and FT_MulDiv_No_Round */
 
 #include "rastpic.h"
 
@@ -179,6 +179,9 @@
 
 #ifdef _STANDALONE_
 
+  /* Auxiliary macros for token concatenation. */
+#define FT_ERR_XCAT( x, y )  x ## y
+#define FT_ERR_CAT( x, y )   FT_ERR_XCAT( x, y )
 
   /* This macro is used to indicate that a function parameter is unused. */
   /* Its purpose is simply to reduce compiler warnings.  Note also that  */
@@ -187,7 +190,7 @@
 #define FT_UNUSED( x )  (x) = (x)
 
   /* Disable the tracing mechanism for simplicity -- developers can      */
-  /* activate it easily by redefining these two macros.                  */
+  /* activate it easily by redefining these macros.                      */
 #ifndef FT_ERROR
 #define FT_ERROR( x )  do { } while ( 0 )     /* nothing */
 #endif
@@ -198,6 +201,10 @@
 #define FT_TRACE6( x )  do { } while ( 0 )    /* nothing */
 #endif
 
+#ifndef FT_THROW
+#define FT_THROW( e )  FT_ERR_CAT( Raster_Err_, e )
+#endif
+
 #define Raster_Err_None          0
 #define Raster_Err_Not_Ini      -1
 #define Raster_Err_Overflow     -2
@@ -224,11 +231,11 @@
 
 
 #include FT_INTERNAL_OBJECTS_H
-#include FT_INTERNAL_DEBUG_H        /* for FT_TRACE() and FT_ERROR() */
+#include FT_INTERNAL_DEBUG_H       /* for FT_TRACE, FT_ERROR, and FT_THROW */
 
 #include "rasterrs.h"
 
-#define Raster_Err_None         Raster_Err_Ok
+#define Raster_Err_None         FT_Err_Ok
 #define Raster_Err_Not_Ini      Raster_Err_Raster_Uninitialized
 #define Raster_Err_Overflow     Raster_Err_Raster_Overflow
 #define Raster_Err_Neg_Height   Raster_Err_Raster_Negative_Height
@@ -255,7 +262,8 @@
   /* On the other hand, SMulDiv means `Slow MulDiv', and is used typically */
   /* for clipping computations.  It simply uses the FT_MulDiv() function   */
   /* defined in `ftcalc.h'.                                                */
-#define SMulDiv  FT_MulDiv
+#define SMulDiv           FT_MulDiv
+#define SMulDiv_No_Round  FT_MulDiv_No_Round
 
   /* The rasterizer is a very general purpose component; please leave */
   /* the following redefinitions there (you never know your target    */
@@ -302,6 +310,7 @@
   typedef short           Short;
   typedef unsigned short  UShort, *PUShort;
   typedef long            Long, *PLong;
+  typedef unsigned long   ULong;
 
   typedef unsigned char   Byte, *PByte;
   typedef char            Bool;
@@ -440,9 +449,9 @@
 
 #define FLOOR( x )    ( (x) & -ras.precision )
 #define CEILING( x )  ( ( (x) + ras.precision - 1 ) & -ras.precision )
-#define TRUNC( x )    ( (signed long)(x) >> ras.precision_bits )
+#define TRUNC( x )    ( (Long)(x) >> ras.precision_bits )
 #define FRAC( x )     ( (x) & ( ras.precision - 1 ) )
-#define SCALED( x )   ( ( (x) << ras.scale_shift ) - ras.precision_half )
+#define SCALED( x )   ( ( (ULong)(x) << ras.scale_shift ) - ras.precision_half )
 
 #define IS_BOTTOM_OVERSHOOT( x )  ( CEILING( x ) - x >= ras.precision_half )
 #define IS_TOP_OVERSHOOT( x )     ( x - FLOOR( x ) >= ras.precision_half )
@@ -654,7 +663,7 @@
   /*    Set precision variables according to param flag.                   */
   /*                                                                       */
   /* <Input>                                                               */
-  /*    High :: Set to True for high precision (typically for ppem < 18),  */
+  /*    High :: Set to True for high precision (typically for ppem < 24),  */
   /*            false otherwise.                                           */
   /*                                                                       */
   static void
@@ -734,7 +743,7 @@
 
     if ( ras.top >= ras.maxBuff )
     {
-      ras.error = Raster_Err_Overflow;
+      ras.error = FT_THROW( Overflow );
       return FAILURE;
     }
 
@@ -764,7 +773,7 @@
 
     default:
       FT_ERROR(( "New_Profile: invalid profile direction\n" ));
-      ras.error = Raster_Err_Invalid;
+      ras.error = FT_THROW( Invalid );
       return FAILURE;
     }
 
@@ -797,8 +806,7 @@
   static Bool
   End_Profile( RAS_ARGS Bool  overshoot )
   {
-    Long      h;
-    PProfile  oldProfile;
+    Long  h;
 
 
     h = (Long)( ras.top - ras.cProfile->offset );
@@ -806,12 +814,15 @@
     if ( h < 0 )
     {
       FT_ERROR(( "End_Profile: negative height encountered\n" ));
-      ras.error = Raster_Err_Neg_Height;
+      ras.error = FT_THROW( Neg_Height );
       return FAILURE;
     }
 
     if ( h > 0 )
     {
+      PProfile  oldProfile;
+
+
       FT_TRACE6(( "Ending profile %p, start = %ld, height = %ld\n",
                   ras.cProfile, ras.cProfile->start, h ));
 
@@ -839,7 +850,7 @@
     if ( ras.top >= ras.maxBuff )
     {
       FT_TRACE1(( "overflow in End_Profile\n" ));
-      ras.error = Raster_Err_Overflow;
+      ras.error = FT_THROW( Overflow );
       return FAILURE;
     }
 
@@ -868,7 +879,7 @@
   Insert_Y_Turn( RAS_ARGS Int  y )
   {
     PLong  y_turns;
-    Int    y2, n;
+    Int    n;
 
 
     n       = ras.numTurns - 1;
@@ -882,7 +893,9 @@
     if ( n >= 0 && y > y_turns[n] )
       while ( n >= 0 )
       {
-        y2 = (Int)y_turns[n];
+        Int  y2 = (Int)y_turns[n];
+
+
         y_turns[n] = y;
         y = y2;
         n--;
@@ -893,7 +906,7 @@
       ras.maxBuff--;
       if ( ras.maxBuff <= ras.top )
       {
-        ras.error = Raster_Err_Overflow;
+        ras.error = FT_THROW( Overflow );
         return FAILURE;
       }
       ras.numTurns++;
@@ -918,7 +931,6 @@
   static Bool
   Finalize_Profile_Table( RAS_ARG )
   {
-    Int       bottom, top;
     UShort    n;
     PProfile  p;
 
@@ -930,6 +942,9 @@
     {
       while ( n > 0 )
       {
+        Int  bottom, top;
+
+
         if ( n > 1 )
           p->link = (PProfile)( p->offset + p->height );
         else
@@ -1144,20 +1159,20 @@
     size = e2 - e1 + 1;
     if ( ras.top + size >= ras.maxBuff )
     {
-      ras.error = Raster_Err_Overflow;
+      ras.error = FT_THROW( Overflow );
       return FAILURE;
     }
 
     if ( Dx > 0 )
     {
-      Ix = SMulDiv( ras.precision, Dx, Dy);
+      Ix = SMulDiv_No_Round( ras.precision, Dx, Dy );
       Rx = ( ras.precision * Dx ) % Dy;
       Dx = 1;
     }
     else
     {
-      Ix = SMulDiv( ras.precision, -Dx, Dy) * -1;
-      Rx =    ( ras.precision * -Dx ) % Dy;
+      Ix = -SMulDiv_No_Round( ras.precision, -Dx, Dy );
+      Rx = ( ras.precision * -Dx ) % Dy;
       Dx = -1;
     }
 
@@ -1319,7 +1334,7 @@
     if ( ( top + TRUNC( e2 - e ) + 1 ) >= ras.maxBuff )
     {
       ras.top   = top;
-      ras.error = Raster_Err_Overflow;
+      ras.error = FT_THROW( Overflow );
       return FAILURE;
     }
 
@@ -1994,7 +2009,7 @@
     return SUCCESS;
 
   Invalid_Outline:
-    ras.error = Raster_Err_Invalid;
+    ras.error = FT_THROW( Invalid );
 
   Fail:
     return FAILURE;
@@ -2023,8 +2038,6 @@
     int       i;
     unsigned  start;
 
-    PProfile  lastProfile;
-
 
     ras.fProfile = NULL;
     ras.joint    = FALSE;
@@ -2042,7 +2055,8 @@
 
     for ( i = 0; i < ras.outline.n_contours; i++ )
     {
-      Bool  o;
+      PProfile  lastProfile;
+      Bool      o;
 
 
       ras.state    = Unknown_State;
@@ -2266,8 +2280,6 @@
                                 PProfile    right )
   {
     Long   e1, e2;
-    int    c1, c2;
-    Byte   f1, f2;
     Byte*  target;
 
     FT_UNUSED( y );
@@ -2286,6 +2298,10 @@
 
     if ( e2 >= 0 && e1 < ras.bWidth )
     {
+      int   c1, c2;
+      Byte  f1, f2;
+
+
       if ( e1 < 0 )
         e1 = 0;
       if ( e2 >= ras.bWidth )
@@ -2509,21 +2525,24 @@
                                   PProfile    left,
                                   PProfile    right )
   {
-    Long   e1, e2;
-    PByte  bits;
-    Byte   f1;
-
     FT_UNUSED( left );
     FT_UNUSED( right );
 
 
     if ( x2 - x1 < ras.precision )
     {
+      Long  e1, e2;
+
+
       e1 = CEILING( x1 );
       e2 = FLOOR  ( x2 );
 
       if ( e1 == e2 )
       {
+        Byte   f1;
+        PByte  bits;
+
+
         bits = ras.bTarget + ( y >> 3 );
         f1   = (Byte)( 0x80 >> ( y & 7 ) );
 
@@ -2720,8 +2739,6 @@
   static void
   Vertical_Gray_Sweep_Step( RAS_ARG )
   {
-    Int     c1, c2;
-    PByte   pix, bit, bit2;
     short*  count = (short*)count_table;
     Byte*   grays;
 
@@ -2730,6 +2747,9 @@
 
     if ( ras.traceOfs > ras.gray_width )
     {
+      PByte  pix;
+
+
       pix   = ras.gTarget + ras.traceG + ras.gray_min_x * 4;
       grays = ras.grays;
 
@@ -2740,6 +2760,9 @@
         Int   last_bit   = last_pixel & 3;
         Bool  over       = 0;
 
+        Int    c1, c2;
+        PByte  bit, bit2;
+
 
         if ( ras.gray_max_x >= last_cell && last_bit != 3 )
         {
@@ -2832,7 +2855,6 @@
   {
     Long   e1, e2;
     PByte  pixel;
-    Byte   color;
 
 
     /* During the horizontal sweep, we only take care of drop-outs */
@@ -2886,6 +2908,9 @@
 
     if ( e1 >= 0 )
     {
+      Byte  color;
+
+
       if ( x2 - x1 >= ras.precision_half )
         color = ras.grays[2];
       else
@@ -2963,7 +2988,7 @@
     /* check the Y-turns */
     if ( ras.numTurns == 0 )
     {
-      ras.error = Raster_Err_Invalid;
+      ras.error = FT_THROW( Invalid );
       return FAILURE;
     }
 
@@ -3204,7 +3229,7 @@
         if ( ras.band_top >= 7 || k < i )
         {
           ras.band_top = 0;
-          ras.error    = Raster_Err_Invalid;
+          ras.error    = FT_THROW( Invalid );
 
           return ras.error;
         }
@@ -3393,7 +3418,7 @@
   {
     FT_UNUSED_RASTER;
 
-    return Raster_Err_Unsupported;
+    return FT_THROW( Unsupported );
   }
 
 #endif /* !FT_RASTER_OPTION_ANTI_ALIASING */
@@ -3498,7 +3523,8 @@
 
 
         raster->buffer      = pool_base + ( ( sizeof ( *worker ) + 7 ) & ~7 );
-        raster->buffer_size = pool_base + pool_size - (char*)raster->buffer;
+        raster->buffer_size = (long)( pool_base + pool_size -
+                                        (char*)raster->buffer );
         raster->worker      = worker;
       }
       else
@@ -3548,37 +3574,37 @@
 
 
     if ( !raster || !raster->buffer || !raster->buffer_size )
-      return Raster_Err_Not_Ini;
+      return FT_THROW( Not_Ini );
 
     if ( !outline )
-      return Raster_Err_Invalid;
+      return FT_THROW( Invalid );
 
     /* return immediately if the outline is empty */
     if ( outline->n_points == 0 || outline->n_contours <= 0 )
       return Raster_Err_None;
 
     if ( !outline->contours || !outline->points )
-      return Raster_Err_Invalid;
+      return FT_THROW( Invalid );
 
     if ( outline->n_points !=
            outline->contours[outline->n_contours - 1] + 1 )
-      return Raster_Err_Invalid;
+      return FT_THROW( Invalid );
 
     worker = raster->worker;
 
     /* this version of the raster does not support direct rendering, sorry */
     if ( params->flags & FT_RASTER_FLAG_DIRECT )
-      return Raster_Err_Unsupported;
+      return FT_THROW( Unsupported );
 
     if ( !target_map )
-      return Raster_Err_Invalid;
+      return FT_THROW( Invalid );
 
     /* nothing to do */
     if ( !target_map->width || !target_map->rows )
       return Raster_Err_None;
 
     if ( !target_map->buffer )
-      return Raster_Err_Invalid;
+      return FT_THROW( Invalid );
 
     ras.outline = *outline;
     ras.target  = *target_map;
diff --git a/src/raster/ftrend1.c b/src/raster/ftrend1.c
index 859cb7d..aa7f6d5 100644
--- a/src/raster/ftrend1.c
+++ b/src/raster/ftrend1.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType glyph rasterizer interface (body).                      */
 /*                                                                         */
-/*  Copyright 1996-2003, 2005, 2006, 2011 by                               */
+/*  Copyright 1996-2003, 2005, 2006, 2011, 2013 by                         */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -17,6 +17,7 @@
 
 
 #include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
 #include FT_INTERNAL_OBJECTS_H
 #include FT_OUTLINE_H
 #include "ftrend1.h"
@@ -37,7 +38,7 @@
                                                library->raster_pool,
                                                library->raster_pool_size );
 
-    return Raster_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
@@ -61,12 +62,12 @@
                         const FT_Matrix*  matrix,
                         const FT_Vector*  delta )
   {
-    FT_Error error = Raster_Err_Ok;
+    FT_Error error = FT_Err_Ok;
 
 
     if ( slot->format != render->glyph_format )
     {
-      error = Raster_Err_Invalid_Argument;
+      error = FT_THROW( Invalid_Argument );
       goto Exit;
     }
 
@@ -114,7 +115,7 @@
     /* check glyph image format */
     if ( slot->format != render->glyph_format )
     {
-      error = Raster_Err_Invalid_Argument;
+      error = FT_THROW( Invalid_Argument );
       goto Exit;
     }
 
@@ -124,13 +125,13 @@
     {
       /* raster1 is only capable of producing monochrome bitmaps */
       if ( render->clazz == &ft_raster1_renderer_class )
-        return Raster_Err_Cannot_Render_Glyph;
+        return FT_THROW( Cannot_Render_Glyph );
     }
     else
     {
       /* raster5 is only capable of producing 5-gray-levels bitmaps */
       if ( render->clazz == &ft_raster5_renderer_class )
-        return Raster_Err_Cannot_Render_Glyph;
+        return FT_THROW( Cannot_Render_Glyph );
     }
 #else /* FT_CONFIG_OPTION_PIC */
     /* When PIC is enabled, we cannot get to the class object      */
@@ -142,13 +143,13 @@
     {
       /* raster1 is only capable of producing monochrome bitmaps */
       if ( render->clazz->root.module_name[6] == '1' )
-        return Raster_Err_Cannot_Render_Glyph;
+        return FT_THROW( Cannot_Render_Glyph );
     }
     else
     {
       /* raster5 is only capable of producing 5-gray-levels bitmaps */
       if ( render->clazz->root.module_name[6] == '5' )
-        return Raster_Err_Cannot_Render_Glyph;
+        return FT_THROW( Cannot_Render_Glyph );
     }
 #endif /* FT_CONFIG_OPTION_PIC */
 
@@ -179,7 +180,7 @@
 
     if ( width > FT_USHORT_MAX || height > FT_USHORT_MAX )
     {
-      error = Raster_Err_Invalid_Argument;
+      error = FT_THROW( Invalid_Argument );
       goto Exit;
     }
 
diff --git a/src/raster/rastpic.c b/src/raster/rastpic.c
index 2883e3f..5e9f7cc 100644
--- a/src/raster/rastpic.c
+++ b/src/raster/rastpic.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType position independent code services for raster module.   */
 /*                                                                         */
-/*  Copyright 2009, 2010 by                                                */
+/*  Copyright 2009, 2010, 2012, 2013 by                                    */
 /*  Oran Agra and Mickey Gabel.                                            */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -22,22 +22,26 @@
 #include "rastpic.h"
 #include "rasterrs.h"
 
+
 #ifdef FT_CONFIG_OPTION_PIC
 
   /* forward declaration of PIC init functions from ftraster.c */
   void
   FT_Init_Class_ft_standard_raster( FT_Raster_Funcs*  funcs );
 
+
   void
   ft_raster1_renderer_class_pic_free( FT_Library  library )
   {
     FT_PIC_Container*  pic_container = &library->pic_container;
-    FT_Memory  memory = library->memory;
+    FT_Memory          memory        = library->memory;
 
 
     if ( pic_container->raster )
     {
-      RasterPIC* container = (RasterPIC*)pic_container->raster;
+      RasterPIC*  container = (RasterPIC*)pic_container->raster;
+
+
       if ( --container->ref_count )
         return;
       FT_FREE( container );
@@ -49,14 +53,14 @@
   FT_Error
   ft_raster1_renderer_class_pic_init( FT_Library  library )
   {
-    FT_PIC_Container* pic_container = &library->pic_container;
-    FT_Error          error         = Raster_Err_Ok;
-    RasterPIC*        container;
-    FT_Memory         memory        = library->memory;
+    FT_PIC_Container*  pic_container = &library->pic_container;
+    FT_Error           error         = FT_Err_Ok;
+    RasterPIC*         container     = NULL;
+    FT_Memory          memory        = library->memory;
 
 
-    /* since this function also serve raster5 renderer,
-       it implements reference counting */
+    /* since this function also serves raster5 renderer, */
+    /* it implements reference counting                  */
     if ( pic_container->raster )
     {
       ((RasterPIC*)pic_container->raster)->ref_count++;
@@ -68,16 +72,17 @@
       return error;
     FT_MEM_SET( container, 0, sizeof ( *container ) );
     pic_container->raster = container;
+
     container->ref_count = 1;
 
-    /* initialize pointer table - this is how the module usually expects this data */
+    /* initialize pointer table -                       */
+    /* this is how the module usually expects this data */
     FT_Init_Class_ft_standard_raster( &container->ft_standard_raster );
-/*Exit:*/
-    if( error )
-      ft_raster1_renderer_class_pic_free( library );
+
     return error;
   }
 
+
   /* re-route these init and free functions to the above functions */
   FT_Error
   ft_raster5_renderer_class_pic_init( FT_Library  library )
@@ -85,6 +90,7 @@
     return ft_raster1_renderer_class_pic_init( library );
   }
 
+
   void
   ft_raster5_renderer_class_pic_free( FT_Library  library )
   {
diff --git a/src/raster/rastpic.h b/src/raster/rastpic.h
index 7822a24..e0ddba6 100644
--- a/src/raster/rastpic.h
+++ b/src/raster/rastpic.h
@@ -24,19 +24,25 @@
 
 #include FT_INTERNAL_PIC_H
 
+
 #ifndef FT_CONFIG_OPTION_PIC
-#define FT_STANDARD_RASTER_GET     ft_standard_raster
+
+#define FT_STANDARD_RASTER_GET  ft_standard_raster
 
 #else /* FT_CONFIG_OPTION_PIC */
 
-  typedef struct RasterPIC_
+  typedef struct  RasterPIC_
   {
-    int ref_count;
-    FT_Raster_Funcs ft_standard_raster;
+    int              ref_count;
+    FT_Raster_Funcs  ft_standard_raster;
+
   } RasterPIC;
 
-#define GET_PIC(lib)               ((RasterPIC*)((lib)->pic_container.raster))
-#define FT_STANDARD_RASTER_GET     (GET_PIC(library)->ft_standard_raster)
+
+#define GET_PIC( lib )                                    \
+          ( (RasterPIC*)( (lib)->pic_container.raster ) )
+#define FT_STANDARD_RASTER_GET  ( GET_PIC( library )->ft_standard_raster )
+
 
   /* see rastpic.c for the implementation */
   void
diff --git a/src/sfnt/pngshim.c b/src/sfnt/pngshim.c
new file mode 100644
index 0000000..408f879
--- /dev/null
+++ b/src/sfnt/pngshim.c
@@ -0,0 +1,336 @@
+/***************************************************************************/
+/*                                                                         */
+/*  pngshim.c                                                              */
+/*                                                                         */
+/*    PNG Bitmap glyph support.                                            */
+/*                                                                         */
+/*  Copyright 2013 by Google, Inc.                                         */
+/*  Written by Stuart Gill and Behdad Esfahbod.                            */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+
+#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_STREAM_H
+#include FT_TRUETYPE_TAGS_H
+#include FT_CONFIG_STANDARD_LIBRARY_H
+
+
+#ifdef FT_CONFIG_OPTION_USE_PNG
+
+  /* We always include <stjmp.h>, so make libpng shut up! */
+#define PNG_SKIP_SETJMP_CHECK 1
+#include <png.h>
+#include "pngshim.h"
+
+#include "sferrors.h"
+
+
+  /* This code is freely based on cairo-png.c.  There's so many ways */
+  /* to call libpng, and the way cairo does it is defacto standard.  */
+
+  static int
+  multiply_alpha( int  alpha,
+                  int  color )
+  {
+    int  temp = ( alpha * color ) + 0x80;
+
+
+    return ( temp + ( temp >> 8 ) ) >> 8;
+  }
+
+
+  /* Premultiplies data and converts RGBA bytes => native endian. */
+  static void
+  premultiply_data( png_structp    png,
+                    png_row_infop  row_info,
+                    png_bytep      data )
+  {
+    unsigned int  i;
+
+    FT_UNUSED( png );
+
+
+    for ( i = 0; i < row_info->rowbytes; i += 4 )
+    {
+      unsigned char*  base  = &data[i];
+      unsigned int    alpha = base[3];
+
+
+      if ( alpha == 0 )
+        base[0] = base[1] = base[2] = base[3] = 0;
+
+      else
+      {
+        unsigned int  red   = base[0];
+        unsigned int  green = base[1];
+        unsigned int  blue  = base[2];
+
+
+        if ( alpha != 0xFF )
+        {
+          red   = multiply_alpha( alpha, red   );
+          green = multiply_alpha( alpha, green );
+          blue  = multiply_alpha( alpha, blue  );
+        }
+
+        base[0] = blue;
+        base[1] = green;
+        base[2] = red;
+        base[3] = alpha;
+      }
+    }
+  }
+
+
+  /* Converts RGBx bytes to BGRA. */
+  static void
+  convert_bytes_to_data( png_structp    png,
+                         png_row_infop  row_info,
+                         png_bytep      data )
+  {
+    unsigned int  i;
+
+    FT_UNUSED( png );
+
+
+    for ( i = 0; i < row_info->rowbytes; i += 4 )
+    {
+      unsigned char*  base  = &data[i];
+      unsigned int    red   = base[0];
+      unsigned int    green = base[1];
+      unsigned int    blue  = base[2];
+
+
+      base[0] = blue;
+      base[1] = green;
+      base[2] = red;
+      base[3] = 0xFF;
+    }
+  }
+
+
+  /* Use error callback to avoid png writing to stderr. */
+  static void
+  error_callback( png_structp      png,
+                  png_const_charp  error_msg )
+  {
+    FT_Error*  error = png_get_error_ptr( png );
+
+    FT_UNUSED( error_msg );
+
+
+    *error = FT_THROW( Out_Of_Memory );
+#ifdef PNG_SETJMP_SUPPORTED
+    longjmp( png_jmpbuf( png ), 1 );
+#endif
+    /* if we get here, then we have no choice but to abort ... */
+  }
+
+
+  /* Use warning callback to avoid png writing to stderr. */
+  static void
+  warning_callback( png_structp      png,
+                    png_const_charp  error_msg )
+  {
+    FT_UNUSED( png );
+    FT_UNUSED( error_msg );
+
+    /* Just ignore warnings. */
+  }
+
+
+  static void
+  read_data_from_FT_Stream( png_structp  png,
+                            png_bytep    data,
+                            png_size_t   length )
+  {
+    FT_Error   error;
+    png_voidp  p      = png_get_io_ptr( png );
+    FT_Stream  stream = (FT_Stream)p;
+
+
+    if ( FT_FRAME_ENTER( length ) )
+    {
+      FT_Error*  e = png_get_error_ptr( png );
+
+
+      *e = FT_THROW( Invalid_Stream_Read );
+      png_error( png, NULL );
+
+      return;
+    }
+
+    memcpy( data, stream->cursor, length );
+
+    FT_FRAME_EXIT();
+  }
+
+
+  static FT_Error
+  Load_SBit_Png( FT_Bitmap*       map,
+                 FT_Int           x_offset,
+                 FT_Int           y_offset,
+                 FT_Int           pix_bits,
+                 TT_SBit_Metrics  metrics,
+                 FT_Memory        memory,
+                 FT_Byte*         data,
+                 FT_UInt          png_len )
+  {
+    FT_Error      error = FT_Err_Ok;
+    FT_StreamRec  stream;
+
+    png_structp  png;
+    png_infop    info;
+    png_uint_32  imgWidth, imgHeight;
+
+    int         bitdepth, color_type, interlace;
+    FT_Int      i;
+    png_byte*  *rows;
+
+
+    if ( x_offset < 0 || x_offset + metrics->width  > map->width ||
+         y_offset < 0 || y_offset + metrics->height > map->rows  ||
+         pix_bits != 32 || map->pixel_mode != FT_PIXEL_MODE_BGRA )
+    {
+      error = FT_THROW( Invalid_Argument );
+      goto Exit;
+    }
+
+    FT_Stream_OpenMemory( &stream, data, png_len );
+
+    png = png_create_read_struct( PNG_LIBPNG_VER_STRING,
+                                  &error,
+                                  error_callback,
+                                  warning_callback );
+    if ( !png )
+    {
+      error = FT_THROW( Out_Of_Memory );
+      goto Exit;
+    }
+
+    info = png_create_info_struct( png );
+    if ( !info )
+    {
+      error = FT_THROW( Out_Of_Memory );
+      png_destroy_read_struct( &png, NULL, NULL );
+      goto Exit;
+    }
+
+    if ( ft_setjmp( png_jmpbuf( png ) ) )
+    {
+      error = FT_THROW( Invalid_File_Format );
+      goto DestroyExit;
+    }
+
+    png_set_read_fn( png, &stream, read_data_from_FT_Stream );
+
+    png_read_info( png, info );
+    png_get_IHDR( png, info,
+                  &imgWidth, &imgHeight,
+                  &bitdepth, &color_type, &interlace,
+                  NULL, NULL );
+
+    if ( error != FT_Err_Ok                   ||
+         (FT_Int)imgWidth  != metrics->width  ||
+         (FT_Int)imgHeight != metrics->height )
+      goto DestroyExit;
+
+    /* convert palette/gray image to rgb */
+    if ( color_type == PNG_COLOR_TYPE_PALETTE )
+      png_set_palette_to_rgb( png );
+
+    /* expand gray bit depth if needed */
+    if ( color_type == PNG_COLOR_TYPE_GRAY )
+    {
+#if PNG_LIBPNG_VER >= 10209
+      png_set_expand_gray_1_2_4_to_8( png );
+#else
+      png_set_gray_1_2_4_to_8( png );
+#endif
+    }
+
+    /* transform transparency to alpha */
+    if ( png_get_valid(png, info, PNG_INFO_tRNS ) )
+      png_set_tRNS_to_alpha( png );
+
+    if ( bitdepth == 16 )
+      png_set_strip_16( png );
+
+    if ( bitdepth < 8 )
+      png_set_packing( png );
+
+    /* convert grayscale to RGB */
+    if ( color_type == PNG_COLOR_TYPE_GRAY       ||
+         color_type == PNG_COLOR_TYPE_GRAY_ALPHA )
+      png_set_gray_to_rgb( png );
+
+    if ( interlace != PNG_INTERLACE_NONE )
+      png_set_interlace_handling( png );
+
+    png_set_filler( png, 0xFF, PNG_FILLER_AFTER );
+
+    /* recheck header after setting EXPAND options */
+    png_read_update_info(png, info );
+    png_get_IHDR( png, info,
+                  &imgWidth, &imgHeight,
+                  &bitdepth, &color_type, &interlace,
+                  NULL, NULL );
+
+    if ( bitdepth != 8                              ||
+        !( color_type == PNG_COLOR_TYPE_RGB       ||
+           color_type == PNG_COLOR_TYPE_RGB_ALPHA ) )
+    {
+      error = FT_THROW( Invalid_File_Format );
+      goto DestroyExit;
+    }
+
+    switch ( color_type )
+    {
+    default:
+      /* Shouldn't happen, but fall through. */
+
+    case PNG_COLOR_TYPE_RGB_ALPHA:
+      png_set_read_user_transform_fn( png, premultiply_data );
+      break;
+
+    case PNG_COLOR_TYPE_RGB:
+      /* Humm, this smells.  Carry on though. */
+      png_set_read_user_transform_fn( png, convert_bytes_to_data );
+      break;
+    }
+
+    if ( FT_NEW_ARRAY( rows, imgHeight ) )
+    {
+      error = FT_THROW( Out_Of_Memory );
+      goto DestroyExit;
+    }
+
+    for ( i = 0; i < (FT_Int)imgHeight; i++ )
+      rows[i] = map->buffer + ( y_offset + i ) * map->pitch + x_offset * 4;
+
+    png_read_image( png, rows );
+
+    FT_FREE( rows );
+
+    png_read_end( png, info );
+
+  DestroyExit:
+    png_destroy_read_struct( &png, &info, NULL );
+    FT_Stream_Close( &stream );
+
+  Exit:
+    return error;
+  }
+
+#endif /* FT_CONFIG_OPTION_USE_PNG */
+
+
+/* END */
diff --git a/src/sfnt/pngshim.h b/src/sfnt/pngshim.h
new file mode 100644
index 0000000..8a2e69c
--- /dev/null
+++ b/src/sfnt/pngshim.h
@@ -0,0 +1,48 @@
+/***************************************************************************/
+/*                                                                         */
+/*  pngshim.h                                                              */
+/*                                                                         */
+/*    PNG Bitmap glyph support.                                            */
+/*                                                                         */
+/*  Copyright 2013 by Google, Inc.                                         */
+/*  Written by Stuart Gill and Behdad Esfahbod.                            */
+/*                                                                         */
+/*  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 __PNGSHIM_H__
+#define __PNGSHIM_H__
+
+
+#include <ft2build.h>
+#include "ttload.h"
+
+
+FT_BEGIN_HEADER
+
+#ifdef FT_CONFIG_OPTION_USE_PNG
+
+  FT_LOCAL( FT_Error )
+  Load_SBit_Png( FT_Bitmap*       map,
+                 FT_Int           x_offset,
+                 FT_Int           y_offset,
+                 FT_Int           pix_bits,
+                 TT_SBit_Metrics  metrics,
+                 FT_Memory        memory,
+                 FT_Byte*         data,
+                 FT_UInt          png_len );
+
+#endif
+
+FT_END_HEADER
+
+#endif /* __PNGSHIM_H__ */
+
+
+/* END */
diff --git a/src/sfnt/sfdriver.c b/src/sfnt/sfdriver.c
index 847d83d..a368b8c 100644
--- a/src/sfnt/sfdriver.c
+++ b/src/sfnt/sfdriver.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    High-level SFNT driver interface (body).                             */
 /*                                                                         */
-/*  Copyright 1996-2007, 2009-2011 by                                      */
+/*  Copyright 1996-2007, 2009-2013 by                                      */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -50,6 +50,7 @@
 #include FT_SERVICE_SFNT_H
 #include FT_SERVICE_TT_CMAP_H
 
+
   /*************************************************************************/
   /*                                                                       */
   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
@@ -60,10 +61,10 @@
 #define FT_COMPONENT  trace_sfdriver
 
 
- /*
-  *  SFNT TABLE SERVICE
-  *
-  */
+  /*
+   *  SFNT TABLE SERVICE
+   *
+   */
 
   static void*
   get_sfnt_table( TT_Face      face,
@@ -118,37 +119,37 @@
                    FT_ULong  *length )
   {
     if ( !offset || !length )
-      return SFNT_Err_Invalid_Argument;
+      return FT_THROW( Invalid_Argument );
 
     if ( !tag )
       *length = face->num_tables;
     else
     {
       if ( idx >= face->num_tables )
-        return SFNT_Err_Table_Missing;
+        return FT_THROW( Table_Missing );
 
       *tag    = face->dir_tables[idx].Tag;
       *offset = face->dir_tables[idx].Offset;
       *length = face->dir_tables[idx].Length;
     }
 
-    return SFNT_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
-  FT_DEFINE_SERVICE_SFNT_TABLEREC(sfnt_service_sfnt_table,
+  FT_DEFINE_SERVICE_SFNT_TABLEREC(
+    sfnt_service_sfnt_table,
     (FT_SFNT_TableLoadFunc)tt_face_load_any,
     (FT_SFNT_TableGetFunc) get_sfnt_table,
-    (FT_SFNT_TableInfoFunc)sfnt_table_info
-  )
+    (FT_SFNT_TableInfoFunc)sfnt_table_info )
 
 
 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
 
- /*
-  *  GLYPH DICT SERVICE
-  *
-  */
+  /*
+   *  GLYPH DICT SERVICE
+   *
+   */
 
   static FT_Error
   sfnt_get_glyph_name( TT_Face     face,
@@ -172,17 +173,18 @@
   sfnt_get_name_index( TT_Face     face,
                        FT_String*  glyph_name )
   {
-    FT_Face   root = &face->root;
-    FT_UInt   i, max_gid = FT_UINT_MAX;
+    FT_Face  root = &face->root;
+
+    FT_UInt  i, max_gid = FT_UINT_MAX;
 
 
     if ( root->num_glyphs < 0 )
       return 0;
-    else if ( ( FT_ULong ) root->num_glyphs < FT_UINT_MAX )
-      max_gid = ( FT_UInt ) root->num_glyphs;
+    else if ( (FT_ULong)root->num_glyphs < FT_UINT_MAX )
+      max_gid = (FT_UInt)root->num_glyphs;
     else
       FT_TRACE0(( "Ignore glyph names for invalid GID 0x%08x - 0x%08x\n",
-         FT_UINT_MAX, root->num_glyphs ));
+                  FT_UINT_MAX, root->num_glyphs ));
 
     for ( i = 0; i < max_gid; i++ )
     {
@@ -201,18 +203,19 @@
   }
 
 
-  FT_DEFINE_SERVICE_GLYPHDICTREC(sfnt_service_glyph_dict,
+  FT_DEFINE_SERVICE_GLYPHDICTREC(
+    sfnt_service_glyph_dict,
     (FT_GlyphDict_GetNameFunc)  sfnt_get_glyph_name,
-    (FT_GlyphDict_NameIndexFunc)sfnt_get_name_index
-  )
+    (FT_GlyphDict_NameIndexFunc)sfnt_get_name_index )
+
 
 #endif /* TT_CONFIG_OPTION_POSTSCRIPT_NAMES */
 
 
- /*
-  *  POSTSCRIPT NAME SERVICE
-  *
-  */
+  /*
+   *  POSTSCRIPT NAME SERVICE
+   *
+   */
 
   static const char*
   sfnt_get_ps_name( TT_Face  face )
@@ -254,7 +257,7 @@
       FT_Memory         memory = face->root.memory;
       TT_NameEntryRec*  name   = face->name_table.names + found_win;
       FT_UInt           len    = name->stringLength / 2;
-      FT_Error          error  = SFNT_Err_Ok;
+      FT_Error          error  = FT_Err_Ok;
 
       FT_UNUSED( error );
 
@@ -296,7 +299,7 @@
       FT_Memory         memory = face->root.memory;
       TT_NameEntryRec*  name   = face->name_table.names + found_apple;
       FT_UInt           len    = name->stringLength;
-      FT_Error          error  = SFNT_Err_Ok;
+      FT_Error          error  = FT_Err_Ok;
 
       FT_UNUSED( error );
 
@@ -324,17 +327,18 @@
     return result;
   }
 
-  FT_DEFINE_SERVICE_PSFONTNAMEREC(sfnt_service_ps_name,
-    (FT_PsName_GetFunc)sfnt_get_ps_name
-  )
+
+  FT_DEFINE_SERVICE_PSFONTNAMEREC(
+    sfnt_service_ps_name,
+    (FT_PsName_GetFunc)sfnt_get_ps_name )
 
 
   /*
    *  TT CMAP INFO
    */
-  FT_DEFINE_SERVICE_TTCMAPSREC(tt_service_get_cmap_info,
-    (TT_CMap_Info_GetFunc)tt_get_cmap_info
-  )
+  FT_DEFINE_SERVICE_TTCMAPSREC(
+    tt_service_get_cmap_info,
+    (TT_CMap_Info_GetFunc)tt_get_cmap_info )
 
 
 #ifdef TT_CONFIG_OPTION_BDF
@@ -367,7 +371,7 @@
           *acharset_registry = registry.u.atom;
         }
         else
-          error = SFNT_Err_Invalid_Argument;
+          error = FT_THROW( Invalid_Argument );
       }
     }
 
@@ -375,10 +379,11 @@
   }
 
 
-  FT_DEFINE_SERVICE_BDFRec(sfnt_service_bdf,
-    (FT_BDF_GetCharsetIdFunc) sfnt_get_charset_id,
-    (FT_BDF_GetPropertyFunc)  tt_face_find_bdf_prop
-  )
+  FT_DEFINE_SERVICE_BDFRec(
+    sfnt_service_bdf,
+    (FT_BDF_GetCharsetIdFunc)sfnt_get_charset_id,
+    (FT_BDF_GetPropertyFunc) tt_face_find_bdf_prop )
+
 
 #endif /* TT_CONFIG_OPTION_BDF */
 
@@ -388,33 +393,33 @@
    */
 
 #if defined TT_CONFIG_OPTION_POSTSCRIPT_NAMES && defined TT_CONFIG_OPTION_BDF
-  FT_DEFINE_SERVICEDESCREC5(sfnt_services,
-    FT_SERVICE_ID_SFNT_TABLE,           &FT_SFNT_SERVICE_SFNT_TABLE_GET,
-    FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &FT_SFNT_SERVICE_PS_NAME_GET,
-    FT_SERVICE_ID_GLYPH_DICT,           &FT_SFNT_SERVICE_GLYPH_DICT_GET,
-    FT_SERVICE_ID_BDF,                  &FT_SFNT_SERVICE_BDF_GET,
-    FT_SERVICE_ID_TT_CMAP,              &FT_TT_SERVICE_GET_CMAP_INFO_GET
-  )
+  FT_DEFINE_SERVICEDESCREC5(
+    sfnt_services,
+    FT_SERVICE_ID_SFNT_TABLE,           &SFNT_SERVICE_SFNT_TABLE_GET,
+    FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &SFNT_SERVICE_PS_NAME_GET,
+    FT_SERVICE_ID_GLYPH_DICT,           &SFNT_SERVICE_GLYPH_DICT_GET,
+    FT_SERVICE_ID_BDF,                  &SFNT_SERVICE_BDF_GET,
+    FT_SERVICE_ID_TT_CMAP,              &TT_SERVICE_CMAP_INFO_GET )
 #elif defined TT_CONFIG_OPTION_POSTSCRIPT_NAMES
-  FT_DEFINE_SERVICEDESCREC4(sfnt_services,
-    FT_SERVICE_ID_SFNT_TABLE,           &FT_SFNT_SERVICE_SFNT_TABLE_GET,
-    FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &FT_SFNT_SERVICE_PS_NAME_GET,
-    FT_SERVICE_ID_GLYPH_DICT,           &FT_SFNT_SERVICE_GLYPH_DICT_GET,
-    FT_SERVICE_ID_TT_CMAP,              &FT_TT_SERVICE_GET_CMAP_INFO_GET
-  )
+  FT_DEFINE_SERVICEDESCREC4(
+    sfnt_services,
+    FT_SERVICE_ID_SFNT_TABLE,           &SFNT_SERVICE_SFNT_TABLE_GET,
+    FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &SFNT_SERVICE_PS_NAME_GET,
+    FT_SERVICE_ID_GLYPH_DICT,           &SFNT_SERVICE_GLYPH_DICT_GET,
+    FT_SERVICE_ID_TT_CMAP,              &TT_SERVICE_CMAP_INFO_GET )
 #elif defined TT_CONFIG_OPTION_BDF
-  FT_DEFINE_SERVICEDESCREC4(sfnt_services,
-    FT_SERVICE_ID_SFNT_TABLE,           &FT_SFNT_SERVICE_SFNT_TABLE_GET,
-    FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &FT_SFNT_SERVICE_PS_NAME_GET,
-    FT_SERVICE_ID_BDF,                  &FT_SFNT_SERVICE_BDF_GET,
-    FT_SERVICE_ID_TT_CMAP,              &FT_TT_SERVICE_GET_CMAP_INFO_GET
-  )
+  FT_DEFINE_SERVICEDESCREC4(
+    sfnt_services,
+    FT_SERVICE_ID_SFNT_TABLE,           &SFNT_SERVICE_SFNT_TABLE_GET,
+    FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &SFNT_SERVICE_PS_NAME_GET,
+    FT_SERVICE_ID_BDF,                  &SFNT_SERVICE_BDF_GET,
+    FT_SERVICE_ID_TT_CMAP,              &TT_SERVICE_CMAP_INFO_GET )
 #else
-  FT_DEFINE_SERVICEDESCREC3(sfnt_services,
-    FT_SERVICE_ID_SFNT_TABLE,           &FT_SFNT_SERVICE_SFNT_TABLE_GET,
-    FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &FT_SFNT_SERVICE_PS_NAME_GET,
-    FT_SERVICE_ID_TT_CMAP,              &FT_TT_SERVICE_GET_CMAP_INFO_GET
-  )
+  FT_DEFINE_SERVICEDESCREC3(
+    sfnt_services,
+    FT_SERVICE_ID_SFNT_TABLE,           &SFNT_SERVICE_SFNT_TABLE_GET,
+    FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &SFNT_SERVICE_PS_NAME_GET,
+    FT_SERVICE_ID_TT_CMAP,              &TT_SERVICE_CMAP_INFO_GET )
 #endif
 
 
@@ -422,7 +427,7 @@
   sfnt_get_interface( FT_Module    module,
                       const char*  module_interface )
   {
-    /* FT_SFNT_SERVICES_GET derefers `library' in PIC mode */
+    /* SFNT_SERVICES_GET derefers `library' in PIC mode */
 #ifdef FT_CONFIG_OPTION_PIC
     FT_Library  library;
 
@@ -435,149 +440,25 @@
 #else
     FT_UNUSED( module );
 #endif
-    return ft_service_list_lookup( FT_SFNT_SERVICES_GET, module_interface );
+
+    return ft_service_list_lookup( SFNT_SERVICES_GET, module_interface );
   }
 
 
-#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
-
-  FT_CALLBACK_DEF( FT_Error )
-  tt_face_load_sfnt_header_stub( TT_Face      face,
-                                 FT_Stream    stream,
-                                 FT_Long      face_index,
-                                 SFNT_Header  header )
-  {
-    FT_UNUSED( face );
-    FT_UNUSED( stream );
-    FT_UNUSED( face_index );
-    FT_UNUSED( header );
-
-    return SFNT_Err_Unimplemented_Feature;
-  }
-
-
-  FT_CALLBACK_DEF( FT_Error )
-  tt_face_load_directory_stub( TT_Face      face,
-                               FT_Stream    stream,
-                               SFNT_Header  header )
-  {
-    FT_UNUSED( face );
-    FT_UNUSED( stream );
-    FT_UNUSED( header );
-
-    return SFNT_Err_Unimplemented_Feature;
-  }
-
-
-  FT_CALLBACK_DEF( FT_Error )
-  tt_face_load_hdmx_stub( TT_Face    face,
-                          FT_Stream  stream )
-  {
-    FT_UNUSED( face );
-    FT_UNUSED( stream );
-
-    return SFNT_Err_Unimplemented_Feature;
-  }
-
-
-  FT_CALLBACK_DEF( void )
-  tt_face_free_hdmx_stub( TT_Face  face )
-  {
-    FT_UNUSED( face );
-  }
-
-
-  FT_CALLBACK_DEF( FT_Error )
-  tt_face_set_sbit_strike_stub( TT_Face    face,
-                                FT_UInt    x_ppem,
-                                FT_UInt    y_ppem,
-                                FT_ULong*  astrike_index )
-  {
-    /*
-     * We simply forge a FT_Size_Request and call the real function
-     * that does all the work.
-     *
-     * This stub might be called by libXfont in the X.Org Xserver,
-     * compiled against version 2.1.8 or newer.
-     */
-
-    FT_Size_RequestRec  req;
-
-
-    req.type           = FT_SIZE_REQUEST_TYPE_NOMINAL;
-    req.width          = (FT_F26Dot6)x_ppem;
-    req.height         = (FT_F26Dot6)y_ppem;
-    req.horiResolution = 0;
-    req.vertResolution = 0;
-
-    *astrike_index = 0x7FFFFFFFUL;
-
-    return tt_face_set_sbit_strike( face, &req, astrike_index );
-  }
-
-
-  FT_CALLBACK_DEF( FT_Error )
-  tt_face_load_sbit_stub( TT_Face    face,
-                          FT_Stream  stream )
-  {
-    FT_UNUSED( face );
-    FT_UNUSED( stream );
-
-    /*
-     *  This function was originally implemented to load the sbit table.
-     *  However, it has been replaced by `tt_face_load_eblc', and this stub
-     *  is only there for some rogue clients which would want to call it
-     *  directly (which doesn't make much sense).
-     */
-    return SFNT_Err_Unimplemented_Feature;
-  }
-
-
-  FT_CALLBACK_DEF( void )
-  tt_face_free_sbit_stub( TT_Face  face )
-  {
-    /* nothing to do in this stub */
-    FT_UNUSED( face );
-  }
-
-
-  FT_CALLBACK_DEF( FT_Error )
-  tt_face_load_charmap_stub( TT_Face    face,
-                             void*      cmap,
-                             FT_Stream  input )
-  {
-    FT_UNUSED( face );
-    FT_UNUSED( cmap );
-    FT_UNUSED( input );
-
-    return SFNT_Err_Unimplemented_Feature;
-  }
-
-
-  FT_CALLBACK_DEF( FT_Error )
-  tt_face_free_charmap_stub( TT_Face  face,
-                             void*    cmap )
-  {
-    FT_UNUSED( face );
-    FT_UNUSED( cmap );
-
-    return SFNT_Err_Ok;
-  }
-
-#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
-
 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
-#define PUT_EMBEDDED_BITMAPS(a) a
+#define PUT_EMBEDDED_BITMAPS( a )  a
 #else
-#define PUT_EMBEDDED_BITMAPS(a) 0
-#endif
-#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
-#define PUT_PS_NAMES(a) a
-#else
-#define PUT_PS_NAMES(a) 0
+#define PUT_EMBEDDED_BITMAPS( a )  NULL
 #endif
 
-  FT_DEFINE_SFNT_INTERFACE(sfnt_interface,
+#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
+#define PUT_PS_NAMES( a )  a
+#else
+#define PUT_PS_NAMES( a )  NULL
+#endif
+
+  FT_DEFINE_SFNT_INTERFACE(
+    sfnt_interface,
     tt_face_goto_table,
 
     sfnt_init_face,
@@ -587,9 +468,6 @@
 
     tt_face_load_any,
 
-    tt_face_load_sfnt_header_stub, /* FT_CONFIG_OPTION_OLD_INTERNALS */
-    tt_face_load_directory_stub, /* FT_CONFIG_OPTION_OLD_INTERNALS */
-
     tt_face_load_head,
     tt_face_load_hhea,
     tt_face_load_cmap,
@@ -600,54 +478,39 @@
     tt_face_load_name,
     tt_face_free_name,
 
-    tt_face_load_hdmx_stub, /* FT_CONFIG_OPTION_OLD_INTERNALS */
-    tt_face_free_hdmx_stub, /* FT_CONFIG_OPTION_OLD_INTERNALS */
-
     tt_face_load_kern,
     tt_face_load_gasp,
     tt_face_load_pclt,
 
     /* see `ttload.h' */
-    PUT_EMBEDDED_BITMAPS(tt_face_load_bhed),
+    PUT_EMBEDDED_BITMAPS( tt_face_load_bhed ),
 
-    tt_face_set_sbit_strike_stub, /* FT_CONFIG_OPTION_OLD_INTERNALS */
-    tt_face_load_sbit_stub, /* FT_CONFIG_OPTION_OLD_INTERNALS */
-
-    tt_find_sbit_image, /* FT_CONFIG_OPTION_OLD_INTERNALS */
-    tt_load_sbit_metrics, /* FT_CONFIG_OPTION_OLD_INTERNALS */
-
-    PUT_EMBEDDED_BITMAPS(tt_face_load_sbit_image),
-
-    tt_face_free_sbit_stub, /* FT_CONFIG_OPTION_OLD_INTERNALS */
+    PUT_EMBEDDED_BITMAPS( tt_face_load_sbit_image ),
 
     /* see `ttpost.h' */
-    PUT_PS_NAMES(tt_face_get_ps_name),
-    PUT_PS_NAMES(tt_face_free_ps_names),
-
-    tt_face_load_charmap_stub, /* FT_CONFIG_OPTION_OLD_INTERNALS */
-    tt_face_free_charmap_stub, /* FT_CONFIG_OPTION_OLD_INTERNALS */
+    PUT_PS_NAMES( tt_face_get_ps_name   ),
+    PUT_PS_NAMES( tt_face_free_ps_names ),
 
     /* since version 2.1.8 */
-
     tt_face_get_kerning,
 
     /* since version 2.2 */
-
     tt_face_load_font_dir,
     tt_face_load_hmtx,
 
     /* see `ttsbit.h' and `sfnt.h' */
-    PUT_EMBEDDED_BITMAPS(tt_face_load_eblc),
-    PUT_EMBEDDED_BITMAPS(tt_face_free_eblc),
+    PUT_EMBEDDED_BITMAPS( tt_face_load_eblc ),
+    PUT_EMBEDDED_BITMAPS( tt_face_free_eblc ),
 
-    PUT_EMBEDDED_BITMAPS(tt_face_set_sbit_strike),
-    PUT_EMBEDDED_BITMAPS(tt_face_load_strike_metrics),
+    PUT_EMBEDDED_BITMAPS( tt_face_set_sbit_strike     ),
+    PUT_EMBEDDED_BITMAPS( tt_face_load_strike_metrics ),
 
     tt_face_get_metrics
   )
 
 
-  FT_DEFINE_MODULE(sfnt_module_class,
+  FT_DEFINE_MODULE(
+    sfnt_module_class,
 
     0,  /* not a font driver or renderer */
     sizeof ( FT_ModuleRec ),
@@ -656,12 +519,11 @@
     0x10000L,   /* driver version 1.0                     */
     0x20000L,   /* driver requires FreeType 2.0 or higher */
 
-    (const void*)&FT_SFNT_INTERFACE_GET,  /* module specific interface */
+    (const void*)&SFNT_INTERFACE_GET,  /* module specific interface */
 
     (FT_Module_Constructor)0,
     (FT_Module_Destructor) 0,
-    (FT_Module_Requester)  sfnt_get_interface
-  )
+    (FT_Module_Requester)  sfnt_get_interface )
 
 
 /* END */
diff --git a/src/sfnt/sferrors.h b/src/sfnt/sferrors.h
index 564a3fe..e981e1d 100644
--- a/src/sfnt/sferrors.h
+++ b/src/sfnt/sferrors.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    SFNT error codes (specification only).                               */
 /*                                                                         */
-/*  Copyright 2001, 2004, 2012 by                                          */
+/*  Copyright 2001, 2004, 2012, 2013 by                                    */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -33,8 +33,6 @@
 #define FT_ERR_PREFIX  SFNT_Err_
 #define FT_ERR_BASE    FT_Mod_Err_SFNT
 
-#define FT_KEEP_ERR_PREFIX
-
 #include FT_ERRORS_H
 
 #endif /* __SFERRORS_H__ */
diff --git a/src/sfnt/sfnt.c b/src/sfnt/sfnt.c
index fc507b4..d62ed4e 100644
--- a/src/sfnt/sfnt.c
+++ b/src/sfnt/sfnt.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Single object library component.                                     */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006 by                   */
+/*  Copyright 1996-2006, 2013 by                                           */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -28,6 +28,7 @@
 #include "sfdriver.c"
 
 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
+#include "pngshim.c"
 #include "ttsbit.c"
 #endif
 
diff --git a/src/sfnt/sfntpic.c b/src/sfnt/sfntpic.c
index 1372376..b3fb24b 100644
--- a/src/sfnt/sfntpic.c
+++ b/src/sfnt/sfntpic.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType position independent code services for sfnt module.     */
 /*                                                                         */
-/*  Copyright 2009, 2010 by                                                */
+/*  Copyright 2009, 2010, 2012, 2013 by                                    */
 /*  Oran Agra and Mickey Gabel.                                            */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -22,57 +22,52 @@
 #include "sfntpic.h"
 #include "sferrors.h"
 
+
 #ifdef FT_CONFIG_OPTION_PIC
 
   /* forward declaration of PIC init functions from sfdriver.c */
   FT_Error
   FT_Create_Class_sfnt_services( FT_Library           library,
-                                 FT_ServiceDescRec**  ouput_class );
-
+                                 FT_ServiceDescRec**  output_class );
   void
   FT_Destroy_Class_sfnt_services( FT_Library          library,
                                   FT_ServiceDescRec*  clazz );
-
   void
   FT_Init_Class_sfnt_service_bdf( FT_Service_BDFRec*  clazz );
-
   void
   FT_Init_Class_sfnt_interface( FT_Library       library,
                                 SFNT_Interface*  clazz );
-
   void
   FT_Init_Class_sfnt_service_glyph_dict(
     FT_Library                library,
     FT_Service_GlyphDictRec*  clazz );
-
   void
   FT_Init_Class_sfnt_service_ps_name(
     FT_Library                 library,
     FT_Service_PsFontNameRec*  clazz );
-
   void
   FT_Init_Class_tt_service_get_cmap_info(
     FT_Library              library,
     FT_Service_TTCMapsRec*  clazz );
-
   void
   FT_Init_Class_sfnt_service_sfnt_table(
     FT_Service_SFNT_TableRec*  clazz );
 
+
   /* forward declaration of PIC init functions from ttcmap.c */
   FT_Error
   FT_Create_Class_tt_cmap_classes( FT_Library       library,
                                    TT_CMap_Class**  output_class );
-
   void
   FT_Destroy_Class_tt_cmap_classes( FT_Library      library,
                                     TT_CMap_Class*  clazz );
 
+
   void
   sfnt_module_class_pic_free( FT_Library  library )
   {
     FT_PIC_Container*  pic_container = &library->pic_container;
-    FT_Memory  memory = library->memory;
+    FT_Memory          memory        = library->memory;
 
 
     if ( pic_container->sfnt )
@@ -84,10 +79,12 @@
         FT_Destroy_Class_sfnt_services( library,
                                         container->sfnt_services );
       container->sfnt_services = NULL;
+
       if ( container->tt_cmap_classes )
         FT_Destroy_Class_tt_cmap_classes( library,
                                           container->tt_cmap_classes );
       container->tt_cmap_classes = NULL;
+
       FT_FREE( container );
       pic_container->sfnt = NULL;
     }
@@ -95,25 +92,27 @@
 
 
   FT_Error
-  sfnt_module_class_pic_init(  FT_Library library )
+  sfnt_module_class_pic_init( FT_Library  library )
   {
     FT_PIC_Container*  pic_container = &library->pic_container;
-    FT_Error           error = SFNT_Err_Ok;
-    sfntModulePIC*     container;
-    FT_Memory          memory = library->memory;
+    FT_Error           error         = FT_Err_Ok;
+    sfntModulePIC*     container     = NULL;
+    FT_Memory          memory        = library->memory;
 
 
     /* allocate pointer, clear and set global container pointer */
-    if ( FT_ALLOC ( container, sizeof ( *container ) ) )
+    if ( FT_ALLOC( container, sizeof ( *container ) ) )
       return error;
     FT_MEM_SET( container, 0, sizeof ( *container ) );
     pic_container->sfnt = container;
 
-    /* initialize pointer table - this is how the module usually expects this data */
+    /* initialize pointer table -                       */
+    /* this is how the module usually expects this data */
     error = FT_Create_Class_sfnt_services( library,
                                            &container->sfnt_services );
     if ( error )
       goto Exit;
+
     error = FT_Create_Class_tt_cmap_classes( library,
                                              &container->tt_cmap_classes );
     if ( error )
@@ -132,14 +131,12 @@
 #endif
     FT_Init_Class_sfnt_interface( library, &container->sfnt_interface );
 
-Exit:
+  Exit:
     if ( error )
       sfnt_module_class_pic_free( library );
     return error;
   }
 
-
-
 #endif /* FT_CONFIG_OPTION_PIC */
 
 
diff --git a/src/sfnt/sfntpic.h b/src/sfnt/sfntpic.h
index f7993d1..b09a914 100644
--- a/src/sfnt/sfntpic.h
+++ b/src/sfnt/sfntpic.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType position independent code services for sfnt module.     */
 /*                                                                         */
-/*  Copyright 2009 by                                                      */
+/*  Copyright 2009, 2012 by                                                */
 /*  Oran Agra and Mickey Gabel.                                            */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -24,57 +24,76 @@
 
 #include FT_INTERNAL_PIC_H
 
- #ifndef FT_CONFIG_OPTION_PIC
-#define FT_SFNT_SERVICES_GET             sfnt_services
-#define FT_SFNT_SERVICE_GLYPH_DICT_GET   sfnt_service_glyph_dict
-#define FT_SFNT_SERVICE_PS_NAME_GET      sfnt_service_ps_name
-#define FT_TT_SERVICE_GET_CMAP_INFO_GET  tt_service_get_cmap_info
-#define FT_SFNT_SERVICES_GET             sfnt_services
-#define FT_TT_CMAP_CLASSES_GET           tt_cmap_classes
-#define FT_SFNT_SERVICE_SFNT_TABLE_GET   sfnt_service_sfnt_table
-#define FT_SFNT_SERVICE_BDF_GET          sfnt_service_bdf
-#define FT_SFNT_INTERFACE_GET            sfnt_interface
+
+#ifndef FT_CONFIG_OPTION_PIC
+
+#define SFNT_SERVICES_GET            sfnt_services
+#define SFNT_SERVICE_GLYPH_DICT_GET  sfnt_service_glyph_dict
+#define SFNT_SERVICE_PS_NAME_GET     sfnt_service_ps_name
+#define TT_SERVICE_CMAP_INFO_GET     tt_service_get_cmap_info
+#define SFNT_SERVICES_GET            sfnt_services
+#define TT_CMAP_CLASSES_GET          tt_cmap_classes
+#define SFNT_SERVICE_SFNT_TABLE_GET  sfnt_service_sfnt_table
+#define SFNT_SERVICE_BDF_GET         sfnt_service_bdf
+#define SFNT_INTERFACE_GET           sfnt_interface
 
 #else /* FT_CONFIG_OPTION_PIC */
 
-/* some include files required for members of sfntModulePIC */
+  /* some include files required for members of sfntModulePIC */
 #include FT_SERVICE_GLYPH_DICT_H
 #include FT_SERVICE_POSTSCRIPT_NAME_H
 #include FT_SERVICE_SFNT_H
 #include FT_SERVICE_TT_CMAP_H
+
 #ifdef TT_CONFIG_OPTION_BDF
 #include "ttbdf.h"
 #include FT_SERVICE_BDF_H
 #endif
+
 #include FT_INTERNAL_DEBUG_H
 #include FT_INTERNAL_STREAM_H
 #include FT_INTERNAL_SFNT_H
 #include "ttcmap.h"
 
-typedef struct sfntModulePIC_
+
+  typedef struct  sfntModulePIC_
   {
-    FT_ServiceDescRec* sfnt_services;
-    FT_Service_GlyphDictRec sfnt_service_glyph_dict;
+    FT_ServiceDescRec*        sfnt_services;
+    FT_Service_GlyphDictRec   sfnt_service_glyph_dict;
     FT_Service_PsFontNameRec  sfnt_service_ps_name;
-    FT_Service_TTCMapsRec  tt_service_get_cmap_info;
-    TT_CMap_Class* tt_cmap_classes;
-    FT_Service_SFNT_TableRec sfnt_service_sfnt_table;
+    FT_Service_TTCMapsRec     tt_service_get_cmap_info;
+    TT_CMap_Class*            tt_cmap_classes;
+    FT_Service_SFNT_TableRec  sfnt_service_sfnt_table;
 #ifdef TT_CONFIG_OPTION_BDF
-    FT_Service_BDFRec sfnt_service_bdf;
+    FT_Service_BDFRec         sfnt_service_bdf;
 #endif
-    SFNT_Interface sfnt_interface;
+    SFNT_Interface            sfnt_interface;
+
   } sfntModulePIC;
 
-#define GET_PIC(lib)                      ((sfntModulePIC*)((lib)->pic_container.sfnt))
-#define FT_SFNT_SERVICES_GET              (GET_PIC(library)->sfnt_services)
-#define FT_SFNT_SERVICE_GLYPH_DICT_GET    (GET_PIC(library)->sfnt_service_glyph_dict)
-#define FT_SFNT_SERVICE_PS_NAME_GET       (GET_PIC(library)->sfnt_service_ps_name)
-#define FT_TT_SERVICE_GET_CMAP_INFO_GET   (GET_PIC(library)->tt_service_get_cmap_info)
-#define FT_SFNT_SERVICES_GET              (GET_PIC(library)->sfnt_services)
-#define FT_TT_CMAP_CLASSES_GET            (GET_PIC(library)->tt_cmap_classes)
-#define FT_SFNT_SERVICE_SFNT_TABLE_GET    (GET_PIC(library)->sfnt_service_sfnt_table)
-#define FT_SFNT_SERVICE_BDF_GET           (GET_PIC(library)->sfnt_service_bdf)
-#define FT_SFNT_INTERFACE_GET             (GET_PIC(library)->sfnt_interface)
+
+#define GET_PIC( lib )                                      \
+          ( (sfntModulePIC*)( (lib)->pic_container.sfnt ) )
+
+#define SFNT_SERVICES_GET                       \
+          ( GET_PIC( library )->sfnt_services )
+#define SFNT_SERVICE_GLYPH_DICT_GET                       \
+          ( GET_PIC( library )->sfnt_service_glyph_dict )
+#define SFNT_SERVICE_PS_NAME_GET                       \
+          ( GET_PIC( library )->sfnt_service_ps_name )
+#define TT_SERVICE_CMAP_INFO_GET                           \
+          ( GET_PIC( library )->tt_service_get_cmap_info )
+#define SFNT_SERVICES_GET                       \
+          ( GET_PIC( library )->sfnt_services )
+#define TT_CMAP_CLASSES_GET                       \
+          ( GET_PIC( library )->tt_cmap_classes )
+#define SFNT_SERVICE_SFNT_TABLE_GET                       \
+          ( GET_PIC( library )->sfnt_service_sfnt_table )
+#define SFNT_SERVICE_BDF_GET                       \
+          ( GET_PIC( library )->sfnt_service_bdf )
+#define SFNT_INTERFACE_GET                       \
+          ( GET_PIC( library )->sfnt_interface )
+
 
   /* see sfntpic.c for the implementation */
   void
@@ -85,7 +104,7 @@
 
 #endif /* FT_CONFIG_OPTION_PIC */
 
-/* */
+  /* */
 
 FT_END_HEADER
 
diff --git a/src/sfnt/sfobjs.c b/src/sfnt/sfobjs.c
index d7be631..f975e71 100644
--- a/src/sfnt/sfobjs.c
+++ b/src/sfnt/sfobjs.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    SFNT object management (base).                                       */
 /*                                                                         */
-/*  Copyright 1996-2008, 2010-2011 by                                      */
+/*  Copyright 1996-2008, 2010-2013 by                                      */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -64,13 +64,17 @@
     for ( n = 0; n < len; n++ )
     {
       code = FT_NEXT_USHORT( read );
+
+      if ( code == 0 )
+        break;
+
       if ( code < 32 || code > 127 )
         code = '?';
 
       string[n] = (char)code;
     }
 
-    string[len] = 0;
+    string[n] = 0;
 
     return string;
   }
@@ -95,13 +99,17 @@
     for ( n = 0; n < len; n++ )
     {
       code = *read++;
+
+      if ( code == 0 )
+        break;
+
       if ( code < 32 || code > 127 )
         code = '?';
 
       string[n] = (char)code;
     }
 
-    string[len] = 0;
+    string[n] = 0;
 
     return string;
   }
@@ -137,7 +145,7 @@
                     FT_String**  name )
   {
     FT_Memory         memory = face->root.memory;
-    FT_Error          error  = SFNT_Err_Ok;
+    FT_Error          error  = FT_Err_Ok;
     FT_String*        result = NULL;
     FT_UShort         n;
     TT_NameEntryRec*  rec;
@@ -378,7 +386,7 @@
          tag != 0x00020000UL )
     {
       FT_TRACE2(( "  not a font using the SFNT container format\n" ));
-      return SFNT_Err_Unknown_File_Format;
+      return FT_THROW( Unknown_File_Format );
     }
 
     face->ttc_header.tag = TTAG_ttcf;
@@ -394,7 +402,7 @@
         return error;
 
       if ( face->ttc_header.count == 0 )
-        return SFNT_Err_Invalid_Table;
+        return FT_THROW( Invalid_Table );
 
       /* a rough size estimate: let's conservatively assume that there   */
       /* is just a single table info in each subfont header (12 + 16*1 = */
@@ -402,7 +410,7 @@
       /* size of the TTC header plus `28*count' bytes for all subfont    */
       /* headers                                                         */
       if ( (FT_ULong)face->ttc_header.count > stream->size / ( 28 + 4 ) )
-        return SFNT_Err_Array_Too_Large;
+        return FT_THROW( Array_Too_Large );
 
       /* now read the offsets of each font in the file */
       if ( FT_NEW_ARRAY( face->ttc_header.offsets, face->ttc_header.count ) )
@@ -457,7 +465,7 @@
       if ( !sfnt )
       {
         FT_ERROR(( "sfnt_init_face: cannot access `sfnt' module\n" ));
-        return SFNT_Err_Missing_Module;
+        return FT_THROW( Missing_Module );
       }
 
       face->sfnt       = sfnt;
@@ -478,7 +486,7 @@
       face_index = 0;
 
     if ( face_index >= face->ttc_header.count )
-      return SFNT_Err_Invalid_Argument;
+      return FT_THROW( Invalid_Argument );
 
     if ( FT_STREAM_SEEK( face->ttc_header.offsets[face_index] ) )
       return error;
@@ -495,42 +503,42 @@
   }
 
 
-#define LOAD_( x )                                            \
-  do {                                                        \
-    FT_TRACE2(( "`" #x "' " ));                               \
-    FT_TRACE3(( "-->\n" ));                                   \
-                                                              \
-    error = sfnt->load_##x( face, stream );                   \
-                                                              \
-    FT_TRACE2(( "%s\n", ( !error )                            \
-                        ? "loaded"                            \
-                        : ( error == SFNT_Err_Table_Missing ) \
-                          ? "missing"                         \
-                          : "failed to load" ));              \
-    FT_TRACE3(( "\n" ));                                      \
+#define LOAD_( x )                                          \
+  do {                                                      \
+    FT_TRACE2(( "`" #x "' " ));                             \
+    FT_TRACE3(( "-->\n" ));                                 \
+                                                            \
+    error = sfnt->load_ ## x( face, stream );               \
+                                                            \
+    FT_TRACE2(( "%s\n", ( !error )                          \
+                        ? "loaded"                          \
+                        : FT_ERR_EQ( error, Table_Missing ) \
+                          ? "missing"                       \
+                          : "failed to load" ));            \
+    FT_TRACE3(( "\n" ));                                    \
   } while ( 0 )
 
-#define LOADM_( x, vertical )                                 \
-  do {                                                        \
-    FT_TRACE2(( "`%s" #x "' ",                                \
-                vertical ? "vertical " : "" ));               \
-    FT_TRACE3(( "-->\n" ));                                   \
-                                                              \
-    error = sfnt->load_##x( face, stream, vertical );         \
-                                                              \
-    FT_TRACE2(( "%s\n", ( !error )                            \
-                        ? "loaded"                            \
-                        : ( error == SFNT_Err_Table_Missing ) \
-                          ? "missing"                         \
-                          : "failed to load" ));              \
-    FT_TRACE3(( "\n" ));                                      \
+#define LOADM_( x, vertical )                               \
+  do {                                                      \
+    FT_TRACE2(( "`%s" #x "' ",                              \
+                vertical ? "vertical " : "" ));             \
+    FT_TRACE3(( "-->\n" ));                                 \
+                                                            \
+    error = sfnt->load_ ## x( face, stream, vertical );     \
+                                                            \
+    FT_TRACE2(( "%s\n", ( !error )                          \
+                        ? "loaded"                          \
+                        : FT_ERR_EQ( error, Table_Missing ) \
+                          ? "missing"                       \
+                          : "failed to load" ));            \
+    FT_TRACE3(( "\n" ));                                    \
   } while ( 0 )
 
-#define GET_NAME( id, field )                                 \
-  do {                                                        \
-    error = tt_face_get_name( face, TT_NAME_ID_##id, field ); \
-    if ( error )                                              \
-      goto Exit;                                              \
+#define GET_NAME( id, field )                                   \
+  do {                                                          \
+    error = tt_face_get_name( face, TT_NAME_ID_ ## id, field ); \
+    if ( error )                                                \
+      goto Exit;                                                \
   } while ( 0 )
 
 
@@ -547,13 +555,14 @@
 #endif
     FT_Bool       has_outline;
     FT_Bool       is_apple_sbit;
-    FT_Bool       ignore_preferred_family = FALSE;
+    FT_Bool       ignore_preferred_family    = FALSE;
     FT_Bool       ignore_preferred_subfamily = FALSE;
 
     SFNT_Service  sfnt = (SFNT_Service)face->sfnt;
 
     FT_UNUSED( face_index );
 
+
     /* Check parameters */
 
     {
@@ -619,7 +628,7 @@
 
     if ( face->header.Units_Per_EM == 0 )
     {
-      error = SFNT_Err_Invalid_Table;
+      error = FT_THROW( Invalid_Table );
 
       goto Exit;
     }
@@ -647,9 +656,9 @@
       if ( !error )
       {
         LOADM_( hmtx, 0 );
-        if ( error == SFNT_Err_Table_Missing )
+        if ( FT_ERR_EQ( error, Table_Missing ) )
         {
-          error = SFNT_Err_Hmtx_Table_Missing;
+          error = FT_THROW( Hmtx_Table_Missing );
 
 #ifdef FT_CONFIG_OPTION_INCREMENTAL
           /* If this is an incrementally loaded font and there are */
@@ -659,12 +668,12 @@
                  get_glyph_metrics                                 )
           {
             face->horizontal.number_Of_HMetrics = 0;
-            error = SFNT_Err_Ok;
+            error                               = FT_Err_Ok;
           }
 #endif
         }
       }
-      else if ( error == SFNT_Err_Table_Missing )
+      else if ( FT_ERR_EQ( error, Table_Missing ) )
       {
         /* No `hhea' table necessary for SFNT Mac fonts. */
         if ( face->format_tag == TTAG_true )
@@ -672,11 +681,11 @@
           FT_TRACE2(( "This is an SFNT Mac font.\n" ));
 
           has_outline = 0;
-          error       = SFNT_Err_Ok;
+          error       = FT_Err_Ok;
         }
         else
         {
-          error = SFNT_Err_Horiz_Header_Missing;
+          error = FT_THROW( Horiz_Header_Missing );
 
 #ifdef FT_CONFIG_OPTION_INCREMENTAL
           /* If this is an incrementally loaded font and there are */
@@ -686,7 +695,7 @@
                  get_glyph_metrics                                 )
           {
             face->horizontal.number_Of_HMetrics = 0;
-            error = SFNT_Err_Ok;
+            error                               = FT_Err_Ok;
           }
 #endif
 
@@ -705,7 +714,7 @@
           face->vertical_info = 1;
       }
 
-      if ( error && error != SFNT_Err_Table_Missing )
+      if ( error && FT_ERR_NEQ( error, Table_Missing ) )
         goto Exit;
 
       LOAD_( os2 );
@@ -727,8 +736,8 @@
         /* a font which contains neither bitmaps nor outlines is */
         /* still valid (although rather useless in most cases);  */
         /* however, you can find such stripped fonts in PDFs     */
-        if ( error == SFNT_Err_Table_Missing )
-          error = SFNT_Err_Ok;
+        if ( FT_ERR_EQ( error, Table_Missing ) )
+          error = FT_Err_Ok;
         else
           goto Exit;
       }
@@ -737,7 +746,7 @@
     LOAD_( pclt );
     if ( error )
     {
-      if ( error != SFNT_Err_Table_Missing )
+      if ( FT_ERR_NEQ( error, Table_Missing ) )
         goto Exit;
 
       face->pclt.Version = 0;
@@ -803,7 +812,7 @@
                FT_FACE_FLAG_HORIZONTAL;   /* horizontal data   */
 
 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
-      if ( psnames_error == SFNT_Err_Ok               &&
+      if ( !psnames_error                             &&
            face->postscript.FormatType != 0x00030000L )
         flags |= FT_FACE_FLAG_GLYPH_NAMES;
 #endif
@@ -910,11 +919,7 @@
         FT_UInt  i, count;
 
 
-#ifndef FT_CONFIG_OPTION_OLD_INTERNALS
         count = face->sbit_num_strikes;
-#else
-        count = (FT_UInt)face->num_sbit_strikes;
-#endif
 
         if ( count > 0 )
         {
@@ -1115,7 +1120,6 @@
     }
 
     /* freeing the horizontal metrics */
-#ifndef FT_CONFIG_OPTION_OLD_INTERNALS
     {
       FT_Stream  stream = FT_FACE_STREAM( face );
 
@@ -1125,10 +1129,6 @@
       face->horz_metrics_size = 0;
       face->vert_metrics_size = 0;
     }
-#else
-    FT_FREE( face->horizontal.long_metrics );
-    FT_FREE( face->horizontal.short_metrics );
-#endif
 
     /* freeing the vertical ones, if any */
     if ( face->vertical_info )
diff --git a/src/sfnt/ttbdf.c b/src/sfnt/ttbdf.c
index 18845c3..9401dae 100644
--- a/src/sfnt/ttbdf.c
+++ b/src/sfnt/ttbdf.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    TrueType and OpenType embedded BDF properties (body).                */
 /*                                                                         */
-/*  Copyright 2005, 2006, 2010 by                                          */
+/*  Copyright 2005, 2006, 2010, 2013 by                                    */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -74,7 +74,7 @@
          length < 8                             ||
          FT_FRAME_EXTRACT( length, bdf->table ) )
     {
-      error = SFNT_Err_Invalid_Table;
+      error = FT_THROW( Invalid_Table );
       goto Exit;
     }
 
@@ -131,7 +131,7 @@
   BadTable:
     FT_FRAME_RELEASE( bdf->table );
     FT_ZERO( bdf );
-    error = SFNT_Err_Invalid_Table;
+    error = FT_THROW( Invalid_Table );
     goto Exit;
   }
 
@@ -143,7 +143,7 @@
   {
     TT_BDF     bdf   = &face->bdf;
     FT_Size    size  = FT_FACE(face)->size;
-    FT_Error   error = SFNT_Err_Ok;
+    FT_Error   error = FT_Err_Ok;
     FT_Byte*   p;
     FT_UInt    count;
     FT_Byte*   strike;
@@ -163,7 +163,7 @@
     p      = bdf->table + 8;
     strike = p + 4 * count;
 
-    error = SFNT_Err_Invalid_Argument;
+    error = FT_ERR( Invalid_Argument );
 
     if ( size == NULL || property_name == NULL )
       goto Exit;
@@ -215,7 +215,7 @@
             {
               aprop->type   = BDF_PROPERTY_TYPE_ATOM;
               aprop->u.atom = (const char*)bdf->strings + value;
-              error         = SFNT_Err_Ok;
+              error         = FT_Err_Ok;
               goto Exit;
             }
             break;
@@ -223,13 +223,13 @@
           case 0x02:
             aprop->type      = BDF_PROPERTY_TYPE_INTEGER;
             aprop->u.integer = (FT_Int32)value;
-            error            = SFNT_Err_Ok;
+            error            = FT_Err_Ok;
             goto Exit;
 
           case 0x03:
             aprop->type       = BDF_PROPERTY_TYPE_CARDINAL;
             aprop->u.cardinal = value;
-            error             = SFNT_Err_Ok;
+            error             = FT_Err_Ok;
             goto Exit;
 
           default:
diff --git a/src/sfnt/ttcmap.c b/src/sfnt/ttcmap.c
index 1dfd987..1507202 100644
--- a/src/sfnt/ttcmap.c
+++ b/src/sfnt/ttcmap.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    TrueType character mapping table (cmap) support (body).              */
 /*                                                                         */
-/*  Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 by      */
+/*  Copyright 2002-2010, 2012, 2013 by                                     */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -56,7 +56,7 @@
                 FT_Byte*  table )
   {
     cmap->data = table;
-    return SFNT_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
@@ -110,7 +110,7 @@
       }
     }
 
-    return SFNT_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
@@ -161,24 +161,28 @@
     cmap_info->format   = 0;
     cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
 
-    return SFNT_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
-  FT_DEFINE_TT_CMAP(tt_cmap0_class_rec,
-      sizeof ( TT_CMapRec ),
+  FT_DEFINE_TT_CMAP(
+    tt_cmap0_class_rec,
+    sizeof ( TT_CMapRec ),
 
-      (FT_CMap_InitFunc)     tt_cmap_init,
-      (FT_CMap_DoneFunc)     NULL,
-      (FT_CMap_CharIndexFunc)tt_cmap0_char_index,
-      (FT_CMap_CharNextFunc) tt_cmap0_char_next,
+    (FT_CMap_InitFunc)     tt_cmap_init,
+    (FT_CMap_DoneFunc)     NULL,
+    (FT_CMap_CharIndexFunc)tt_cmap0_char_index,
+    (FT_CMap_CharNextFunc) tt_cmap0_char_next,
 
-      NULL, NULL, NULL, NULL, NULL
-    ,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+
     0,
-    (TT_CMap_ValidateFunc)   tt_cmap0_validate,
-    (TT_CMap_Info_GetFunc)   tt_cmap0_get_info
-  )
+    (TT_CMap_ValidateFunc)tt_cmap0_validate,
+    (TT_CMap_Info_GetFunc)tt_cmap0_get_info )
 
 #endif /* TT_CONFIG_CMAP_FORMAT_0 */
 
@@ -365,7 +369,7 @@
       }
     }
 
-    return SFNT_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
@@ -537,24 +541,28 @@
     cmap_info->format   = 2;
     cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
 
-    return SFNT_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
-  FT_DEFINE_TT_CMAP(tt_cmap2_class_rec,
-      sizeof ( TT_CMapRec ),
+  FT_DEFINE_TT_CMAP(
+    tt_cmap2_class_rec,
+    sizeof ( TT_CMapRec ),
 
-      (FT_CMap_InitFunc)     tt_cmap_init,
-      (FT_CMap_DoneFunc)     NULL,
-      (FT_CMap_CharIndexFunc)tt_cmap2_char_index,
-      (FT_CMap_CharNextFunc) tt_cmap2_char_next,
+    (FT_CMap_InitFunc)     tt_cmap_init,
+    (FT_CMap_DoneFunc)     NULL,
+    (FT_CMap_CharIndexFunc)tt_cmap2_char_index,
+    (FT_CMap_CharNextFunc) tt_cmap2_char_next,
 
-      NULL, NULL, NULL, NULL, NULL
-    ,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+
     2,
-    (TT_CMap_ValidateFunc)   tt_cmap2_validate,
-    (TT_CMap_Info_GetFunc)   tt_cmap2_get_info
-  )
+    (TT_CMap_ValidateFunc)tt_cmap2_validate,
+    (TT_CMap_Info_GetFunc)tt_cmap2_get_info )
 
 #endif /* TT_CONFIG_CMAP_FORMAT_2 */
 
@@ -662,7 +670,7 @@
     cmap->cur_charcode = (FT_UInt32)0xFFFFFFFFUL;
     cmap->cur_gindex   = 0;
 
-    return SFNT_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
@@ -812,7 +820,7 @@
     FT_UInt   length = TT_NEXT_USHORT( p );
     FT_Byte   *ends, *starts, *offsets, *deltas, *glyph_ids;
     FT_UInt   num_segs;
-    FT_Error  error = SFNT_Err_Ok;
+    FT_Error  error = FT_Err_Ok;
 
 
     if ( length < 16 )
@@ -1373,23 +1381,27 @@
     cmap_info->format   = 4;
     cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
 
-    return SFNT_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
-  FT_DEFINE_TT_CMAP(tt_cmap4_class_rec,
-      sizeof ( TT_CMap4Rec ),
-      (FT_CMap_InitFunc)     tt_cmap4_init,
-      (FT_CMap_DoneFunc)     NULL,
-      (FT_CMap_CharIndexFunc)tt_cmap4_char_index,
-      (FT_CMap_CharNextFunc) tt_cmap4_char_next,
+  FT_DEFINE_TT_CMAP(
+    tt_cmap4_class_rec,
+    sizeof ( TT_CMap4Rec ),
+    (FT_CMap_InitFunc)     tt_cmap4_init,
+    (FT_CMap_DoneFunc)     NULL,
+    (FT_CMap_CharIndexFunc)tt_cmap4_char_index,
+    (FT_CMap_CharNextFunc) tt_cmap4_char_next,
 
-      NULL, NULL, NULL, NULL, NULL
-    ,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+
     4,
-    (TT_CMap_ValidateFunc)   tt_cmap4_validate,
-    (TT_CMap_Info_GetFunc)   tt_cmap4_get_info
-  )
+    (TT_CMap_ValidateFunc)tt_cmap4_validate,
+    (TT_CMap_Info_GetFunc)tt_cmap4_get_info )
 
 #endif /* TT_CONFIG_CMAP_FORMAT_4 */
 
@@ -1456,7 +1468,7 @@
       }
     }
 
-    return SFNT_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
@@ -1532,24 +1544,28 @@
     cmap_info->format   = 6;
     cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p );
 
-    return SFNT_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
-  FT_DEFINE_TT_CMAP(tt_cmap6_class_rec,
-      sizeof ( TT_CMapRec ),
+  FT_DEFINE_TT_CMAP(
+    tt_cmap6_class_rec,
+    sizeof ( TT_CMapRec ),
 
-      (FT_CMap_InitFunc)     tt_cmap_init,
-      (FT_CMap_DoneFunc)     NULL,
-      (FT_CMap_CharIndexFunc)tt_cmap6_char_index,
-      (FT_CMap_CharNextFunc) tt_cmap6_char_next,
+    (FT_CMap_InitFunc)     tt_cmap_init,
+    (FT_CMap_DoneFunc)     NULL,
+    (FT_CMap_CharIndexFunc)tt_cmap6_char_index,
+    (FT_CMap_CharNextFunc) tt_cmap6_char_next,
 
-      NULL, NULL, NULL, NULL, NULL
-    ,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+
     6,
-    (TT_CMap_ValidateFunc)   tt_cmap6_validate,
-    (TT_CMap_Info_GetFunc)   tt_cmap6_get_info
-  )
+    (TT_CMap_ValidateFunc)tt_cmap6_validate,
+    (TT_CMap_Info_GetFunc)tt_cmap6_get_info )
 
 #endif /* TT_CONFIG_CMAP_FORMAT_6 */
 
@@ -1700,7 +1716,7 @@
       }
     }
 
-    return SFNT_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
@@ -1785,24 +1801,28 @@
     cmap_info->format   = 8;
     cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
 
-    return SFNT_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
-  FT_DEFINE_TT_CMAP(tt_cmap8_class_rec,
-      sizeof ( TT_CMapRec ),
+  FT_DEFINE_TT_CMAP(
+    tt_cmap8_class_rec,
+    sizeof ( TT_CMapRec ),
 
-      (FT_CMap_InitFunc)     tt_cmap_init,
-      (FT_CMap_DoneFunc)     NULL,
-      (FT_CMap_CharIndexFunc)tt_cmap8_char_index,
-      (FT_CMap_CharNextFunc) tt_cmap8_char_next,
+    (FT_CMap_InitFunc)     tt_cmap_init,
+    (FT_CMap_DoneFunc)     NULL,
+    (FT_CMap_CharIndexFunc)tt_cmap8_char_index,
+    (FT_CMap_CharNextFunc) tt_cmap8_char_next,
 
-      NULL, NULL, NULL, NULL, NULL
-    ,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+
     8,
-    (TT_CMap_ValidateFunc)   tt_cmap8_validate,
-    (TT_CMap_Info_GetFunc)   tt_cmap8_get_info
-  )
+    (TT_CMap_ValidateFunc)tt_cmap8_validate,
+    (TT_CMap_Info_GetFunc)tt_cmap8_get_info )
 
 #endif /* TT_CONFIG_CMAP_FORMAT_8 */
 
@@ -1867,7 +1887,7 @@
       }
     }
 
-    return SFNT_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
@@ -1934,24 +1954,28 @@
     cmap_info->format   = 10;
     cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
 
-    return SFNT_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
-  FT_DEFINE_TT_CMAP(tt_cmap10_class_rec,
-      sizeof ( TT_CMapRec ),
+  FT_DEFINE_TT_CMAP(
+    tt_cmap10_class_rec,
+    sizeof ( TT_CMapRec ),
 
-      (FT_CMap_InitFunc)     tt_cmap_init,
-      (FT_CMap_DoneFunc)     NULL,
-      (FT_CMap_CharIndexFunc)tt_cmap10_char_index,
-      (FT_CMap_CharNextFunc) tt_cmap10_char_next,
+    (FT_CMap_InitFunc)     tt_cmap_init,
+    (FT_CMap_DoneFunc)     NULL,
+    (FT_CMap_CharIndexFunc)tt_cmap10_char_index,
+    (FT_CMap_CharNextFunc) tt_cmap10_char_next,
 
-      NULL, NULL, NULL, NULL, NULL
-    ,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+
     10,
-    (TT_CMap_ValidateFunc)   tt_cmap10_validate,
-    (TT_CMap_Info_GetFunc)   tt_cmap10_get_info
-  )
+    (TT_CMap_ValidateFunc)tt_cmap10_validate,
+    (TT_CMap_Info_GetFunc)tt_cmap10_get_info )
 
 #endif /* TT_CONFIG_CMAP_FORMAT_10 */
 
@@ -2010,7 +2034,7 @@
 
     cmap->valid      = 0;
 
-    return SFNT_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
@@ -2063,7 +2087,7 @@
       }
     }
 
-    return SFNT_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
@@ -2254,24 +2278,28 @@
     cmap_info->format   = 12;
     cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
 
-    return SFNT_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
-  FT_DEFINE_TT_CMAP(tt_cmap12_class_rec,
-      sizeof ( TT_CMap12Rec ),
+  FT_DEFINE_TT_CMAP(
+    tt_cmap12_class_rec,
+    sizeof ( TT_CMap12Rec ),
 
-      (FT_CMap_InitFunc)     tt_cmap12_init,
-      (FT_CMap_DoneFunc)     NULL,
-      (FT_CMap_CharIndexFunc)tt_cmap12_char_index,
-      (FT_CMap_CharNextFunc) tt_cmap12_char_next,
+    (FT_CMap_InitFunc)     tt_cmap12_init,
+    (FT_CMap_DoneFunc)     NULL,
+    (FT_CMap_CharIndexFunc)tt_cmap12_char_index,
+    (FT_CMap_CharNextFunc) tt_cmap12_char_next,
 
-      NULL, NULL, NULL, NULL, NULL
-    ,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+
     12,
-    (TT_CMap_ValidateFunc)   tt_cmap12_validate,
-    (TT_CMap_Info_GetFunc)   tt_cmap12_get_info
-  )
+    (TT_CMap_ValidateFunc)tt_cmap12_validate,
+    (TT_CMap_Info_GetFunc)tt_cmap12_get_info )
 
 #endif /* TT_CONFIG_CMAP_FORMAT_12 */
 
@@ -2330,7 +2358,7 @@
 
     cmap->valid      = 0;
 
-    return SFNT_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
@@ -2338,9 +2366,9 @@
   tt_cmap13_validate( FT_Byte*      table,
                       FT_Validator  valid )
   {
-    FT_Byte*   p;
-    FT_ULong   length;
-    FT_ULong   num_groups;
+    FT_Byte*  p;
+    FT_ULong  length;
+    FT_ULong  num_groups;
 
 
     if ( table + 16 > valid->limit )
@@ -2383,7 +2411,7 @@
       }
     }
 
-    return SFNT_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
@@ -2490,7 +2518,6 @@
 
       /* if `char_code' is not in any group, then `mid' is */
       /* the group nearest to `char_code'                  */
-      /*                                                   */
 
       if ( char_code > end )
       {
@@ -2570,24 +2597,28 @@
     cmap_info->format   = 13;
     cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p );
 
-    return SFNT_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
-  FT_DEFINE_TT_CMAP(tt_cmap13_class_rec,
-      sizeof ( TT_CMap13Rec ),
+  FT_DEFINE_TT_CMAP(
+    tt_cmap13_class_rec,
+    sizeof ( TT_CMap13Rec ),
 
-      (FT_CMap_InitFunc)     tt_cmap13_init,
-      (FT_CMap_DoneFunc)     NULL,
-      (FT_CMap_CharIndexFunc)tt_cmap13_char_index,
-      (FT_CMap_CharNextFunc) tt_cmap13_char_next,
+    (FT_CMap_InitFunc)     tt_cmap13_init,
+    (FT_CMap_DoneFunc)     NULL,
+    (FT_CMap_CharIndexFunc)tt_cmap13_char_index,
+    (FT_CMap_CharNextFunc) tt_cmap13_char_next,
 
-      NULL, NULL, NULL, NULL, NULL
-    ,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+
     13,
-    (TT_CMap_ValidateFunc)   tt_cmap13_validate,
-    (TT_CMap_Info_GetFunc)   tt_cmap13_get_info
-  )
+    (TT_CMap_ValidateFunc)tt_cmap13_validate,
+    (TT_CMap_Info_GetFunc)tt_cmap13_get_info )
 
 #endif /* TT_CONFIG_CMAP_FORMAT_13 */
 
@@ -2688,8 +2719,8 @@
                     FT_UInt32  num_results,
                     FT_Memory  memory )
   {
-    FT_UInt32 old_max = cmap->max_results;
-    FT_Error  error   = SFNT_Err_Ok;
+    FT_UInt32  old_max = cmap->max_results;
+    FT_Error   error   = FT_Err_Ok;
 
 
     if ( num_results > cmap->max_results )
@@ -2713,11 +2744,11 @@
     cmap->cmap.data = table;
 
     table               += 6;
-    cmap->num_selectors = FT_PEEK_ULONG( table );
-    cmap->max_results   = 0;
-    cmap->results       = NULL;
+    cmap->num_selectors  = FT_PEEK_ULONG( table );
+    cmap->max_results    = 0;
+    cmap->results        = NULL;
 
-    return SFNT_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
@@ -2791,7 +2822,7 @@
         {
           FT_Byte*  ndp         = table + nondefOff;
           FT_ULong  numMappings = TT_NEXT_ULONG( ndp );
-          FT_ULong  i, lastUni = 0;
+          FT_ULong  i, lastUni  = 0;
 
 
           if ( numMappings * 4 > (FT_ULong)( valid->limit - ndp ) )
@@ -2819,7 +2850,7 @@
       }
     }
 
-    return SFNT_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
@@ -2857,7 +2888,7 @@
     /* subtable 14 does not define a language field */
     cmap_info->language = 0xFFFFFFFFUL;
 
-    return SFNT_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
@@ -2965,7 +2996,7 @@
   tt_cmap14_char_var_index( TT_CMap    cmap,
                             TT_CMap    ucmap,
                             FT_UInt32  charcode,
-                            FT_UInt32  variantSelector)
+                            FT_UInt32  variantSelector )
   {
     FT_Byte*  p = tt_cmap14_find_variant( cmap->data + 6, variantSelector );
     FT_ULong  defOff;
@@ -3106,9 +3137,9 @@
 
 
   static FT_UInt32*
-  tt_cmap14_get_def_chars( TT_CMap     cmap,
-                           FT_Byte*    p,
-                           FT_Memory   memory )
+  tt_cmap14_get_def_chars( TT_CMap    cmap,
+                           FT_Byte*   p,
+                           FT_Memory  memory )
   {
     TT_CMap14   cmap14 = (TT_CMap14) cmap;
     FT_UInt32   numRanges;
@@ -3124,7 +3155,7 @@
 
     for ( q = cmap14->results; numRanges > 0; --numRanges )
     {
-      FT_UInt32 uni = (FT_UInt32)TT_NEXT_UINT24( p );
+      FT_UInt32  uni = (FT_UInt32)TT_NEXT_UINT24( p );
 
 
       cnt = FT_NEXT_BYTE( p ) + 1;
@@ -3133,6 +3164,7 @@
         q[0]  = uni;
         uni  += 1;
         q    += 1;
+
       } while ( --cnt != 0 );
     }
     q[0] = 0;
@@ -3306,25 +3338,25 @@
   }
 
 
-  FT_DEFINE_TT_CMAP(tt_cmap14_class_rec,
-      sizeof ( TT_CMap14Rec ),
+  FT_DEFINE_TT_CMAP(
+    tt_cmap14_class_rec,
+    sizeof ( TT_CMap14Rec ),
 
-      (FT_CMap_InitFunc)     tt_cmap14_init,
-      (FT_CMap_DoneFunc)     tt_cmap14_done,
-      (FT_CMap_CharIndexFunc)tt_cmap14_char_index,
-      (FT_CMap_CharNextFunc) tt_cmap14_char_next,
+    (FT_CMap_InitFunc)     tt_cmap14_init,
+    (FT_CMap_DoneFunc)     tt_cmap14_done,
+    (FT_CMap_CharIndexFunc)tt_cmap14_char_index,
+    (FT_CMap_CharNextFunc) tt_cmap14_char_next,
 
-      /* Format 14 extension functions */
-      (FT_CMap_CharVarIndexFunc)    tt_cmap14_char_var_index,
-      (FT_CMap_CharVarIsDefaultFunc)tt_cmap14_char_var_isdefault,
-      (FT_CMap_VariantListFunc)     tt_cmap14_variants,
-      (FT_CMap_CharVariantListFunc) tt_cmap14_char_variants,
-      (FT_CMap_VariantCharListFunc) tt_cmap14_variant_chars
-    ,
+    /* Format 14 extension functions */
+    (FT_CMap_CharVarIndexFunc)    tt_cmap14_char_var_index,
+    (FT_CMap_CharVarIsDefaultFunc)tt_cmap14_char_var_isdefault,
+    (FT_CMap_VariantListFunc)     tt_cmap14_variants,
+    (FT_CMap_CharVariantListFunc) tt_cmap14_char_variants,
+    (FT_CMap_VariantCharListFunc) tt_cmap14_variant_chars,
+
     14,
     (TT_CMap_ValidateFunc)tt_cmap14_validate,
-    (TT_CMap_Info_GetFunc)tt_cmap14_get_info
-  )
+    (TT_CMap_Info_GetFunc)tt_cmap14_get_info )
 
 #endif /* TT_CONFIG_CMAP_FORMAT_14 */
 
@@ -3333,50 +3365,62 @@
 
   static const TT_CMap_Class  tt_cmap_classes[] =
   {
-#define TTCMAPCITEM(a) &a,
+#define TTCMAPCITEM( a )  &a,
 #include "ttcmapc.h"
     NULL,
   };
 
 #else /*FT_CONFIG_OPTION_PIC*/
 
-  void FT_Destroy_Class_tt_cmap_classes(FT_Library library, TT_CMap_Class* clazz)
+  void
+  FT_Destroy_Class_tt_cmap_classes( FT_Library      library,
+                                    TT_CMap_Class*  clazz )
   {
-    FT_Memory memory = library->memory;
+    FT_Memory  memory = library->memory;
+
+
     if ( clazz )
       FT_FREE( clazz );
   }
 
-  FT_Error FT_Create_Class_tt_cmap_classes(FT_Library library, TT_CMap_Class** output_class)
-  {
-    TT_CMap_Class*  clazz;
-    TT_CMap_ClassRec* recs;
-    FT_Error          error;
-    FT_Memory memory = library->memory;
-    int i = 0;
 
-#define TTCMAPCITEM(a) i++;
+  FT_Error
+  FT_Create_Class_tt_cmap_classes( FT_Library       library,
+                                   TT_CMap_Class**  output_class )
+  {
+    TT_CMap_Class*     clazz  = NULL;
+    TT_CMap_ClassRec*  recs;
+    FT_Error           error;
+    FT_Memory          memory = library->memory;
+
+    int  i = 0;
+
+
+#define TTCMAPCITEM( a ) i++;
 #include "ttcmapc.h"
 
-    /* allocate enough space for both the pointers +terminator and the class instances */
-    if ( FT_ALLOC( clazz, sizeof(*clazz)*(i+1)+sizeof(TT_CMap_ClassRec)*i ) )
+    /* allocate enough space for both the pointers */
+    /* plus terminator and the class instances     */
+    if ( FT_ALLOC( clazz, sizeof ( *clazz ) * ( i + 1 ) +
+                          sizeof ( TT_CMap_ClassRec ) * i ) )
       return error;
 
     /* the location of the class instances follows the array of pointers */
-    recs = (TT_CMap_ClassRec*) (((char*)clazz)+(sizeof(*clazz)*(i+1)));
-    i=0;
+    recs = (TT_CMap_ClassRec*)( (char*)clazz +
+                                sizeof ( *clazz ) * ( i + 1 ) );
+    i    = 0;
 
 #undef TTCMAPCITEM
-#define TTCMAPCITEM(a)           \
-    FT_Init_Class_##a(&recs[i]); \
-    clazz[i] = &recs[i];         \
+#define  TTCMAPCITEM( a )             \
+    FT_Init_Class_ ## a( &recs[i] );  \
+    clazz[i] = &recs[i];              \
     i++;
 #include "ttcmapc.h"
 
     clazz[i] = NULL;
 
     *output_class = clazz;
-    return SFNT_Err_Ok;
+    return FT_Err_Ok;
   }
 
 #endif /*FT_CONFIG_OPTION_PIC*/
@@ -3398,7 +3442,7 @@
 
 
     if ( !p || p + 4 > limit )
-      return SFNT_Err_Invalid_Table;
+      return FT_THROW( Invalid_Table );
 
     /* only recognize format 0 */
     if ( TT_NEXT_USHORT( p ) != 0 )
@@ -3407,14 +3451,16 @@
       FT_ERROR(( "tt_face_build_cmaps:"
                  " unsupported `cmap' table format = %d\n",
                  TT_PEEK_USHORT( p ) ));
-      return SFNT_Err_Invalid_Table;
+      return FT_THROW( Invalid_Table );
     }
 
     num_cmaps = TT_NEXT_USHORT( p );
+
 #ifdef FT_MAX_CHARMAP_CACHEABLE
     if ( num_cmaps > FT_MAX_CHARMAP_CACHEABLE )
-      FT_ERROR(( "tt_face_build_cmaps: too many cmap subtables(%d) "
-                 "subtable#%d and later are loaded but cannot be searched\n",
+      FT_ERROR(( "tt_face_build_cmaps: too many cmap subtables (%d)\n"
+                 "                     subtable #%d and higher are loaded"
+                 "                     but cannot be searched\n",
                  num_cmaps, FT_MAX_CHARMAP_CACHEABLE + 1 ));
 #endif
 
@@ -3434,7 +3480,7 @@
       {
         FT_Byte* volatile              cmap   = table + offset;
         volatile FT_UInt               format = TT_PEEK_USHORT( cmap );
-        const TT_CMap_Class* volatile  pclazz = FT_TT_CMAP_CLASSES_GET;
+        const TT_CMap_Class* volatile  pclazz = TT_CMAP_CLASSES_GET;
         TT_CMap_Class volatile         clazz;
 
 
@@ -3444,7 +3490,7 @@
           if ( clazz->format == format )
           {
             volatile TT_ValidatorRec  valid;
-            volatile FT_Error         error = SFNT_Err_Ok;
+            volatile FT_Error         error = FT_Err_Ok;
 
 
             ft_validator_init( FT_VALIDATOR( &valid ), cmap, limit,
@@ -3452,8 +3498,7 @@
 
             valid.num_glyphs = (FT_UInt)face->max_profile.numGlyphs;
 
-            if ( ft_setjmp(
-              *((ft_jmp_buf*)&FT_VALIDATOR( &valid )->jump_buffer) ) == 0 )
+            if ( ft_setjmp( FT_VALIDATOR( &valid )->jump_buffer) == 0 )
             {
               /* validate this cmap sub-table */
               error = clazz->validate( cmap, FT_VALIDATOR( &valid ) );
@@ -3464,9 +3509,9 @@
               FT_CMap  ttcmap;
 
 
-              /* It might make sense to store the single variation selector */
-              /* cmap somewhere special.  But it would have to be in the    */
-              /* public FT_FaceRec, and we can't change that.               */
+              /* It might make sense to store the single variation         */
+              /* selector cmap somewhere special.  But it would have to be */
+              /* in the public FT_FaceRec, and we can't change that.       */
 
               if ( !FT_CMap_New( (FT_CMap_Class)clazz,
                                  cmap, &charmap, &ttcmap ) )
@@ -3493,7 +3538,7 @@
       }
     }
 
-    return SFNT_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
diff --git a/src/sfnt/ttcmap.h b/src/sfnt/ttcmap.h
index 94f7978..0fde167 100644
--- a/src/sfnt/ttcmap.h
+++ b/src/sfnt/ttcmap.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    TrueType character mapping table (cmap) support (specification).     */
 /*                                                                         */
-/*  Copyright 2002, 2003, 2004, 2005 by                                    */
+/*  Copyright 2002-2005, 2009, 2012 by                                     */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -55,47 +55,80 @@
 
   } TT_CMap_ClassRec;
 
+
 #ifndef FT_CONFIG_OPTION_PIC
 
-#define FT_DEFINE_TT_CMAP(class_, size_, init_, done_, char_index_,          \
-    char_next_, char_var_index_, char_var_default_, variant_list_,           \
-    charvariant_list_,variantchar_list_,                                     \
-    format_, validate_, get_cmap_info_)                                      \
-  FT_CALLBACK_TABLE_DEF                                                      \
-  const TT_CMap_ClassRec class_ =                                            \
-  {                                                                          \
-    {size_, init_, done_, char_index_,                                       \
-     char_next_, char_var_index_, char_var_default_, variant_list_,          \
-     charvariant_list_, variantchar_list_},                                  \
-    format_, validate_, get_cmap_info_                                       \
+#define FT_DEFINE_TT_CMAP( class_,             \
+                           size_,              \
+                           init_,              \
+                           done_,              \
+                           char_index_,        \
+                           char_next_,         \
+                           char_var_index_,    \
+                           char_var_default_,  \
+                           variant_list_,      \
+                           charvariant_list_,  \
+                           variantchar_list_,  \
+                           format_,            \
+                           validate_,          \
+                           get_cmap_info_ )    \
+  FT_CALLBACK_TABLE_DEF                        \
+  const TT_CMap_ClassRec  class_ =             \
+  {                                            \
+    { size_,                                   \
+      init_,                                   \
+      done_,                                   \
+      char_index_,                             \
+      char_next_,                              \
+      char_var_index_,                         \
+      char_var_default_,                       \
+      variant_list_,                           \
+      charvariant_list_,                       \
+      variantchar_list_                        \
+    },                                         \
+                                               \
+    format_,                                   \
+    validate_,                                 \
+    get_cmap_info_                             \
   };
 
 #else /* FT_CONFIG_OPTION_PIC */
 
-#define FT_DEFINE_TT_CMAP(class_, size_, init_, done_, char_index_,          \
-    char_next_, char_var_index_, char_var_default_, variant_list_,           \
-    charvariant_list_,variantchar_list_,                                     \
-    format_, validate_, get_cmap_info_)                                      \
-  void                                                                       \
-  FT_Init_Class_##class_( TT_CMap_ClassRec*  clazz )                         \
-  {                                                                          \
-    clazz->clazz.size = size_;                                               \
-    clazz->clazz.init = init_;                                               \
-    clazz->clazz.done = done_;                                               \
-    clazz->clazz.char_index = char_index_;                                   \
-    clazz->clazz.char_next = char_next_;                                     \
-    clazz->clazz.char_var_index = char_var_index_;                           \
-    clazz->clazz.char_var_default = char_var_default_;                       \
-    clazz->clazz.variant_list = variant_list_;                               \
-    clazz->clazz.charvariant_list = charvariant_list_;                       \
-    clazz->clazz.variantchar_list = variantchar_list_;                       \
-    clazz->format = format_;                                                 \
-    clazz->validate = validate_;                                             \
-    clazz->get_cmap_info = get_cmap_info_;                                   \
+#define FT_DEFINE_TT_CMAP( class_,                      \
+                           size_,                       \
+                           init_,                       \
+                           done_,                       \
+                           char_index_,                 \
+                           char_next_,                  \
+                           char_var_index_,             \
+                           char_var_default_,           \
+                           variant_list_,               \
+                           charvariant_list_,           \
+                           variantchar_list_,           \
+                           format_,                     \
+                           validate_,                   \
+                           get_cmap_info_ )             \
+  void                                                  \
+  FT_Init_Class_ ## class_( TT_CMap_ClassRec*  clazz )  \
+  {                                                     \
+    clazz->clazz.size             = size_;              \
+    clazz->clazz.init             = init_;              \
+    clazz->clazz.done             = done_;              \
+    clazz->clazz.char_index       = char_index_;        \
+    clazz->clazz.char_next        = char_next_;         \
+    clazz->clazz.char_var_index   = char_var_index_;    \
+    clazz->clazz.char_var_default = char_var_default_;  \
+    clazz->clazz.variant_list     = variant_list_;      \
+    clazz->clazz.charvariant_list = charvariant_list_;  \
+    clazz->clazz.variantchar_list = variantchar_list_;  \
+    clazz->format                 = format_;            \
+    clazz->validate               = validate_;          \
+    clazz->get_cmap_info          = get_cmap_info_;     \
   }
 
 #endif /* FT_CONFIG_OPTION_PIC */
 
+
   typedef struct  TT_ValidatorRec_
   {
     FT_ValidatorRec  validator;
@@ -104,7 +137,7 @@
   } TT_ValidatorRec, *TT_Validator;
 
 
-#define TT_VALIDATOR( x )          ((TT_Validator)( x ))
+#define TT_VALIDATOR( x )          ( (TT_Validator)( x ) )
 #define TT_VALID_GLYPH_COUNT( x )  TT_VALIDATOR( x )->num_glyphs
 
 
diff --git a/src/sfnt/ttcmapc.h b/src/sfnt/ttcmapc.h
index 4c9c6a5..2ea2043 100644
--- a/src/sfnt/ttcmapc.h
+++ b/src/sfnt/ttcmapc.h
@@ -17,39 +17,40 @@
 
 
 #ifdef TT_CONFIG_CMAP_FORMAT_0
-    TTCMAPCITEM(tt_cmap0_class_rec)
+  TTCMAPCITEM( tt_cmap0_class_rec )
 #endif
 
 #ifdef TT_CONFIG_CMAP_FORMAT_2
-    TTCMAPCITEM(tt_cmap2_class_rec)
+  TTCMAPCITEM( tt_cmap2_class_rec )
 #endif
 
 #ifdef TT_CONFIG_CMAP_FORMAT_4
-    TTCMAPCITEM(tt_cmap4_class_rec)
+  TTCMAPCITEM( tt_cmap4_class_rec )
 #endif
 
 #ifdef TT_CONFIG_CMAP_FORMAT_6
-    TTCMAPCITEM(tt_cmap6_class_rec)
+  TTCMAPCITEM( tt_cmap6_class_rec )
 #endif
 
 #ifdef TT_CONFIG_CMAP_FORMAT_8
-    TTCMAPCITEM(tt_cmap8_class_rec)
+  TTCMAPCITEM( tt_cmap8_class_rec )
 #endif
 
 #ifdef TT_CONFIG_CMAP_FORMAT_10
-    TTCMAPCITEM(tt_cmap10_class_rec)
+  TTCMAPCITEM( tt_cmap10_class_rec )
 #endif
 
 #ifdef TT_CONFIG_CMAP_FORMAT_12
-    TTCMAPCITEM(tt_cmap12_class_rec)
+  TTCMAPCITEM( tt_cmap12_class_rec )
 #endif
 
 #ifdef TT_CONFIG_CMAP_FORMAT_13
-    TTCMAPCITEM(tt_cmap13_class_rec)
+  TTCMAPCITEM( tt_cmap13_class_rec )
 #endif
 
 #ifdef TT_CONFIG_CMAP_FORMAT_14
-    TTCMAPCITEM(tt_cmap14_class_rec)
+  TTCMAPCITEM( tt_cmap14_class_rec )
 #endif
 
+
   /* END */
diff --git a/src/sfnt/ttkern.c b/src/sfnt/ttkern.c
index 4688898..60ee546 100644
--- a/src/sfnt/ttkern.c
+++ b/src/sfnt/ttkern.c
@@ -61,7 +61,7 @@
     {
       FT_ERROR(( "tt_face_load_kern:"
                  " kerning table is too small - ignored\n" ));
-      error = SFNT_Err_Table_Missing;
+      error = FT_THROW( Table_Missing );
       goto Exit;
     }
 
diff --git a/src/sfnt/ttload.c b/src/sfnt/ttload.c
index 5fb9aea..fbe70f7 100644
--- a/src/sfnt/ttload.c
+++ b/src/sfnt/ttload.c
@@ -5,8 +5,7 @@
 /*    Load the basic TrueType tables, i.e., tables that can be either in   */
 /*    TTF or OTF fonts (body).                                             */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,   */
-/*            2010 by                                                      */
+/*  Copyright 1996-2010, 2012, 2013 by                                     */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -143,7 +142,7 @@
         goto Exit;
     }
     else
-      error = SFNT_Err_Table_Missing;
+      error = FT_THROW( Table_Missing );
 
   Exit:
     return error;
@@ -238,7 +237,7 @@
         if ( table.Length < 0x36 )
         {
           FT_TRACE2(( "check_table_dir: `head' table too small\n" ));
-          error = SFNT_Err_Table_Missing;
+          error = FT_THROW( Table_Missing );
           goto Exit;
         }
 
@@ -250,7 +249,7 @@
         {
           FT_TRACE2(( "check_table_dir:"
                       " no magic number found in `head' table\n"));
-          error = SFNT_Err_Table_Missing;
+          error = FT_THROW( Table_Missing );
           goto Exit;
         }
 
@@ -268,14 +267,14 @@
     if ( sfnt->num_tables == 0 )
     {
       FT_TRACE2(( "check_table_dir: no tables found\n" ));
-      error = SFNT_Err_Unknown_File_Format;
+      error = FT_THROW( Unknown_File_Format );
       goto Exit;
     }
 
     /* if `sing' and `meta' tables are present, there is no `head' table */
     if ( has_head || ( has_sing && has_meta ) )
     {
-      error = SFNT_Err_Ok;
+      error = FT_Err_Ok;
       goto Exit;
     }
     else
@@ -286,7 +285,7 @@
 #else
       FT_TRACE2(( " neither `head' nor `sing' table found\n" ));
 #endif
-      error = SFNT_Err_Table_Missing;
+      error = FT_THROW( Table_Missing );
     }
 
   Exit:
@@ -354,7 +353,7 @@
 #if 0
     if ( sfnt.search_range != 1 << ( sfnt.entry_selector + 4 )        ||
          sfnt.search_range + sfnt.range_shift != sfnt.num_tables << 4 )
-      return SFNT_Err_Unknown_File_Format;
+      return FT_THROW( Unknown_File_Format );
 #endif
 
     /* load the table directory */
@@ -362,14 +361,17 @@
     FT_TRACE2(( "-- Number of tables: %10u\n",    sfnt.num_tables ));
     FT_TRACE2(( "-- Format version:   0x%08lx\n", sfnt.format_tag ));
 
-    /* check first */
-    error = check_table_dir( &sfnt, stream );
-    if ( error )
+    if ( sfnt.format_tag != TTAG_OTTO )
     {
-      FT_TRACE2(( "tt_face_load_font_dir:"
-                  " invalid table directory for TrueType\n" ));
+      /* check first */
+      error = check_table_dir( &sfnt, stream );
+      if ( error )
+      {
+        FT_TRACE2(( "tt_face_load_font_dir:"
+                    " invalid table directory for TrueType\n" ));
 
-      goto Exit;
+        goto Exit;
+      }
     }
 
     face->num_tables = sfnt.num_tables;
@@ -480,7 +482,7 @@
       table = tt_face_lookup_table( face, tag );
       if ( !table )
       {
-        error = SFNT_Err_Table_Missing;
+        error = FT_THROW( Table_Missing );
         goto Exit;
       }
 
@@ -495,7 +497,7 @@
     {
       *length = size;
 
-      return SFNT_Err_Ok;
+      return FT_Err_Ok;
     }
 
     if ( length )
@@ -624,7 +626,7 @@
     FT_Error        error;
     TT_MaxProfile*  maxProfile = &face->max_profile;
 
-    const FT_Frame_Field  maxp_fields[] =
+    static const FT_Frame_Field  maxp_fields[] =
     {
 #undef  FT_STRUCTURE
 #define FT_STRUCTURE  TT_MaxProfile
@@ -635,7 +637,7 @@
       FT_FRAME_END
     };
 
-    const FT_Frame_Field  maxp_fields_extra[] =
+    static const FT_Frame_Field  maxp_fields_extra[] =
     {
       FT_FRAME_START( 26 ),
         FT_FRAME_USHORT( maxPoints ),
@@ -721,7 +723,7 @@
   /*************************************************************************/
   /*                                                                       */
   /* <Function>                                                            */
-  /*    tt_face_load_names                                                 */
+  /*    tt_face_load_name                                                  */
   /*                                                                       */
   /* <Description>                                                         */
   /*    Loads the name records.                                            */
@@ -799,7 +801,7 @@
     if ( storage_start > storage_limit )
     {
       FT_ERROR(( "tt_face_load_name: invalid `name' table\n" ));
-      error = SFNT_Err_Name_Table_Missing;
+      error = FT_THROW( Name_Table_Missing );
       goto Exit;
     }
 
@@ -952,7 +954,7 @@
     FT_Error  error;
     TT_OS2*   os2;
 
-    const FT_Frame_Field  os2_fields[] =
+    static const FT_Frame_Field  os2_fields[] =
     {
 #undef  FT_STRUCTURE
 #define FT_STRUCTURE  TT_OS2
@@ -1004,7 +1006,7 @@
       FT_FRAME_END
     };
 
-    const FT_Frame_Field  os2_fields_extra[] =
+    static const FT_Frame_Field  os2_fields_extra[] =
     {
       FT_FRAME_START( 8 ),
         FT_FRAME_ULONG( ulCodePageRange1 ),
@@ -1012,7 +1014,7 @@
       FT_FRAME_END
     };
 
-    const FT_Frame_Field  os2_fields_extra2[] =
+    static const FT_Frame_Field  os2_fields_extra2[] =
     {
       FT_FRAME_START( 10 ),
         FT_FRAME_SHORT ( sxHeight ),
@@ -1125,7 +1127,7 @@
     FT_TRACE3(( "isFixedPitch:   %s\n", post->isFixedPitch
                                         ? "  yes" : "   no" ));
 
-    return SFNT_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
@@ -1233,18 +1235,18 @@
     if ( face->gasp.version >= 2 )
     {
       face->gasp.numRanges = 0;
-      error = SFNT_Err_Invalid_Table;
+      error = FT_THROW( Invalid_Table );
       goto Exit;
     }
 
     num_ranges = face->gasp.numRanges;
     FT_TRACE3(( "numRanges: %u\n", num_ranges ));
 
-    if ( FT_QNEW_ARRAY( gaspranges, num_ranges ) ||
-         FT_FRAME_ENTER( num_ranges * 4L )      )
+    if ( FT_QNEW_ARRAY( face->gasp.gaspRanges, num_ranges ) ||
+         FT_FRAME_ENTER( num_ranges * 4L )                  )
       goto Exit;
 
-    face->gasp.gaspRanges = gaspranges;
+    gaspranges = face->gasp.gaspRanges;
 
     for ( j = 0; j < num_ranges; j++ )
     {
diff --git a/src/sfnt/ttmtx.c b/src/sfnt/ttmtx.c
index 73ac8b2..371a9ed 100644
--- a/src/sfnt/ttmtx.c
+++ b/src/sfnt/ttmtx.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Load the metrics tables common to TTF and OTF fonts (body).          */
 /*                                                                         */
-/*  Copyright 2006-2009, 2011 by                                           */
+/*  Copyright 2006-2009, 2011-2013 by                                      */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -35,13 +35,6 @@
 #define FT_COMPONENT  trace_ttmtx
 
 
-  /*
-   *  Unfortunately, we can't enable our memory optimizations if
-   *  FT_CONFIG_OPTION_OLD_INTERNALS is defined.  This is because at least
-   *  one rogue client (libXfont in the X.Org XServer) is directly accessing
-   *  the metrics.
-   */
-
   /*************************************************************************/
   /*                                                                       */
   /* <Function>                                                            */
@@ -60,8 +53,6 @@
   /* <Return>                                                              */
   /*    FreeType error code.  0 means success.                             */
   /*                                                                       */
-#ifndef FT_CONFIG_OPTION_OLD_INTERNALS
-
   FT_LOCAL_DEF( FT_Error )
   tt_face_load_hmtx( TT_Face    face,
                      FT_Stream  stream,
@@ -97,142 +88,6 @@
     return error;
   }
 
-#else /* !FT_CONFIG_OPTION_OLD_INTERNALS */
-
-  FT_LOCAL_DEF( FT_Error )
-  tt_face_load_hmtx( TT_Face    face,
-                     FT_Stream  stream,
-                     FT_Bool    vertical )
-  {
-    FT_Error   error;
-    FT_Memory  memory = stream->memory;
-
-    FT_ULong   table_len;
-    FT_Long    num_shorts, num_longs, num_shorts_checked;
-
-    TT_LongMetrics*    longs;
-    TT_ShortMetrics**  shorts;
-    FT_Byte*           p;
-
-
-    if ( vertical )
-    {
-      void*   lm = &face->vertical.long_metrics;
-      void**  sm = &face->vertical.short_metrics;
-
-
-      error = face->goto_table( face, TTAG_vmtx, stream, &table_len );
-      if ( error )
-        goto Fail;
-
-      num_longs = face->vertical.number_Of_VMetrics;
-      if ( (FT_ULong)num_longs > table_len / 4 )
-        num_longs = (FT_Long)( table_len / 4 );
-
-      face->vertical.number_Of_VMetrics = 0;
-
-      longs  = (TT_LongMetrics*)lm;
-      shorts = (TT_ShortMetrics**)sm;
-    }
-    else
-    {
-      void*   lm = &face->horizontal.long_metrics;
-      void**  sm = &face->horizontal.short_metrics;
-
-
-      error = face->goto_table( face, TTAG_hmtx, stream, &table_len );
-      if ( error )
-        goto Fail;
-
-      num_longs = face->horizontal.number_Of_HMetrics;
-      if ( (FT_ULong)num_longs > table_len / 4 )
-        num_longs = (FT_Long)( table_len / 4 );
-
-      face->horizontal.number_Of_HMetrics = 0;
-
-      longs  = (TT_LongMetrics*)lm;
-      shorts = (TT_ShortMetrics**)sm;
-    }
-
-    /* never trust derived values */
-
-    num_shorts         = face->max_profile.numGlyphs - num_longs;
-    num_shorts_checked = ( table_len - num_longs * 4L ) / 2;
-
-    if ( num_shorts < 0 )
-    {
-      FT_TRACE0(( "tt_face_load_hmtx:"
-                  " %cmtx has more metrics than glyphs.\n",
-                  vertical ? 'v' : 'h' ));
-
-      /* Adobe simply ignores this problem.  So we shall do the same. */
-#if 0
-      error = vertical ? SFNT_Err_Invalid_Vert_Metrics
-                       : SFNT_Err_Invalid_Horiz_Metrics;
-      goto Exit;
-#else
-      num_shorts = 0;
-#endif
-    }
-
-    if ( FT_QNEW_ARRAY( *longs,  num_longs  ) ||
-         FT_QNEW_ARRAY( *shorts, num_shorts ) )
-      goto Fail;
-
-    if ( FT_FRAME_ENTER( table_len ) )
-      goto Fail;
-
-    p = stream->cursor;
-
-    {
-      TT_LongMetrics  cur   = *longs;
-      TT_LongMetrics  limit = cur + num_longs;
-
-
-      for ( ; cur < limit; cur++ )
-      {
-        cur->advance = FT_NEXT_USHORT( p );
-        cur->bearing = FT_NEXT_SHORT( p );
-      }
-    }
-
-    /* do we have an inconsistent number of metric values? */
-    {
-      TT_ShortMetrics*  cur   = *shorts;
-      TT_ShortMetrics*  limit = cur +
-                                FT_MIN( num_shorts, num_shorts_checked );
-
-
-      for ( ; cur < limit; cur++ )
-        *cur = FT_NEXT_SHORT( p );
-
-      /* We fill up the missing left side bearings with the     */
-      /* last valid value.  Since this will occur for buggy CJK */
-      /* fonts usually only, nothing serious will happen.       */
-      if ( num_shorts > num_shorts_checked && num_shorts_checked > 0 )
-      {
-        FT_Short  val = (*shorts)[num_shorts_checked - 1];
-
-
-        limit = *shorts + num_shorts;
-        for ( ; cur < limit; cur++ )
-          *cur = val;
-      }
-    }
-
-    FT_FRAME_EXIT();
-
-    if ( vertical )
-      face->vertical.number_Of_VMetrics = (FT_UShort)num_longs;
-    else
-      face->horizontal.number_Of_HMetrics = (FT_UShort)num_longs;
-
-  Fail:
-    return error;
-  }
-
-#endif /* !FT_CONFIG_OPTION_OLD_INTERNALS */
-
 
   /*************************************************************************/
   /*                                                                       */
@@ -260,7 +115,7 @@
     FT_Error        error;
     TT_HoriHeader*  header;
 
-    const FT_Frame_Field  metrics_header_fields[] =
+    static const FT_Frame_Field  metrics_header_fields[] =
     {
 #undef  FT_STRUCTURE
 #define FT_STRUCTURE  TT_HoriHeader
@@ -343,8 +198,6 @@
   /*                                                                       */
   /*    advance :: The advance width resp. advance height.                 */
   /*                                                                       */
-#ifndef FT_CONFIG_OPTION_OLD_INTERNALS
-
   FT_LOCAL_DEF( FT_Error )
   tt_face_get_metrics( TT_Face     face,
                        FT_Bool     vertical,
@@ -419,50 +272,8 @@
       *aadvance = 0;
     }
 
-    return SFNT_Err_Ok;
+    return FT_Err_Ok;
   }
 
-#else /* !FT_CONFIG_OPTION_OLD_INTERNALS */
-
-  FT_LOCAL_DEF( FT_Error )
-  tt_face_get_metrics( TT_Face     face,
-                       FT_Bool     vertical,
-                       FT_UInt     gindex,
-                       FT_Short*   abearing,
-                       FT_UShort*  aadvance )
-  {
-    void*           v = &face->vertical;
-    void*           h = &face->horizontal;
-    TT_HoriHeader*  header = vertical ? (TT_HoriHeader*)v
-                                      : (TT_HoriHeader*)h;
-    TT_LongMetrics  longs_m;
-    FT_UShort       k = header->number_Of_HMetrics;
-
-
-    if ( k == 0                                         ||
-         !header->long_metrics                          ||
-         gindex >= (FT_UInt)face->max_profile.numGlyphs )
-    {
-      *abearing = *aadvance = 0;
-      return SFNT_Err_Ok;
-    }
-
-    if ( gindex < (FT_UInt)k )
-    {
-      longs_m   = (TT_LongMetrics)header->long_metrics + gindex;
-      *abearing = longs_m->bearing;
-      *aadvance = longs_m->advance;
-    }
-    else
-    {
-      *abearing = ((TT_ShortMetrics*)header->short_metrics)[gindex - k];
-      *aadvance = ((TT_LongMetrics)header->long_metrics)[k - 1].advance;
-    }
-
-    return SFNT_Err_Ok;
-  }
-
-#endif /* !FT_CONFIG_OPTION_OLD_INTERNALS */
-
 
 /* END */
diff --git a/src/sfnt/ttpost.c b/src/sfnt/ttpost.c
index 6f4bb1d..47a85c0 100644
--- a/src/sfnt/ttpost.c
+++ b/src/sfnt/ttpost.c
@@ -5,7 +5,7 @@
 /*    Postcript name table processing for TrueType and OpenType fonts      */
 /*    (body).                                                              */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003, 2006, 2007, 2008, 2009, 2010 by       */
+/*  Copyright 1996-2003, 2006-2010, 2013 by                                */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -178,7 +178,7 @@
 
     if ( num_glyphs > face->max_profile.numGlyphs )
     {
-      error = SFNT_Err_Invalid_File_Format;
+      error = FT_THROW( Invalid_File_Format );
       goto Exit;
     }
 
@@ -284,7 +284,7 @@
       table->glyph_indices = glyph_indices;
       table->glyph_names   = name_strings;
     }
-    return SFNT_Err_Ok;
+    return FT_Err_Ok;
 
   Fail1:
     {
@@ -325,7 +325,7 @@
     /* check the number of glyphs */
     if ( num_glyphs > face->max_profile.numGlyphs || num_glyphs > 258 )
     {
-      error = SFNT_Err_Invalid_File_Format;
+      error = FT_THROW( Invalid_File_Format );
       goto Exit;
     }
 
@@ -345,7 +345,7 @@
 
         if ( idx < 0 || idx > num_glyphs )
         {
-          error = SFNT_Err_Invalid_File_Format;
+          error = FT_THROW( Invalid_File_Format );
           goto Fail;
         }
       }
@@ -360,7 +360,7 @@
       table->offsets    = offset_table;
     }
 
-    return SFNT_Err_Ok;
+    return FT_Err_Ok;
 
   Fail:
     FT_FREE( offset_table );
@@ -402,7 +402,7 @@
     else if ( format == 0x00028000L )
       error = load_format_25( face, stream, post_limit );
     else
-      error = SFNT_Err_Invalid_File_Format;
+      error = FT_THROW( Invalid_File_Format );
 
     face->postscript_names.loaded = 1;
 
@@ -488,15 +488,15 @@
 
 
     if ( !face )
-      return SFNT_Err_Invalid_Face_Handle;
+      return FT_THROW( Invalid_Face_Handle );
 
     if ( idx >= (FT_UInt)face->max_profile.numGlyphs )
-      return SFNT_Err_Invalid_Glyph_Index;
+      return FT_THROW( Invalid_Glyph_Index );
 
 #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
     psnames = (FT_Service_PsCMaps)face->psnames;
     if ( !psnames )
-      return SFNT_Err_Unimplemented_Feature;
+      return FT_THROW( Unimplemented_Feature );
 #endif
 
     names = &face->postscript_names;
@@ -556,7 +556,7 @@
     /* nothing to do for format == 0x00030000L */
 
   End:
-    return SFNT_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
diff --git a/src/sfnt/ttsbit.c b/src/sfnt/ttsbit.c
index 283ba7e..cd3e5a4 100644
--- a/src/sfnt/ttsbit.c
+++ b/src/sfnt/ttsbit.c
@@ -4,10 +4,12 @@
 /*                                                                         */
 /*    TrueType and OpenType embedded bitmap support (body).                */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,   */
-/*            2010 by                                                      */
+/*  Copyright 2005-2009, 2013 by                                           */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
+/*  Copyright 2013 by Google, Inc.                                         */
+/*  Google Author(s): Behdad Esfahbod.                                     */
+/*                                                                         */
 /*  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     */
@@ -16,29 +18,18 @@
 /*                                                                         */
 /***************************************************************************/
 
-#include <ft2build.h>
-#include FT_INTERNAL_DEBUG_H
-#include FT_INTERNAL_STREAM_H
-#include FT_TRUETYPE_TAGS_H
-
-  /*
-   *  Alas, the memory-optimized sbit loader can't be used when implementing
-   *  the `old internals' hack
-   */
-#ifndef FT_CONFIG_OPTION_OLD_INTERNALS
-
-#include "ttsbit0.c"
-
-#else /* FT_CONFIG_OPTION_OLD_INTERNALS */
 
 #include <ft2build.h>
 #include FT_INTERNAL_DEBUG_H
 #include FT_INTERNAL_STREAM_H
 #include FT_TRUETYPE_TAGS_H
+#include FT_BITMAP_H
 #include "ttsbit.h"
 
 #include "sferrors.h"
 
+#include "pngshim.h"
+
 
   /*************************************************************************/
   /*                                                                       */
@@ -50,597 +41,84 @@
 #define FT_COMPONENT  trace_ttsbit
 
 
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    blit_sbit                                                          */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Blits a bitmap from an input stream into a given target.  Supports */
-  /*    x and y offsets as well as byte padded lines.                      */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    target      :: The target bitmap/pixmap.                           */
-  /*                                                                       */
-  /*    source      :: The input packed bitmap data.                       */
-  /*                                                                       */
-  /*    line_bits   :: The number of bits per line.                        */
-  /*                                                                       */
-  /*    byte_padded :: A flag which is true if lines are byte-padded.      */
-  /*                                                                       */
-  /*    x_offset    :: The horizontal offset.                              */
-  /*                                                                       */
-  /*    y_offset    :: The vertical offset.                                */
-  /*                                                                       */
-  /* <Note>                                                                */
-  /*    IMPORTANT: The x and y offsets are relative to the top corner of   */
-  /*               the target bitmap (unlike the normal TrueType           */
-  /*               convention).  A positive y offset indicates a downwards */
-  /*               direction!                                              */
-  /*                                                                       */
-  static void
-  blit_sbit( FT_Bitmap*  target,
-             FT_Byte*    source,
-             FT_Int      line_bits,
-             FT_Bool     byte_padded,
-             FT_Int      x_offset,
-             FT_Int      y_offset,
-             FT_Int      source_height )
-  {
-    FT_Byte*   line_buff;
-    FT_Int     line_incr;
-    FT_Int     height;
-
-    FT_UShort  acc;
-    FT_UInt    loaded;
-
-
-    /* first of all, compute starting write position */
-    line_incr = target->pitch;
-    line_buff = target->buffer;
-
-    if ( line_incr < 0 )
-      line_buff -= line_incr * ( target->rows - 1 );
-
-    line_buff += ( x_offset >> 3 ) + y_offset * line_incr;
-
-    /***********************************************************************/
-    /*                                                                     */
-    /* We use the extra-classic `accumulator' trick to extract the bits    */
-    /* from the source byte stream.                                        */
-    /*                                                                     */
-    /* Namely, the variable `acc' is a 16-bit accumulator containing the   */
-    /* last `loaded' bits from the input stream.  The bits are shifted to  */
-    /* the upmost position in `acc'.                                       */
-    /*                                                                     */
-    /***********************************************************************/
-
-    acc    = 0;  /* clear accumulator   */
-    loaded = 0;  /* no bits were loaded */
-
-    for ( height = source_height; height > 0; height-- )
-    {
-      FT_Byte*  cur   = line_buff;        /* current write cursor          */
-      FT_Int    count = line_bits;        /* # of bits to extract per line */
-      FT_Byte   shift = (FT_Byte)( x_offset & 7 ); /* current write shift  */
-      FT_Byte   space = (FT_Byte)( 8 - shift );
-
-
-      /* first of all, read individual source bytes */
-      if ( count >= 8 )
-      {
-        count -= 8;
-        {
-          do
-          {
-            FT_Byte  val;
-
-
-            /* ensure that there are at least 8 bits in the accumulator */
-            if ( loaded < 8 )
-            {
-              acc    |= (FT_UShort)((FT_UShort)*source++ << ( 8 - loaded ));
-              loaded += 8;
-            }
-
-            /* now write one byte */
-            val = (FT_Byte)( acc >> 8 );
-            if ( shift )
-            {
-              cur[0] |= (FT_Byte)( val >> shift );
-              cur[1] |= (FT_Byte)( val << space );
-            }
-            else
-              cur[0] |= val;
-
-            cur++;
-            acc   <<= 8;  /* remove bits from accumulator */
-            loaded -= 8;
-            count  -= 8;
-
-          } while ( count >= 0 );
-        }
-
-        /* restore `count' to correct value */
-        count += 8;
-      }
-
-      /* now write remaining bits (count < 8) */
-      if ( count > 0 )
-      {
-        FT_Byte  val;
-
-
-        /* ensure that there are at least `count' bits in the accumulator */
-        if ( (FT_Int)loaded < count )
-        {
-          acc    |= (FT_UShort)((FT_UShort)*source++ << ( 8 - loaded ));
-          loaded += 8;
-        }
-
-        /* now write remaining bits */
-        val     = (FT_Byte)( ( (FT_Byte)( acc >> 8 ) ) & ~( 0xFF >> count ) );
-        cur[0] |= (FT_Byte)( val >> shift );
-
-        if ( count > space )
-          cur[1] |= (FT_Byte)( val << space );
-
-        acc   <<= count;
-        loaded -= count;
-      }
-
-      /* now, skip to next line */
-      if ( byte_padded )
-      {
-        acc    = 0;
-        loaded = 0;   /* clear accumulator on byte-padded lines */
-      }
-
-      line_buff += line_incr;
-    }
-  }
-
-
-  static const FT_Frame_Field  sbit_metrics_fields[] =
-  {
-#undef  FT_STRUCTURE
-#define FT_STRUCTURE  TT_SBit_MetricsRec
-
-    FT_FRAME_START( 8 ),
-      FT_FRAME_BYTE( height ),
-      FT_FRAME_BYTE( width ),
-
-      FT_FRAME_CHAR( horiBearingX ),
-      FT_FRAME_CHAR( horiBearingY ),
-      FT_FRAME_BYTE( horiAdvance ),
-
-      FT_FRAME_CHAR( vertBearingX ),
-      FT_FRAME_CHAR( vertBearingY ),
-      FT_FRAME_BYTE( vertAdvance ),
-    FT_FRAME_END
-  };
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    Load_SBit_Const_Metrics                                            */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Loads the metrics for `EBLC' index tables format 2 and 5.          */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    range  :: The target range.                                        */
-  /*                                                                       */
-  /*    stream :: The input stream.                                        */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    FreeType error code.  0 means success.                             */
-  /*                                                                       */
-  static FT_Error
-  Load_SBit_Const_Metrics( TT_SBit_Range  range,
-                           FT_Stream      stream )
-  {
-    FT_Error  error;
-
-
-    if ( FT_READ_ULONG( range->image_size ) )
-      return error;
-
-    return FT_STREAM_READ_FIELDS( sbit_metrics_fields, &range->metrics );
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    Load_SBit_Range_Codes                                              */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Loads the range codes for `EBLC' index tables format 4 and 5.      */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    range        :: The target range.                                  */
-  /*                                                                       */
-  /*    stream       :: The input stream.                                  */
-  /*                                                                       */
-  /*    load_offsets :: A flag whether to load the glyph offset table.     */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    FreeType error code.  0 means success.                             */
-  /*                                                                       */
-  static FT_Error
-  Load_SBit_Range_Codes( TT_SBit_Range  range,
-                         FT_Stream      stream,
-                         FT_Bool        load_offsets )
-  {
-    FT_Error   error;
-    FT_ULong   count, n, size;
-    FT_Memory  memory = stream->memory;
-
-
-    if ( FT_READ_ULONG( count ) )
-      goto Exit;
-
-    range->num_glyphs = count;
-
-    /* Allocate glyph offsets table if needed */
-    if ( load_offsets )
-    {
-      if ( FT_NEW_ARRAY( range->glyph_offsets, count ) )
-        goto Exit;
-
-      size = count * 4L;
-    }
-    else
-      size = count * 2L;
-
-    /* Allocate glyph codes table and access frame */
-    if ( FT_NEW_ARRAY ( range->glyph_codes, count ) ||
-         FT_FRAME_ENTER( size )                     )
-      goto Exit;
-
-    for ( n = 0; n < count; n++ )
-    {
-      range->glyph_codes[n] = FT_GET_USHORT();
-
-      if ( load_offsets )
-        range->glyph_offsets[n] = (FT_ULong)range->image_offset +
-                                  FT_GET_USHORT();
-    }
-
-    FT_FRAME_EXIT();
-
-  Exit:
-    return error;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    Load_SBit_Range                                                    */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Loads a given `EBLC' index/range table.                            */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    range  :: The target range.                                        */
-  /*                                                                       */
-  /*    stream :: The input stream.                                        */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    FreeType error code.  0 means success.                             */
-  /*                                                                       */
-  static FT_Error
-  Load_SBit_Range( TT_SBit_Range  range,
-                   FT_Stream      stream )
-  {
-    FT_Error   error;
-    FT_Memory  memory = stream->memory;
-
-
-    switch( range->index_format )
-    {
-    case 1:   /* variable metrics with 4-byte offsets */
-    case 3:   /* variable metrics with 2-byte offsets */
-      {
-        FT_ULong  num_glyphs, n;
-        FT_Int    size_elem;
-        FT_Bool   large = FT_BOOL( range->index_format == 1 );
-
-
-
-        if ( range->last_glyph < range->first_glyph )
-        {
-          error = SFNT_Err_Invalid_File_Format;
-          goto Exit;
-        }
-
-        num_glyphs        = range->last_glyph - range->first_glyph + 1L;
-        range->num_glyphs = num_glyphs;
-        num_glyphs++;                       /* XXX: BEWARE - see spec */
-
-        size_elem = large ? 4 : 2;
-
-        if ( FT_NEW_ARRAY( range->glyph_offsets, num_glyphs ) ||
-             FT_FRAME_ENTER( num_glyphs * size_elem )         )
-          goto Exit;
-
-        for ( n = 0; n < num_glyphs; n++ )
-          range->glyph_offsets[n] = (FT_ULong)( range->image_offset +
-                                                ( large ? FT_GET_ULONG()
-                                                        : FT_GET_USHORT() ) );
-        FT_FRAME_EXIT();
-      }
-      break;
-
-    case 2:   /* all glyphs have identical metrics */
-      error = Load_SBit_Const_Metrics( range, stream );
-      break;
-
-    case 4:
-      error = Load_SBit_Range_Codes( range, stream, 1 );
-      break;
-
-    case 5:
-      error = Load_SBit_Const_Metrics( range, stream );
-      if ( !error )
-        error = Load_SBit_Range_Codes( range, stream, 0 );
-      break;
-
-    default:
-      error = SFNT_Err_Invalid_File_Format;
-    }
-
-  Exit:
-    return error;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    tt_face_load_eblc                                                  */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Loads the table of embedded bitmap sizes for this face.            */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    face   :: The target face object.                                  */
-  /*                                                                       */
-  /*    stream :: The input stream.                                        */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    FreeType error code.  0 means success.                             */
-  /*                                                                       */
   FT_LOCAL_DEF( FT_Error )
   tt_face_load_eblc( TT_Face    face,
                      FT_Stream  stream )
   {
-    FT_Error   error  = SFNT_Err_Ok;
-    FT_Memory  memory = stream->memory;
-    FT_Fixed   version;
-    FT_ULong   num_strikes;
-    FT_ULong   table_base;
-
-    static const FT_Frame_Field  sbit_line_metrics_fields[] =
-    {
-#undef  FT_STRUCTURE
-#define FT_STRUCTURE  TT_SBit_LineMetricsRec
-
-      /* no FT_FRAME_START */
-        FT_FRAME_CHAR( ascender ),
-        FT_FRAME_CHAR( descender ),
-        FT_FRAME_BYTE( max_width ),
-
-        FT_FRAME_CHAR( caret_slope_numerator ),
-        FT_FRAME_CHAR( caret_slope_denominator ),
-        FT_FRAME_CHAR( caret_offset ),
-
-        FT_FRAME_CHAR( min_origin_SB ),
-        FT_FRAME_CHAR( min_advance_SB ),
-        FT_FRAME_CHAR( max_before_BL ),
-        FT_FRAME_CHAR( min_after_BL ),
-        FT_FRAME_CHAR( pads[0] ),
-        FT_FRAME_CHAR( pads[1] ),
-      FT_FRAME_END
-    };
-
-    static const FT_Frame_Field  strike_start_fields[] =
-    {
-#undef  FT_STRUCTURE
-#define FT_STRUCTURE  TT_SBit_StrikeRec
-
-      /* no FT_FRAME_START */
-        FT_FRAME_ULONG( ranges_offset ),
-        FT_FRAME_SKIP_LONG,
-        FT_FRAME_ULONG( num_ranges ),
-        FT_FRAME_ULONG( color_ref ),
-      FT_FRAME_END
-    };
-
-    static const FT_Frame_Field  strike_end_fields[] =
-    {
-      /* no FT_FRAME_START */
-        FT_FRAME_USHORT( start_glyph ),
-        FT_FRAME_USHORT( end_glyph ),
-        FT_FRAME_BYTE  ( x_ppem ),
-        FT_FRAME_BYTE  ( y_ppem ),
-        FT_FRAME_BYTE  ( bit_depth ),
-        FT_FRAME_CHAR  ( flags ),
-      FT_FRAME_END
-    };
+    FT_Error  error = FT_Err_Ok;
+    FT_Fixed  version;
+    FT_ULong  num_strikes, table_size;
+    FT_Byte*  p;
+    FT_Byte*  p_limit;
+    FT_UInt   count;
 
 
-    face->num_sbit_strikes = 0;
+    face->sbit_num_strikes = 0;
 
     /* this table is optional */
-    error = face->goto_table( face, TTAG_EBLC, stream, 0 );
+    error = face->goto_table( face, TTAG_CBLC, stream, &table_size );
     if ( error )
-      error = face->goto_table( face, TTAG_bloc, stream, 0 );
+      error = face->goto_table( face, TTAG_EBLC, stream, &table_size );
+    if ( error )
+      error = face->goto_table( face, TTAG_bloc, stream, &table_size );
     if ( error )
       goto Exit;
 
-    table_base = FT_STREAM_POS();
-    if ( FT_FRAME_ENTER( 8L ) )
+    if ( table_size < 8 )
+    {
+      FT_ERROR(( "tt_face_load_sbit_strikes: table too short\n" ));
+      error = FT_THROW( Invalid_File_Format );
+      goto Exit;
+    }
+
+    if ( FT_FRAME_EXTRACT( table_size, face->sbit_table ) )
       goto Exit;
 
-    version     = FT_GET_LONG();
-    num_strikes = FT_GET_ULONG();
+    face->sbit_table_size = table_size;
 
-    FT_FRAME_EXIT();
+    p       = face->sbit_table;
+    p_limit = p + table_size;
 
-    /* check version number and strike count */
-    if ( version     != 0x00020000L ||
-         num_strikes >= 0x10000L    )
+    version     = FT_NEXT_ULONG( p );
+    num_strikes = FT_NEXT_ULONG( p );
+
+    if ( version != 0x00020000UL || num_strikes >= 0x10000UL )
     {
       FT_ERROR(( "tt_face_load_sbit_strikes: invalid table version\n" ));
-      error = SFNT_Err_Invalid_File_Format;
-
-      goto Exit;
+      error = FT_THROW( Invalid_File_Format );
+      goto Fail;
     }
 
-    /* allocate the strikes table */
-    if ( FT_NEW_ARRAY( face->sbit_strikes, num_strikes ) )
-      goto Exit;
+    /*
+     *  Count the number of strikes available in the table.  We are a bit
+     *  paranoid there and don't trust the data.
+     */
+    count = (FT_UInt)num_strikes;
+    if ( 8 + 48UL * count > table_size )
+      count = (FT_UInt)( ( p_limit - p ) / 48 );
 
-    face->num_sbit_strikes = num_strikes;
+    face->sbit_num_strikes = count;
 
-    /* now read each strike table separately */
-    {
-      TT_SBit_Strike  strike = face->sbit_strikes;
-      FT_ULong        count  = num_strikes;
-
-
-      if ( FT_FRAME_ENTER( 48L * num_strikes ) )
-        goto Exit;
-
-      while ( count > 0 )
-      {
-        if ( FT_STREAM_READ_FIELDS( strike_start_fields, strike )             ||
-             FT_STREAM_READ_FIELDS( sbit_line_metrics_fields, &strike->hori ) ||
-             FT_STREAM_READ_FIELDS( sbit_line_metrics_fields, &strike->vert ) ||
-             FT_STREAM_READ_FIELDS( strike_end_fields, strike )               )
-          break;
-
-        count--;
-        strike++;
-      }
-
-      FT_FRAME_EXIT();
-    }
-
-    /* allocate the index ranges for each strike table */
-    {
-      TT_SBit_Strike  strike = face->sbit_strikes;
-      FT_ULong        count  = num_strikes;
-
-
-      while ( count > 0 )
-      {
-        TT_SBit_Range  range;
-        FT_ULong       count2 = strike->num_ranges;
-
-
-        /* read each range */
-        if ( FT_STREAM_SEEK( table_base + strike->ranges_offset ) ||
-             FT_FRAME_ENTER( strike->num_ranges * 8L )            )
-          goto Exit;
-
-        if ( FT_NEW_ARRAY( strike->sbit_ranges, strike->num_ranges ) )
-          goto Exit;
-
-        range = strike->sbit_ranges;
-        while ( count2 > 0 )
-        {
-          range->first_glyph  = FT_GET_USHORT();
-          range->last_glyph   = FT_GET_USHORT();
-          range->table_offset = table_base + strike->ranges_offset +
-                                  FT_GET_ULONG();
-          count2--;
-          range++;
-        }
-
-        FT_FRAME_EXIT();
-
-        /* Now, read each index table */
-        count2 = strike->num_ranges;
-        range  = strike->sbit_ranges;
-        while ( count2 > 0 )
-        {
-          /* Read the header */
-          if ( FT_STREAM_SEEK( range->table_offset ) ||
-               FT_FRAME_ENTER( 8L )                  )
-            goto Exit;
-
-          range->index_format = FT_GET_USHORT();
-          range->image_format = FT_GET_USHORT();
-          range->image_offset = FT_GET_ULONG();
-
-          FT_FRAME_EXIT();
-
-          error = Load_SBit_Range( range, stream );
-          if ( error )
-            goto Exit;
-
-          count2--;
-          range++;
-        }
-
-        count--;
-        strike++;
-      }
-    }
-
+    FT_TRACE3(( "sbit_num_strikes: %u\n", count ));
   Exit:
     return error;
+
+  Fail:
+    FT_FRAME_RELEASE( face->sbit_table );
+    face->sbit_table_size = 0;
+    goto Exit;
   }
 
 
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    tt_face_free_eblc                                                  */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Releases the embedded bitmap tables.                               */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    face :: The target face object.                                    */
-  /*                                                                       */
   FT_LOCAL_DEF( void )
   tt_face_free_eblc( TT_Face  face )
   {
-    FT_Memory       memory       = face->root.memory;
-    TT_SBit_Strike  strike       = face->sbit_strikes;
-    TT_SBit_Strike  strike_limit = strike + face->num_sbit_strikes;
+    FT_Stream  stream = face->root.stream;
 
 
-    if ( strike )
-    {
-      for ( ; strike < strike_limit; strike++ )
-      {
-        TT_SBit_Range  range       = strike->sbit_ranges;
-        TT_SBit_Range  range_limit = range + strike->num_ranges;
-
-
-        if ( range )
-        {
-          for ( ; range < range_limit; range++ )
-          {
-            /* release the glyph offsets and codes tables */
-            /* where appropriate                          */
-            FT_FREE( range->glyph_offsets );
-            FT_FREE( range->glyph_codes );
-          }
-        }
-        FT_FREE( strike->sbit_ranges );
-        strike->num_ranges = 0;
-      }
-      FT_FREE( face->sbit_strikes );
-    }
-    face->num_sbit_strikes = 0;
+    FT_FRAME_RELEASE( face->sbit_table );
+    face->sbit_table_size  = 0;
+    face->sbit_num_strikes = 0;
   }
 
 
@@ -658,790 +136,1013 @@
                                FT_ULong          strike_index,
                                FT_Size_Metrics*  metrics )
   {
-    TT_SBit_Strike  strike;
+    FT_Byte*  strike;
 
 
-    if ( strike_index >= face->num_sbit_strikes )
-      return SFNT_Err_Invalid_Argument;
+    if ( strike_index >= (FT_ULong)face->sbit_num_strikes )
+      return FT_THROW( Invalid_Argument );
 
-    strike = face->sbit_strikes + strike_index;
+    strike = face->sbit_table + 8 + strike_index * 48;
 
-    metrics->x_ppem = strike->x_ppem;
-    metrics->y_ppem = strike->y_ppem;
+    metrics->x_ppem = (FT_UShort)strike[44];
+    metrics->y_ppem = (FT_UShort)strike[45];
 
-    metrics->ascender  = strike->hori.ascender << 6;
-    metrics->descender = strike->hori.descender << 6;
+    metrics->ascender  = (FT_Char)strike[16] << 6;  /* hori.ascender  */
+    metrics->descender = (FT_Char)strike[17] << 6;  /* hori.descender */
+    metrics->height    = metrics->ascender - metrics->descender;
 
     /* XXX: Is this correct? */
-    metrics->max_advance = ( strike->hori.min_origin_SB  +
-                             strike->hori.max_width      +
-                             strike->hori.min_advance_SB ) << 6;
+    metrics->max_advance = ( (FT_Char)strike[22] + /* min_origin_SB  */
+                                      strike[18] + /* max_width      */
+                             (FT_Char)strike[23]   /* min_advance_SB */
+                                                 ) << 6;
 
-    metrics->height = metrics->ascender - metrics->descender;
-
-    return SFNT_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    find_sbit_range                                                    */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Scans a given strike's ranges and return, for a given glyph        */
-  /*    index, the corresponding sbit range, and `EBDT' offset.            */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    glyph_index   :: The glyph index.                                  */
-  /*                                                                       */
-  /*    strike        :: The source/current sbit strike.                   */
-  /*                                                                       */
-  /* <Output>                                                              */
-  /*    arange        :: The sbit range containing the glyph index.        */
-  /*                                                                       */
-  /*    aglyph_offset :: The offset of the glyph data in `EBDT' table.     */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    FreeType error code.  0 means the glyph index was found.           */
-  /*                                                                       */
+  typedef struct  TT_SBitDecoderRec_
+  {
+    TT_Face          face;
+    FT_Stream        stream;
+    FT_Bitmap*       bitmap;
+    TT_SBit_Metrics  metrics;
+    FT_Bool          metrics_loaded;
+    FT_Bool          bitmap_allocated;
+    FT_Byte          bit_depth;
+
+    FT_ULong         ebdt_start;
+    FT_ULong         ebdt_size;
+
+    FT_ULong         strike_index_array;
+    FT_ULong         strike_index_count;
+    FT_Byte*         eblc_base;
+    FT_Byte*         eblc_limit;
+
+  } TT_SBitDecoderRec, *TT_SBitDecoder;
+
+
   static FT_Error
-  find_sbit_range( FT_UInt          glyph_index,
-                   TT_SBit_Strike   strike,
-                   TT_SBit_Range   *arange,
-                   FT_ULong        *aglyph_offset )
+  tt_sbit_decoder_init( TT_SBitDecoder       decoder,
+                        TT_Face              face,
+                        FT_ULong             strike_index,
+                        TT_SBit_MetricsRec*  metrics )
   {
-    TT_SBit_RangeRec  *range, *range_limit;
+    FT_Error   error;
+    FT_Stream  stream = face->root.stream;
+    FT_ULong   ebdt_size;
 
 
-    /* check whether the glyph index is within this strike's */
-    /* glyph range                                           */
-    if ( glyph_index < (FT_UInt)strike->start_glyph ||
-         glyph_index > (FT_UInt)strike->end_glyph   )
-      goto Fail;
-
-    /* scan all ranges in strike */
-    range       = strike->sbit_ranges;
-    range_limit = range + strike->num_ranges;
-    if ( !range )
-      goto Fail;
-
-    for ( ; range < range_limit; range++ )
-    {
-      if ( glyph_index >= (FT_UInt)range->first_glyph &&
-           glyph_index <= (FT_UInt)range->last_glyph  )
-      {
-        FT_UShort  delta = (FT_UShort)( glyph_index - range->first_glyph );
-
-
-        switch ( range->index_format )
-        {
-        case 1:
-        case 3:
-          *aglyph_offset = range->glyph_offsets[delta];
-          break;
-
-        case 2:
-          *aglyph_offset = range->image_offset +
-                           range->image_size * delta;
-          break;
-
-        case 4:
-        case 5:
-          {
-            FT_ULong  n;
-
-
-            for ( n = 0; n < range->num_glyphs; n++ )
-            {
-              if ( (FT_UInt)range->glyph_codes[n] == glyph_index )
-              {
-                if ( range->index_format == 4 )
-                  *aglyph_offset = range->glyph_offsets[n];
-                else
-                  *aglyph_offset = range->image_offset +
-                                   n * range->image_size;
-                goto Found;
-              }
-            }
-          }
-
-        /* fall-through */
-        default:
-          goto Fail;
-        }
-
-      Found:
-        /* return successfully! */
-        *arange  = range;
-        return SFNT_Err_Ok;
-      }
-    }
-
-  Fail:
-    *arange        = 0;
-    *aglyph_offset = 0;
-
-    return SFNT_Err_Invalid_Argument;
-  }
-
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    tt_find_sbit_image                                                 */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Checks whether an embedded bitmap (an `sbit') exists for a given   */
-  /*    glyph, at a given strike.                                          */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    face          :: The target face object.                           */
-  /*                                                                       */
-  /*    glyph_index   :: The glyph index.                                  */
-  /*                                                                       */
-  /*    strike_index  :: The current strike index.                         */
-  /*                                                                       */
-  /* <Output>                                                              */
-  /*    arange        :: The SBit range containing the glyph index.        */
-  /*                                                                       */
-  /*    astrike       :: The SBit strike containing the glyph index.       */
-  /*                                                                       */
-  /*    aglyph_offset :: The offset of the glyph data in `EBDT' table.     */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    FreeType error code.  0 means success.  Returns                    */
-  /*    SFNT_Err_Invalid_Argument if no sbit exists for the requested      */
-  /*    glyph.                                                             */
-  /*                                                                       */
-  FT_LOCAL( FT_Error )
-  tt_find_sbit_image( TT_Face          face,
-                      FT_UInt          glyph_index,
-                      FT_ULong         strike_index,
-                      TT_SBit_Range   *arange,
-                      TT_SBit_Strike  *astrike,
-                      FT_ULong        *aglyph_offset )
-  {
-    FT_Error        error;
-    TT_SBit_Strike  strike;
-
-
-    if ( !face->sbit_strikes                        ||
-         ( face->num_sbit_strikes <= strike_index ) )
-      goto Fail;
-
-    strike = &face->sbit_strikes[strike_index];
-
-    error = find_sbit_range( glyph_index, strike,
-                             arange, aglyph_offset );
+    error = face->goto_table( face, TTAG_CBDT, stream, &ebdt_size );
     if ( error )
-      goto Fail;
+      error = face->goto_table( face, TTAG_EBDT, stream, &ebdt_size );
+    if ( error )
+      error = face->goto_table( face, TTAG_bdat, stream, &ebdt_size );
+    if ( error )
+      goto Exit;
 
-    *astrike = strike;
+    decoder->face    = face;
+    decoder->stream  = stream;
+    decoder->bitmap  = &face->root.glyph->bitmap;
+    decoder->metrics = metrics;
 
-    return SFNT_Err_Ok;
+    decoder->metrics_loaded   = 0;
+    decoder->bitmap_allocated = 0;
 
-  Fail:
-    /* no embedded bitmap for this glyph in face */
-    *arange        = 0;
-    *astrike       = 0;
-    *aglyph_offset = 0;
+    decoder->ebdt_start = FT_STREAM_POS();
+    decoder->ebdt_size  = ebdt_size;
 
-    return SFNT_Err_Invalid_Argument;
-  }
+    decoder->eblc_base  = face->sbit_table;
+    decoder->eblc_limit = face->sbit_table + face->sbit_table_size;
 
-
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    tt_load_sbit_metrics                                               */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Gets the big metrics for a given SBit.                             */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    stream      :: The input stream.                                   */
-  /*                                                                       */
-  /*    range       :: The SBit range containing the glyph.                */
-  /*                                                                       */
-  /* <Output>                                                              */
-  /*    big_metrics :: A big SBit metrics structure for the glyph.         */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    FreeType error code.  0 means success.                             */
-  /*                                                                       */
-  /* <Note>                                                                */
-  /*    The stream cursor must be positioned at the glyph's offset within  */
-  /*    the `EBDT' table before the call.                                  */
-  /*                                                                       */
-  /*    If the image format uses variable metrics, the stream cursor is    */
-  /*    positioned just after the metrics header in the `EBDT' table on    */
-  /*    function exit.                                                     */
-  /*                                                                       */
-  FT_LOCAL( FT_Error )
-  tt_load_sbit_metrics( FT_Stream        stream,
-                        TT_SBit_Range    range,
-                        TT_SBit_Metrics  metrics )
-  {
-    FT_Error  error = SFNT_Err_Ok;
-
-
-    switch ( range->image_format )
+    /* now find the strike corresponding to the index */
     {
-    case 1:
-    case 2:
-    case 8:
-      /* variable small metrics */
+      FT_Byte*  p;
+
+
+      if ( 8 + 48 * strike_index + 3 * 4 + 34 + 1 > face->sbit_table_size )
       {
-        TT_SBit_SmallMetricsRec  smetrics;
-
-        static const FT_Frame_Field  sbit_small_metrics_fields[] =
-        {
-#undef  FT_STRUCTURE
-#define FT_STRUCTURE  TT_SBit_SmallMetricsRec
-
-          FT_FRAME_START( 5 ),
-            FT_FRAME_BYTE( height ),
-            FT_FRAME_BYTE( width ),
-            FT_FRAME_CHAR( bearingX ),
-            FT_FRAME_CHAR( bearingY ),
-            FT_FRAME_BYTE( advance ),
-          FT_FRAME_END
-        };
-
-
-        /* read small metrics */
-        if ( FT_STREAM_READ_FIELDS( sbit_small_metrics_fields, &smetrics ) )
-          goto Exit;
-
-        /* convert it to a big metrics */
-        metrics->height       = smetrics.height;
-        metrics->width        = smetrics.width;
-        metrics->horiBearingX = smetrics.bearingX;
-        metrics->horiBearingY = smetrics.bearingY;
-        metrics->horiAdvance  = smetrics.advance;
-
-        /* these metrics are made up at a higher level when */
-        /* needed.                                          */
-        metrics->vertBearingX = 0;
-        metrics->vertBearingY = 0;
-        metrics->vertAdvance  = 0;
-      }
-      break;
-
-    case 6:
-    case 7:
-    case 9:
-      /* variable big metrics */
-      if ( FT_STREAM_READ_FIELDS( sbit_metrics_fields, metrics ) )
+        error = FT_THROW( Invalid_File_Format );
         goto Exit;
-      break;
+      }
 
-    case 5:
-    default:  /* constant metrics */
-      if ( range->index_format == 2 || range->index_format == 5 )
-        *metrics = range->metrics;
-      else
-        return SFNT_Err_Invalid_File_Format;
-   }
+      p = decoder->eblc_base + 8 + 48 * strike_index;
+
+      decoder->strike_index_array = FT_NEXT_ULONG( p );
+      p                          += 4;
+      decoder->strike_index_count = FT_NEXT_ULONG( p );
+      p                          += 34;
+      decoder->bit_depth          = *p;
+
+      if ( decoder->strike_index_array > face->sbit_table_size             ||
+           decoder->strike_index_array + 8 * decoder->strike_index_count >
+             face->sbit_table_size                                         )
+        error = FT_THROW( Invalid_File_Format );
+    }
 
   Exit:
     return error;
   }
 
 
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    crop_bitmap                                                        */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Crops a bitmap to its tightest bounding box, and adjusts its       */
-  /*    metrics.                                                           */
-  /*                                                                       */
-  /* <InOut>                                                               */
-  /*    map     :: The bitmap.                                             */
-  /*                                                                       */
-  /*    metrics :: The corresponding metrics structure.                    */
-  /*                                                                       */
   static void
-  crop_bitmap( FT_Bitmap*       map,
-               TT_SBit_Metrics  metrics )
+  tt_sbit_decoder_done( TT_SBitDecoder  decoder )
   {
-    /***********************************************************************/
-    /*                                                                     */
-    /* In this situation, some bounding boxes of embedded bitmaps are too  */
-    /* large.  We need to crop it to a reasonable size.                    */
-    /*                                                                     */
-    /*      ---------                                                      */
-    /*      |       |                -----                                 */
-    /*      |  ***  |                |***|                                 */
-    /*      |   *   |                | * |                                 */
-    /*      |   *   |    ------>     | * |                                 */
-    /*      |   *   |                | * |                                 */
-    /*      |   *   |                | * |                                 */
-    /*      |  ***  |                |***|                                 */
-    /*      ---------                -----                                 */
-    /*                                                                     */
-    /***********************************************************************/
-
-    FT_Int    rows, count;
-    FT_Long   line_len;
-    FT_Byte*  line;
-
-
-    /***********************************************************************/
-    /*                                                                     */
-    /* first of all, check the top-most lines of the bitmap, and remove    */
-    /* them if they're empty.                                              */
-    /*                                                                     */
-    {
-      line     = (FT_Byte*)map->buffer;
-      rows     = map->rows;
-      line_len = map->pitch;
-
-
-      for ( count = 0; count < rows; count++ )
-      {
-        FT_Byte*  cur   = line;
-        FT_Byte*  limit = line + line_len;
-
-
-        for ( ; cur < limit; cur++ )
-          if ( cur[0] )
-            goto Found_Top;
-
-        /* the current line was empty - skip to next one */
-        line  = limit;
-      }
-
-    Found_Top:
-      /* check that we have at least one filled line */
-      if ( count >= rows )
-        goto Empty_Bitmap;
-
-      /* now, crop the empty upper lines */
-      if ( count > 0 )
-      {
-        line = (FT_Byte*)map->buffer;
-
-        FT_MEM_MOVE( line, line + count * line_len,
-                     ( rows - count ) * line_len );
-
-        metrics->height       = (FT_Byte)( metrics->height - count );
-        metrics->horiBearingY = (FT_Char)( metrics->horiBearingY - count );
-        metrics->vertBearingY = (FT_Char)( metrics->vertBearingY - count );
-
-        map->rows -= count;
-        rows      -= count;
-      }
-    }
-
-    /***********************************************************************/
-    /*                                                                     */
-    /* second, crop the lower lines                                        */
-    /*                                                                     */
-    {
-      line = (FT_Byte*)map->buffer + ( rows - 1 ) * line_len;
-
-      for ( count = 0; count < rows; count++ )
-      {
-        FT_Byte*  cur   = line;
-        FT_Byte*  limit = line + line_len;
-
-
-        for ( ; cur < limit; cur++ )
-          if ( cur[0] )
-            goto Found_Bottom;
-
-        /* the current line was empty - skip to previous one */
-        line -= line_len;
-      }
-
-    Found_Bottom:
-      if ( count > 0 )
-      {
-        metrics->height  = (FT_Byte)( metrics->height - count );
-        rows            -= count;
-        map->rows       -= count;
-      }
-    }
-
-    /***********************************************************************/
-    /*                                                                     */
-    /* third, get rid of the space on the left side of the glyph           */
-    /*                                                                     */
-    do
-    {
-      FT_Byte*  limit;
-
-
-      line  = (FT_Byte*)map->buffer;
-      limit = line + rows * line_len;
-
-      for ( ; line < limit; line += line_len )
-        if ( line[0] & 0x80 )
-          goto Found_Left;
-
-      /* shift the whole glyph one pixel to the left */
-      line  = (FT_Byte*)map->buffer;
-      limit = line + rows * line_len;
-
-      for ( ; line < limit; line += line_len )
-      {
-        FT_Int    n, width = map->width;
-        FT_Byte   old;
-        FT_Byte*  cur = line;
-
-
-        old = (FT_Byte)(cur[0] << 1);
-        for ( n = 8; n < width; n += 8 )
-        {
-          FT_Byte  val;
-
-
-          val    = cur[1];
-          cur[0] = (FT_Byte)( old | ( val >> 7 ) );
-          old    = (FT_Byte)( val << 1 );
-          cur++;
-        }
-        cur[0] = old;
-      }
-
-      map->width--;
-      metrics->horiBearingX++;
-      metrics->vertBearingX++;
-      metrics->width--;
-
-    } while ( map->width > 0 );
-
-  Found_Left:
-
-    /***********************************************************************/
-    /*                                                                     */
-    /* finally, crop the bitmap width to get rid of the space on the right */
-    /* side of the glyph.                                                  */
-    /*                                                                     */
-    do
-    {
-      FT_Int    right = map->width - 1;
-      FT_Byte*  limit;
-      FT_Byte   mask;
-
-
-      line  = (FT_Byte*)map->buffer + ( right >> 3 );
-      limit = line + rows * line_len;
-      mask  = (FT_Byte)( 0x80 >> ( right & 7 ) );
-
-      for ( ; line < limit; line += line_len )
-        if ( line[0] & mask )
-          goto Found_Right;
-
-      /* crop the whole glyph to the right */
-      map->width--;
-      metrics->width--;
-
-    } while ( map->width > 0 );
-
-  Found_Right:
-    /* all right, the bitmap was cropped */
-    return;
-
-  Empty_Bitmap:
-    map->width      = 0;
-    map->rows       = 0;
-    map->pitch      = 0;
-    map->pixel_mode = FT_PIXEL_MODE_MONO;
+    FT_UNUSED( decoder );
   }
 
 
   static FT_Error
-  Load_SBit_Single( FT_Bitmap*       map,
-                    FT_Int           x_offset,
-                    FT_Int           y_offset,
-                    FT_Int           pix_bits,
-                    FT_UShort        image_format,
-                    TT_SBit_Metrics  metrics,
-                    FT_Stream        stream )
+  tt_sbit_decoder_alloc_bitmap( TT_SBitDecoder  decoder,
+                                FT_UInt         load_flags )
   {
-    FT_Error  error;
+    FT_Error    error = FT_Err_Ok;
+    FT_UInt     width, height;
+    FT_Bitmap*  map = decoder->bitmap;
+    FT_Long     size;
 
 
-    /* check that the source bitmap fits into the target pixmap */
-    if ( x_offset < 0 || x_offset + metrics->width  > map->width ||
-         y_offset < 0 || y_offset + metrics->height > map->rows  )
+    if ( !decoder->metrics_loaded )
     {
-      error = SFNT_Err_Invalid_Argument;
-
+      error = FT_THROW( Invalid_Argument );
       goto Exit;
     }
 
+    width  = decoder->metrics->width;
+    height = decoder->metrics->height;
+
+    map->width = (int)width;
+    map->rows  = (int)height;
+
+    switch ( decoder->bit_depth )
     {
-      FT_Int   glyph_width  = metrics->width;
-      FT_Int   glyph_height = metrics->height;
-      FT_Int   glyph_size;
-      FT_Int   line_bits    = pix_bits * glyph_width;
-      FT_Bool  pad_bytes    = 0;
+    case 1:
+      map->pixel_mode = FT_PIXEL_MODE_MONO;
+      map->pitch      = ( map->width + 7 ) >> 3;
+      map->num_grays  = 2;
+      break;
 
+    case 2:
+      map->pixel_mode = FT_PIXEL_MODE_GRAY2;
+      map->pitch      = ( map->width + 3 ) >> 2;
+      map->num_grays  = 4;
+      break;
 
-      /* compute size of glyph image */
-      switch ( image_format )
+    case 4:
+      map->pixel_mode = FT_PIXEL_MODE_GRAY4;
+      map->pitch      = ( map->width + 1 ) >> 1;
+      map->num_grays  = 16;
+      break;
+
+    case 8:
+      map->pixel_mode = FT_PIXEL_MODE_GRAY;
+      map->pitch      = map->width;
+      map->num_grays  = 256;
+      break;
+
+    case 32:
+      if ( load_flags & FT_LOAD_COLOR )
       {
-      case 1:  /* byte-padded formats */
-      case 6:
+        map->pixel_mode = FT_PIXEL_MODE_BGRA;
+        map->pitch      = map->width * 4;
+        map->num_grays  = 256;
+      }
+      else
+      {
+        map->pixel_mode = FT_PIXEL_MODE_GRAY;
+        map->pitch      = map->width;
+        map->num_grays  = 256;
+      }
+      break;
+
+    default:
+      error = FT_THROW( Invalid_File_Format );
+      goto Exit;
+    }
+
+    size = map->rows * map->pitch;
+
+    /* check that there is no empty image */
+    if ( size == 0 )
+      goto Exit;     /* exit successfully! */
+
+    error = ft_glyphslot_alloc_bitmap( decoder->face->root.glyph, size );
+    if ( error )
+      goto Exit;
+
+    decoder->bitmap_allocated = 1;
+
+  Exit:
+    return error;
+  }
+
+
+  static FT_Error
+  tt_sbit_decoder_load_metrics( TT_SBitDecoder  decoder,
+                                FT_Byte*       *pp,
+                                FT_Byte*        limit,
+                                FT_Bool         big )
+  {
+    FT_Byte*         p       = *pp;
+    TT_SBit_Metrics  metrics = decoder->metrics;
+
+
+    if ( p + 5 > limit )
+      goto Fail;
+
+    metrics->height       = p[0];
+    metrics->width        = p[1];
+    metrics->horiBearingX = (FT_Char)p[2];
+    metrics->horiBearingY = (FT_Char)p[3];
+    metrics->horiAdvance  = p[4];
+
+    p += 5;
+    if ( big )
+    {
+      if ( p + 3 > limit )
+        goto Fail;
+
+      metrics->vertBearingX = (FT_Char)p[0];
+      metrics->vertBearingY = (FT_Char)p[1];
+      metrics->vertAdvance  = p[2];
+
+      p += 3;
+    }
+
+    decoder->metrics_loaded = 1;
+    *pp = p;
+    return FT_Err_Ok;
+
+  Fail:
+    FT_TRACE1(( "tt_sbit_decoder_load_metrics: broken table" ));
+    return FT_THROW( Invalid_Argument );
+  }
+
+
+  /* forward declaration */
+  static FT_Error
+  tt_sbit_decoder_load_image( TT_SBitDecoder  decoder,
+                              FT_UInt         load_flags,
+                              FT_UInt         glyph_index,
+                              FT_Int          x_pos,
+                              FT_Int          y_pos );
+
+  typedef FT_Error  (*TT_SBitDecoder_LoadFunc)( TT_SBitDecoder  decoder,
+                                                FT_UInt         load_flags,
+                                                FT_Byte*        p,
+                                                FT_Byte*        plimit,
+                                                FT_Int          x_pos,
+                                                FT_Int          y_pos );
+
+
+  static FT_Error
+  tt_sbit_decoder_load_byte_aligned( TT_SBitDecoder  decoder,
+                                     FT_UInt         load_flags,
+                                     FT_Byte*        p,
+                                     FT_Byte*        limit,
+                                     FT_Int          x_pos,
+                                     FT_Int          y_pos )
+  {
+    FT_Error    error = FT_Err_Ok;
+    FT_Byte*    line;
+    FT_Int      bit_height, bit_width, pitch, width, height, line_bits, h;
+    FT_Bitmap*  bitmap;
+
+    FT_UNUSED( load_flags );
+
+
+    /* check that we can write the glyph into the bitmap */
+    bitmap     = decoder->bitmap;
+    bit_width  = bitmap->width;
+    bit_height = bitmap->rows;
+    pitch      = bitmap->pitch;
+    line       = bitmap->buffer;
+
+    width  = decoder->metrics->width;
+    height = decoder->metrics->height;
+
+    line_bits = width * decoder->bit_depth;
+
+    if ( x_pos < 0 || x_pos + width > bit_width   ||
+         y_pos < 0 || y_pos + height > bit_height )
+    {
+      FT_TRACE1(( "tt_sbit_decoder_load_byte_aligned:"
+                  " invalid bitmap dimensions\n" ));
+      error = FT_THROW( Invalid_File_Format );
+      goto Exit;
+    }
+
+    if ( p + ( ( line_bits + 7 ) >> 3 ) * height > limit )
+    {
+      FT_TRACE1(( "tt_sbit_decoder_load_byte_aligned: broken bitmap\n" ));
+      error = FT_THROW( Invalid_File_Format );
+      goto Exit;
+    }
+
+    /* now do the blit */
+    line  += y_pos * pitch + ( x_pos >> 3 );
+    x_pos &= 7;
+
+    if ( x_pos == 0 )  /* the easy one */
+    {
+      for ( h = height; h > 0; h--, line += pitch )
+      {
+        FT_Byte*  pwrite = line;
+        FT_Int    w;
+
+
+        for ( w = line_bits; w >= 8; w -= 8 )
         {
-          FT_Int  line_length;
-
-
-          switch ( pix_bits )
-          {
-          case 1:
-            line_length = ( glyph_width + 7 ) >> 3;
-            break;
-          case 2:
-            line_length = ( glyph_width + 3 ) >> 2;
-            break;
-          case 4:
-            line_length = ( glyph_width + 1 ) >> 1;
-            break;
-          default:
-            line_length =   glyph_width;
-          }
-
-          glyph_size = glyph_height * line_length;
-          pad_bytes  = 1;
+          pwrite[0] = (FT_Byte)( pwrite[0] | *p++ );
+          pwrite   += 1;
         }
+
+        if ( w > 0 )
+          pwrite[0] = (FT_Byte)( pwrite[0] | ( *p++ & ( 0xFF00U >> w ) ) );
+      }
+    }
+    else  /* x_pos > 0 */
+    {
+      for ( h = height; h > 0; h--, line += pitch )
+      {
+        FT_Byte*  pwrite = line;
+        FT_Int    w;
+        FT_UInt   wval = 0;
+
+
+        for ( w = line_bits; w >= 8; w -= 8 )
+        {
+          wval       = (FT_UInt)( wval | *p++ );
+          pwrite[0]  = (FT_Byte)( pwrite[0] | ( wval >> x_pos ) );
+          pwrite    += 1;
+          wval     <<= 8;
+        }
+
+        if ( w > 0 )
+          wval = (FT_UInt)( wval | ( *p++ & ( 0xFF00U >> w ) ) );
+
+        /* all bits read and there are `x_pos + w' bits to be written */
+
+        pwrite[0] = (FT_Byte)( pwrite[0] | ( wval >> x_pos ) );
+
+        if ( x_pos + w > 8 )
+        {
+          pwrite++;
+          wval     <<= 8;
+          pwrite[0]  = (FT_Byte)( pwrite[0] | ( wval >> x_pos ) );
+        }
+      }
+    }
+
+  Exit:
+    if ( !error )
+      FT_TRACE3(( "tt_sbit_decoder_load_byte_aligned: loaded\n" ));
+    return error;
+  }
+
+
+  /*
+   * Load a bit-aligned bitmap (with pointer `p') into a line-aligned bitmap
+   * (with pointer `pwrite').  In the example below, the width is 3 pixel,
+   * and `x_pos' is 1 pixel.
+   *
+   *       p                               p+1
+   *     |                               |                               |
+   *     | 7   6   5   4   3   2   1   0 | 7   6   5   4   3   2   1   0 |...
+   *     |                               |                               |
+   *       +-------+   +-------+   +-------+ ...
+   *           .           .           .
+   *           .           .           .
+   *           v           .           .
+   *       +-------+       .           .
+   * |                               | .
+   * | 7   6   5   4   3   2   1   0 | .
+   * |                               | .
+   *   pwrite              .           .
+   *                       .           .
+   *                       v           .
+   *                   +-------+       .
+   *             |                               |
+   *             | 7   6   5   4   3   2   1   0 |
+   *             |                               |
+   *               pwrite+1            .
+   *                                   .
+   *                                   v
+   *                               +-------+
+   *                         |                               |
+   *                         | 7   6   5   4   3   2   1   0 |
+   *                         |                               |
+   *                           pwrite+2
+   *
+   */
+
+  static FT_Error
+  tt_sbit_decoder_load_bit_aligned( TT_SBitDecoder  decoder,
+                                    FT_UInt         load_flags,
+                                    FT_Byte*        p,
+                                    FT_Byte*        limit,
+                                    FT_Int          x_pos,
+                                    FT_Int          y_pos )
+  {
+    FT_Error    error = FT_Err_Ok;
+    FT_Byte*    line;
+    FT_Int      bit_height, bit_width, pitch, width, height, line_bits, h, nbits;
+    FT_Bitmap*  bitmap;
+    FT_UShort   rval;
+
+    FT_UNUSED( load_flags );
+
+
+    /* check that we can write the glyph into the bitmap */
+    bitmap     = decoder->bitmap;
+    bit_width  = bitmap->width;
+    bit_height = bitmap->rows;
+    pitch      = bitmap->pitch;
+    line       = bitmap->buffer;
+
+    width  = decoder->metrics->width;
+    height = decoder->metrics->height;
+
+    line_bits = width * decoder->bit_depth;
+
+    if ( x_pos < 0 || x_pos + width  > bit_width  ||
+         y_pos < 0 || y_pos + height > bit_height )
+    {
+      FT_TRACE1(( "tt_sbit_decoder_load_bit_aligned:"
+                  " invalid bitmap dimensions\n" ));
+      error = FT_THROW( Invalid_File_Format );
+      goto Exit;
+    }
+
+    if ( p + ( ( line_bits * height + 7 ) >> 3 ) > limit )
+    {
+      FT_TRACE1(( "tt_sbit_decoder_load_bit_aligned: broken bitmap\n" ));
+      error = FT_THROW( Invalid_File_Format );
+      goto Exit;
+    }
+
+    /* now do the blit */
+
+    /* adjust `line' to point to the first byte of the bitmap */
+    line  += y_pos * pitch + ( x_pos >> 3 );
+    x_pos &= 7;
+
+    /* the higher byte of `rval' is used as a buffer */
+    rval  = 0;
+    nbits = 0;
+
+    for ( h = height; h > 0; h--, line += pitch )
+    {
+      FT_Byte*  pwrite = line;
+      FT_Int    w      = line_bits;
+
+
+      /* handle initial byte (in target bitmap) specially if necessary */
+      if ( x_pos )
+      {
+        w = ( line_bits < 8 - x_pos ) ? line_bits : 8 - x_pos;
+
+        if ( h == height )
+        {
+          rval  = *p++;
+          nbits = x_pos;
+        }
+        else if ( nbits < w )
+        {
+          if ( p < limit )
+            rval |= *p++;
+          nbits += 8 - w;
+        }
+        else
+        {
+          rval  >>= 8;
+          nbits  -= w;
+        }
+
+        *pwrite++ |= ( ( rval >> nbits ) & 0xFF ) &
+                     ( ~( 0xFF << w ) << ( 8 - w - x_pos ) );
+        rval     <<= 8;
+
+        w = line_bits - w;
+      }
+
+      /* handle medial bytes */
+      for ( ; w >= 8; w -= 8 )
+      {
+        rval      |= *p++;
+        *pwrite++ |= ( rval >> nbits ) & 0xFF;
+
+        rval <<= 8;
+      }
+
+      /* handle final byte if necessary */
+      if ( w > 0 )
+      {
+        if ( nbits < w )
+        {
+          if ( p < limit )
+            rval |= *p++;
+          *pwrite |= ( ( rval >> nbits ) & 0xFF ) & ( 0xFF00U >> w );
+          nbits   += 8 - w;
+
+          rval <<= 8;
+        }
+        else
+        {
+          *pwrite |= ( ( rval >> nbits ) & 0xFF ) & ( 0xFF00U >> w );
+          nbits   -= w;
+        }
+      }
+    }
+
+  Exit:
+    if ( !error )
+      FT_TRACE3(( "tt_sbit_decoder_load_bit_aligned: loaded\n" ));
+    return error;
+  }
+
+
+  static FT_Error
+  tt_sbit_decoder_load_compound( TT_SBitDecoder  decoder,
+                                 FT_UInt         load_flags,
+                                 FT_Byte*        p,
+                                 FT_Byte*        limit,
+                                 FT_Int          x_pos,
+                                 FT_Int          y_pos )
+  {
+    FT_Error  error = FT_Err_Ok;
+    FT_UInt   num_components, nn;
+
+    FT_Char  horiBearingX = decoder->metrics->horiBearingX;
+    FT_Char  horiBearingY = decoder->metrics->horiBearingY;
+    FT_Byte  horiAdvance  = decoder->metrics->horiAdvance;
+    FT_Char  vertBearingX = decoder->metrics->vertBearingX;
+    FT_Char  vertBearingY = decoder->metrics->vertBearingY;
+    FT_Byte  vertAdvance  = decoder->metrics->vertAdvance;
+
+
+    if ( p + 2 > limit )
+      goto Fail;
+
+    num_components = FT_NEXT_USHORT( p );
+    if ( p + 4 * num_components > limit )
+    {
+      FT_TRACE1(( "tt_sbit_decoder_load_compound: broken table\n" ));
+      goto Fail;
+    }
+
+    FT_TRACE3(( "tt_sbit_decoder_load_compound: loading %d components\n",
+                num_components ));
+
+    for ( nn = 0; nn < num_components; nn++ )
+    {
+      FT_UInt  gindex = FT_NEXT_USHORT( p );
+      FT_Byte  dx     = FT_NEXT_BYTE( p );
+      FT_Byte  dy     = FT_NEXT_BYTE( p );
+
+
+      /* NB: a recursive call */
+      error = tt_sbit_decoder_load_image( decoder, load_flags, gindex,
+                                          x_pos + dx, y_pos + dy );
+      if ( error )
+        break;
+    }
+
+    FT_TRACE3(( "tt_sbit_decoder_load_compound: done\n" ));
+
+    decoder->metrics->horiBearingX = horiBearingX;
+    decoder->metrics->horiBearingY = horiBearingY;
+    decoder->metrics->horiAdvance  = horiAdvance;
+    decoder->metrics->vertBearingX = vertBearingX;
+    decoder->metrics->vertBearingY = vertBearingY;
+    decoder->metrics->vertAdvance  = vertAdvance;
+    decoder->metrics->width        = (FT_Byte)decoder->bitmap->width;
+    decoder->metrics->height       = (FT_Byte)decoder->bitmap->rows;
+
+  Exit:
+    return error;
+
+  Fail:
+    error = FT_THROW( Invalid_File_Format );
+    goto Exit;
+  }
+
+
+#ifdef FT_CONFIG_OPTION_USE_PNG
+
+  static FT_Error
+  tt_sbit_decoder_load_png( TT_SBitDecoder  decoder,
+                            FT_UInt         load_flags,
+                            FT_Byte*        p,
+                            FT_Byte*        limit,
+                            FT_Int          x_pos,
+                            FT_Int          y_pos )
+  {
+    FT_Error  error = FT_Err_Ok;
+    FT_ULong  png_len;
+
+    FT_UNUSED( load_flags );
+
+
+    if ( limit - p < 4 )
+    {
+      FT_TRACE1(( "tt_sbit_decoder_load_png: broken bitmap\n" ));
+      error = FT_THROW( Invalid_File_Format );
+      goto Exit;
+    }
+
+    png_len = FT_NEXT_ULONG( p );
+    if ( (FT_ULong)( limit - p ) < png_len )
+    {
+      FT_TRACE1(( "tt_sbit_decoder_load_png: broken bitmap\n" ));
+      error = FT_THROW( Invalid_File_Format );
+      goto Exit;
+    }
+
+    error = Load_SBit_Png( decoder->bitmap,
+                           x_pos,
+                           y_pos,
+                           decoder->bit_depth,
+                           decoder->metrics,
+                           decoder->stream->memory,
+                           p,
+                           png_len );
+
+  Exit:
+    if ( !error )
+      FT_TRACE3(( "tt_sbit_decoder_load_png: loaded\n" ));
+    return error;
+  }
+
+#endif /* FT_CONFIG_OPTION_USE_PNG */
+
+
+  static FT_Error
+  tt_sbit_decoder_load_bitmap( TT_SBitDecoder  decoder,
+                               FT_UInt         load_flags,
+                               FT_UInt         glyph_format,
+                               FT_ULong        glyph_start,
+                               FT_ULong        glyph_size,
+                               FT_Int          x_pos,
+                               FT_Int          y_pos )
+  {
+    FT_Error   error;
+    FT_Stream  stream = decoder->stream;
+    FT_Byte*   p;
+    FT_Byte*   p_limit;
+    FT_Byte*   data;
+
+
+    /* seek into the EBDT table now */
+    if ( glyph_start + glyph_size > decoder->ebdt_size )
+    {
+      error = FT_THROW( Invalid_Argument );
+      goto Exit;
+    }
+
+    if ( FT_STREAM_SEEK( decoder->ebdt_start + glyph_start ) ||
+         FT_FRAME_EXTRACT( glyph_size, data )                )
+      goto Exit;
+
+    p       = data;
+    p_limit = p + glyph_size;
+
+    /* read the data, depending on the glyph format */
+    switch ( glyph_format )
+    {
+    case 1:
+    case 2:
+    case 8:
+    case 17:
+      error = tt_sbit_decoder_load_metrics( decoder, &p, p_limit, 0 );
+      break;
+
+    case 6:
+    case 7:
+    case 9:
+    case 18:
+      error = tt_sbit_decoder_load_metrics( decoder, &p, p_limit, 1 );
+      break;
+
+    default:
+      error = FT_Err_Ok;
+    }
+
+    if ( error )
+      goto Fail;
+
+    {
+      TT_SBitDecoder_LoadFunc  loader;
+
+
+      switch ( glyph_format )
+      {
+      case 1:
+      case 6:
+        loader = tt_sbit_decoder_load_byte_aligned;
         break;
 
       case 2:
       case 5:
       case 7:
-        line_bits  =   glyph_width  * pix_bits;
-        glyph_size = ( glyph_height * line_bits + 7 ) >> 3;
+        loader = tt_sbit_decoder_load_bit_aligned;
         break;
 
-      default:  /* invalid format */
-        return SFNT_Err_Invalid_File_Format;
+      case 8:
+        if ( p + 1 > p_limit )
+          goto Fail;
+
+        p += 1;  /* skip padding */
+        /* fall-through */
+
+      case 9:
+        loader = tt_sbit_decoder_load_compound;
+        break;
+
+#ifdef FT_CONFIG_OPTION_USE_PNG
+      case 17: /* small metrics, PNG image data   */
+      case 18: /* big metrics, PNG image data     */
+      case 19: /* metrics in EBLC, PNG image data */
+        loader = tt_sbit_decoder_load_png;
+        break;
+#endif /* FT_CONFIG_OPTION_USE_PNG */
+
+      default:
+        error = FT_THROW( Invalid_Table );
+        goto Fail;
       }
 
-      /* Now read data and draw glyph into target pixmap       */
-      if ( FT_FRAME_ENTER( glyph_size ) )
-        goto Exit;
+      if ( !decoder->bitmap_allocated )
+      {
+        error = tt_sbit_decoder_alloc_bitmap( decoder, load_flags );
+        if ( error )
+          goto Fail;
+      }
 
-      /* don't forget to multiply `x_offset' by `map->pix_bits' as */
-      /* the sbit blitter doesn't make a difference between pixmap */
-      /* depths.                                                   */
-      blit_sbit( map, (FT_Byte*)stream->cursor, line_bits, pad_bytes,
-                 x_offset * pix_bits, y_offset, metrics->height );
+      if ( decoder->bit_depth == 32                          &&
+           decoder->bitmap->pixel_mode != FT_PIXEL_MODE_BGRA )
+      {
+        /* Flatten color bitmaps if color was not requested. */
 
-      FT_FRAME_EXIT();
+        FT_Library library = decoder->face->root.glyph->library;
+        FT_Memory  memory  = decoder->stream->memory;
+
+        FT_Bitmap color, *orig;
+
+
+        if ( decoder->bitmap->pixel_mode != FT_PIXEL_MODE_GRAY ||
+             x_pos != 0 || y_pos != 0                          )
+        {
+          /* Shouldn't happen. */
+          error = FT_THROW( Invalid_Table );
+          goto Fail;
+        }
+
+        FT_Bitmap_New( &color );
+
+        color.rows       = decoder->bitmap->rows;
+        color.width      = decoder->bitmap->width;
+        color.pitch      = color.width * 4;
+        color.pixel_mode = FT_PIXEL_MODE_BGRA;
+
+        if ( FT_ALLOC( color.buffer, color.rows * color.pitch ) )
+          goto Fail;
+
+        orig            = decoder->bitmap;
+        decoder->bitmap = &color;
+
+        error = loader( decoder, load_flags, p, p_limit, x_pos, y_pos );
+
+        decoder->bitmap = orig;
+
+        /* explicitly test against FT_Err_Ok to avoid compiler warnings */
+        /* (we do an assignment within a conditional)                   */
+        if ( error                                           ||
+             ( error = FT_Bitmap_Convert( library,
+                                          &color,
+                                          decoder->bitmap,
+                                          1 ) ) != FT_Err_Ok )
+        {
+          FT_Bitmap_Done( library, &color );
+          goto Fail;
+        }
+
+        FT_Bitmap_Done( library, &color );
+      }
+
+      else
+        error = loader( decoder, load_flags, p, p_limit, x_pos, y_pos );
     }
 
+  Fail:
+    FT_FRAME_RELEASE( data );
+
   Exit:
     return error;
   }
 
 
   static FT_Error
-  Load_SBit_Image( TT_SBit_Strike   strike,
-                   TT_SBit_Range    range,
-                   FT_ULong         ebdt_pos,
-                   FT_ULong         glyph_offset,
-                   FT_GlyphSlot     slot,
-                   FT_Int           x_offset,
-                   FT_Int           y_offset,
-                   FT_Stream        stream,
-                   TT_SBit_Metrics  metrics,
-                   FT_Int           depth )
+  tt_sbit_decoder_load_image( TT_SBitDecoder  decoder,
+                              FT_UInt         load_flags,
+                              FT_UInt         glyph_index,
+                              FT_Int          x_pos,
+                              FT_Int          y_pos )
   {
-    FT_Memory   memory = stream->memory;
-    FT_Bitmap*  map    = &slot->bitmap;
-    FT_Error    error;
+    /*
+     *  First, we find the correct strike range that applies to this
+     *  glyph index.
+     */
+
+    FT_Byte*  p          = decoder->eblc_base + decoder->strike_index_array;
+    FT_Byte*  p_limit    = decoder->eblc_limit;
+    FT_ULong  num_ranges = decoder->strike_index_count;
+    FT_UInt   start, end, index_format, image_format;
+    FT_ULong  image_start = 0, image_end = 0, image_offset;
 
 
-    /* place stream at beginning of glyph data and read metrics */
-    if ( FT_STREAM_SEEK( ebdt_pos + glyph_offset ) )
-      goto Exit;
-
-    error = tt_load_sbit_metrics( stream, range, metrics );
-    if ( error )
-      goto Exit;
-
-    /* This function is recursive.  At the top-level call, we  */
-    /* compute the dimensions of the higher-level glyph to     */
-    /* allocate the final pixmap buffer.                       */
-    if ( depth == 0 )
+    for ( ; num_ranges > 0; num_ranges-- )
     {
-      FT_Long  size;
+      start = FT_NEXT_USHORT( p );
+      end   = FT_NEXT_USHORT( p );
 
+      if ( glyph_index >= start && glyph_index <= end )
+        goto FoundRange;
 
-      map->width = metrics->width;
-      map->rows  = metrics->height;
-
-      switch ( strike->bit_depth )
-      {
-      case 1:
-        map->pixel_mode = FT_PIXEL_MODE_MONO;
-        map->pitch      = ( map->width + 7 ) >> 3;
-        break;
-
-      case 2:
-        map->pixel_mode = FT_PIXEL_MODE_GRAY2;
-        map->pitch      = ( map->width + 3 ) >> 2;
-        break;
-
-      case 4:
-        map->pixel_mode = FT_PIXEL_MODE_GRAY4;
-        map->pitch      = ( map->width + 1 ) >> 1;
-        break;
-
-      case 8:
-        map->pixel_mode = FT_PIXEL_MODE_GRAY;
-        map->pitch      = map->width;
-        break;
-
-      default:
-        return SFNT_Err_Invalid_File_Format;
-      }
-
-      size = map->rows * map->pitch;
-
-      /* check that there is no empty image */
-      if ( size == 0 )
-        goto Exit;     /* exit successfully! */
-
-      error = ft_glyphslot_alloc_bitmap( slot, size );
-      if (error)
-        goto Exit;
+      p += 4;  /* ignore index offset */
     }
+    goto NoBitmap;
 
-    switch ( range->image_format )
+  FoundRange:
+    image_offset = FT_NEXT_ULONG( p );
+
+    /* overflow check */
+    p = decoder->eblc_base + decoder->strike_index_array;
+    if ( image_offset > (FT_ULong)( p_limit - p ) )
+      goto Failure;
+
+    p += image_offset;
+    if ( p + 8 > p_limit )
+      goto NoBitmap;
+
+    /* now find the glyph's location and extend within the ebdt table */
+    index_format = FT_NEXT_USHORT( p );
+    image_format = FT_NEXT_USHORT( p );
+    image_offset = FT_NEXT_ULONG ( p );
+
+    switch ( index_format )
     {
-    case 1:  /* single sbit image - load it */
-    case 2:
-    case 5:
-    case 6:
-    case 7:
-      return Load_SBit_Single( map, x_offset, y_offset, strike->bit_depth,
-                               range->image_format, metrics, stream );
-
-    case 8:  /* compound format */
-      if ( FT_STREAM_SKIP( 1L ) )
+    case 1: /* 4-byte offsets relative to `image_offset' */
       {
-        error = SFNT_Err_Invalid_Stream_Skip;
-        goto Exit;
-      }
-      /* fallthrough */
+        p += 4 * ( glyph_index - start );
+        if ( p + 8 > p_limit )
+          goto NoBitmap;
 
-    case 9:
+        image_start = FT_NEXT_ULONG( p );
+        image_end   = FT_NEXT_ULONG( p );
+
+        if ( image_start == image_end )  /* missing glyph */
+          goto NoBitmap;
+      }
       break;
 
-    default: /* invalid image format */
-      return SFNT_Err_Invalid_File_Format;
+    case 2: /* big metrics, constant image size */
+      {
+        FT_ULong  image_size;
+
+
+        if ( p + 12 > p_limit )
+          goto NoBitmap;
+
+        image_size = FT_NEXT_ULONG( p );
+
+        if ( tt_sbit_decoder_load_metrics( decoder, &p, p_limit, 1 ) )
+          goto NoBitmap;
+
+        image_start = image_size * ( glyph_index - start );
+        image_end   = image_start + image_size;
+      }
+      break;
+
+    case 3: /* 2-byte offsets relative to 'image_offset' */
+      {
+        p += 2 * ( glyph_index - start );
+        if ( p + 4 > p_limit )
+          goto NoBitmap;
+
+        image_start = FT_NEXT_USHORT( p );
+        image_end   = FT_NEXT_USHORT( p );
+
+        if ( image_start == image_end )  /* missing glyph */
+          goto NoBitmap;
+      }
+      break;
+
+    case 4: /* sparse glyph array with (glyph,offset) pairs */
+      {
+        FT_ULong  mm, num_glyphs;
+
+
+        if ( p + 4 > p_limit )
+          goto NoBitmap;
+
+        num_glyphs = FT_NEXT_ULONG( p );
+
+        /* overflow check for p + ( num_glyphs + 1 ) * 4 */
+        if ( num_glyphs > (FT_ULong)( ( ( p_limit - p ) >> 2 ) - 1 ) )
+          goto NoBitmap;
+
+        for ( mm = 0; mm < num_glyphs; mm++ )
+        {
+          FT_UInt  gindex = FT_NEXT_USHORT( p );
+
+
+          if ( gindex == glyph_index )
+          {
+            image_start = FT_NEXT_USHORT( p );
+            p          += 2;
+            image_end   = FT_PEEK_USHORT( p );
+            break;
+          }
+          p += 2;
+        }
+
+        if ( mm >= num_glyphs )
+          goto NoBitmap;
+      }
+      break;
+
+    case 5: /* constant metrics with sparse glyph codes */
+    case 19:
+      {
+        FT_ULong  image_size, mm, num_glyphs;
+
+
+        if ( p + 16 > p_limit )
+          goto NoBitmap;
+
+        image_size = FT_NEXT_ULONG( p );
+
+        if ( tt_sbit_decoder_load_metrics( decoder, &p, p_limit, 1 ) )
+          goto NoBitmap;
+
+        num_glyphs = FT_NEXT_ULONG( p );
+
+        /* overflow check for p + 2 * num_glyphs */
+        if ( num_glyphs > (FT_ULong)( ( p_limit - p ) >> 1 ) )
+          goto NoBitmap;
+
+        for ( mm = 0; mm < num_glyphs; mm++ )
+        {
+          FT_UInt  gindex = FT_NEXT_USHORT( p );
+
+
+          if ( gindex == glyph_index )
+            break;
+        }
+
+        if ( mm >= num_glyphs )
+          goto NoBitmap;
+
+        image_start = image_size * mm;
+        image_end   = image_start + image_size;
+      }
+      break;
+
+    default:
+      goto NoBitmap;
     }
 
-    /* All right, we have a compound format.  First of all, read */
-    /* the array of elements.                                    */
-    {
-      TT_SBit_Component  components = NULL;
-      TT_SBit_Component  comp;
-      FT_UShort          num_components, count;
+    if ( image_start > image_end )
+      goto NoBitmap;
 
+    image_end  -= image_start;
+    image_start = image_offset + image_start;
 
-      if ( FT_READ_USHORT( num_components )           ||
-           FT_NEW_ARRAY( components, num_components ) )
-        goto Exit;
+    FT_TRACE3(( "tt_sbit_decoder_load_image:"
+                " found sbit (format %d) for glyph index %d\n",
+                image_format, glyph_index ));
 
-      count = num_components;
+    return tt_sbit_decoder_load_bitmap( decoder,
+                                        load_flags,
+                                        image_format,
+                                        image_start,
+                                        image_end,
+                                        x_pos,
+                                        y_pos );
 
-      if ( FT_FRAME_ENTER( 4L * num_components ) )
-        goto Fail_Memory;
+  Failure:
+    return FT_THROW( Invalid_Table );
 
-      for ( comp = components; count > 0; count--, comp++ )
-      {
-        comp->glyph_code = FT_GET_USHORT();
-        comp->x_offset   = FT_GET_CHAR();
-        comp->y_offset   = FT_GET_CHAR();
-      }
+  NoBitmap:
+    FT_TRACE4(( "tt_sbit_decoder_load_image:"
+                " no sbit found for glyph index %d\n", glyph_index ));
 
-      FT_FRAME_EXIT();
-
-      /* Now recursively load each element glyph */
-      count = num_components;
-      comp  = components;
-      for ( ; count > 0; count--, comp++ )
-      {
-        TT_SBit_Range       elem_range;
-        TT_SBit_MetricsRec  elem_metrics;
-        FT_ULong            elem_offset;
-
-
-        /* find the range for this element */
-        error = find_sbit_range( comp->glyph_code,
-                                 strike,
-                                 &elem_range,
-                                 &elem_offset );
-        if ( error )
-          goto Fail_Memory;
-
-        /* now load the element, recursively */
-        error = Load_SBit_Image( strike,
-                                 elem_range,
-                                 ebdt_pos,
-                                 elem_offset,
-                                 slot,
-                                 x_offset + comp->x_offset,
-                                 y_offset + comp->y_offset,
-                                 stream,
-                                 &elem_metrics,
-                                 depth + 1 );
-        if ( error )
-          goto Fail_Memory;
-      }
-
-    Fail_Memory:
-      FT_FREE( components );
-    }
-
-  Exit:
-    return error;
+    return FT_THROW( Invalid_Argument );
   }
 
 
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    tt_face_load_sbit_image                                            */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Loads a given glyph sbit image from the font resource.  This also  */
-  /*    returns its metrics.                                               */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    face         :: The target face object.                            */
-  /*                                                                       */
-  /*    strike_index :: The current strike index.                          */
-  /*                                                                       */
-  /*    glyph_index  :: The current glyph index.                           */
-  /*                                                                       */
-  /*    load_flags   :: The glyph load flags (the code checks for the flag */
-  /*                    FT_LOAD_CROP_BITMAP).                              */
-  /*                                                                       */
-  /*    stream       :: The input stream.                                  */
-  /*                                                                       */
-  /* <Output>                                                              */
-  /*    map          :: The target pixmap.                                 */
-  /*                                                                       */
-  /*    metrics      :: A big sbit metrics structure for the glyph image.  */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    FreeType error code.  0 means success.  Returns an error if no     */
-  /*    glyph sbit exists for the index.                                   */
-  /*                                                                       */
-  /*  <Note>                                                               */
-  /*    The `map.buffer' field is always freed before the glyph is loaded. */
-  /*                                                                       */
-  FT_LOCAL_DEF( FT_Error )
+  FT_LOCAL( FT_Error )
   tt_face_load_sbit_image( TT_Face              face,
                            FT_ULong             strike_index,
                            FT_UInt              glyph_index,
@@ -1450,59 +1151,27 @@
                            FT_Bitmap           *map,
                            TT_SBit_MetricsRec  *metrics )
   {
-    FT_Error        error;
-    FT_ULong        ebdt_pos, glyph_offset;
+    TT_SBitDecoderRec  decoder[1];
+    FT_Error           error;
 
-    TT_SBit_Strike  strike;
-    TT_SBit_Range   range;
+    FT_UNUSED( load_flags );
+    FT_UNUSED( stream );
+    FT_UNUSED( map );
 
 
-    /* Check whether there is a glyph sbit for the current index */
-    error = tt_find_sbit_image( face, glyph_index, strike_index,
-                                &range, &strike, &glyph_offset );
-    if ( error )
-      goto Exit;
-
-    /* now, find the location of the `EBDT' table in */
-    /* the font file                                 */
-    error = face->goto_table( face, TTAG_EBDT, stream, 0 );
-    if ( error )
-      error = face->goto_table( face, TTAG_bdat, stream, 0 );
-    if ( error )
-      goto Exit;
-
-    ebdt_pos = FT_STREAM_POS();
-
-    error = Load_SBit_Image( strike, range, ebdt_pos, glyph_offset,
-                             face->root.glyph, 0, 0, stream, metrics, 0 );
-    if ( error )
-      goto Exit;
-
-    /* setup vertical metrics if needed */
-    if ( strike->flags & 1 )
+    error = tt_sbit_decoder_init( decoder, face, strike_index, metrics );
+    if ( !error )
     {
-      /* in case of a horizontal strike only */
-      FT_Int  advance;
-
-
-      advance = strike->hori.ascender - strike->hori.descender;
-
-      /* some heuristic values */
-
-      metrics->vertBearingX = (FT_Char)(-metrics->width / 2 );
-      metrics->vertBearingY = (FT_Char)( ( advance - metrics->height ) / 2 );
-      metrics->vertAdvance  = (FT_Char)( advance * 12 / 10 );
+      error = tt_sbit_decoder_load_image( decoder,
+                                          load_flags,
+                                          glyph_index,
+                                          0,
+                                          0 );
+      tt_sbit_decoder_done( decoder );
     }
 
-    /* Crop the bitmap now, unless specified otherwise */
-    if ( load_flags & FT_LOAD_CROP_BITMAP )
-      crop_bitmap( map, metrics );
-
-  Exit:
     return error;
   }
 
-#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
 
-
-/* END */
+/* EOF */
diff --git a/src/sfnt/ttsbit.h b/src/sfnt/ttsbit.h
index 7ea2af1..ea0b5f8 100644
--- a/src/sfnt/ttsbit.h
+++ b/src/sfnt/ttsbit.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    TrueType and OpenType embedded bitmap support (specification).       */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 by       */
+/*  Copyright 1996-2008, 2013 by                                           */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -45,22 +45,6 @@
                                FT_ULong          strike_index,
                                FT_Size_Metrics*  metrics );
 
-#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
-  FT_LOCAL( FT_Error )
-  tt_find_sbit_image( TT_Face          face,
-                      FT_UInt          glyph_index,
-                      FT_ULong         strike_index,
-                      TT_SBit_Range   *arange,
-                      TT_SBit_Strike  *astrike,
-                      FT_ULong        *aglyph_offset );
-
-  FT_LOCAL( FT_Error )
-  tt_load_sbit_metrics( FT_Stream        stream,
-                        TT_SBit_Range    range,
-                        TT_SBit_Metrics  metrics );
-
-#endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
-
   FT_LOCAL( FT_Error )
   tt_face_load_sbit_image( TT_Face              face,
                            FT_ULong             strike_index,
diff --git a/src/smooth/ftgrays.c b/src/smooth/ftgrays.c
index 4c0eea5..d2158e7 100644
--- a/src/smooth/ftgrays.c
+++ b/src/smooth/ftgrays.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    A new `perfect' anti-aliasing renderer (body).                       */
 /*                                                                         */
-/*  Copyright 2000-2003, 2005-2012 by                                      */
+/*  Copyright 2000-2003, 2005-2013 by                                      */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -94,6 +94,11 @@
 #ifdef _STANDALONE_
 
 
+  /* Auxiliary macros for token concatenation. */
+#define FT_ERR_XCAT( x, y )  x ## y
+#define FT_ERR_CAT( x, y )   FT_ERR_XCAT( x, y )
+
+
   /* define this to dump debugging information */
 /* #define FT_DEBUG_LEVEL_TRACE */
 
@@ -154,6 +159,21 @@
     va_end( ap );
   }
 
+
+  /* empty function useful for setting a breakpoint to catch errors */
+  int
+  FT_Throw( int          error,
+            int          line,
+            const char*  file )
+  {
+    FT_UNUSED( error );
+    FT_UNUSED( line );
+    FT_UNUSED( file );
+
+    return 0;
+  }
+
+
   /* we don't handle tracing levels in stand-alone mode; */
 #ifndef FT_TRACE5
 #define FT_TRACE5( varformat )  FT_Message varformat
@@ -165,11 +185,19 @@
 #define FT_ERROR( varformat )   FT_Message varformat
 #endif
 
+#define FT_THROW( e )                               \
+          ( FT_Throw( FT_ERR_CAT( ErrRaster, e ),   \
+                      __LINE__,                     \
+                      __FILE__ )                  | \
+            FT_ERR_CAT( ErrRaster, e )            )
+
 #else /* !FT_DEBUG_LEVEL_TRACE */
 
 #define FT_TRACE5( x )  do { } while ( 0 )     /* nothing */
 #define FT_TRACE7( x )  do { } while ( 0 )     /* nothing */
 #define FT_ERROR( x )   do { } while ( 0 )     /* nothing */
+#define FT_THROW( e )   FT_ERR_CAT( ErrRaster_, e )
+
 
 #endif /* !FT_DEBUG_LEVEL_TRACE */
 
@@ -202,6 +230,7 @@
             raster_done_                                          \
          };
 
+
 #else /* !_STANDALONE_ */
 
 
@@ -215,13 +244,14 @@
 
 #include "ftspic.h"
 
-#define ErrRaster_Invalid_Mode      Smooth_Err_Cannot_Render_Glyph
-#define ErrRaster_Invalid_Outline   Smooth_Err_Invalid_Outline
+#define Smooth_Err_Invalid_Mode     Smooth_Err_Cannot_Render_Glyph
+#define Smooth_Err_Memory_Overflow  Smooth_Err_Out_Of_Memory
 #define ErrRaster_Memory_Overflow   Smooth_Err_Out_Of_Memory
-#define ErrRaster_Invalid_Argument  Smooth_Err_Invalid_Argument
+
 
 #endif /* !_STANDALONE_ */
 
+
 #ifndef FT_MEM_SET
 #define FT_MEM_SET( d, s, c )  ft_memset( d, s, c )
 #endif
@@ -312,7 +342,7 @@
 #endif /* PIXEL_BITS >= 8 */
 
 
-  /* maximal number of gray spans in a call to the span callback */
+  /* maximum number of gray spans in a call to the span callback */
 #define FT_MAX_GRAY_SPANS  32
 
 
@@ -600,7 +630,7 @@
                                  TPos    x2,
                                  TCoord  y2 )
   {
-    TCoord  ex1, ex2, fx1, fx2, delta, mod, lift, rem;
+    TCoord  ex1, ex2, fx1, fx2, delta, mod;
     long    p, first, dx;
     int     incr;
 
@@ -661,6 +691,9 @@
 
     if ( ex1 != ex2 )
     {
+      TCoord  lift, rem;
+
+
       p    = ONE_PIXEL * ( y2 - y1 + delta );
       lift = (TCoord)( p / dx );
       rem  = (TCoord)( p % dx );
@@ -1091,11 +1124,11 @@
         if ( s > s_limit )
           goto Split;
 
-        /* If P1 or P2 is outside P0-P3, split the curve. */
-        if ( dy * dy1 + dx * dx1 < 0                                     ||
-             dy * dy2 + dx * dx2 < 0                                     ||
-             dy * (arc[3].y - arc[1].y) + dx * (arc[3].x - arc[1].x) < 0 ||
-             dy * (arc[3].y - arc[2].y) + dx * (arc[3].x - arc[2].x) < 0 )
+        /* Split super curvy segments where the off points are so far
+           from the chord that the angles P0-P1-P3 or P0-P2-P3 become
+           acute as detected by appropriate dot products. */
+        if ( dx1 * ( dx1 - dx ) + dy1 * ( dy1 - dy ) > 0 ||
+             dx2 * ( dx2 - dx ) + dy2 * ( dy2 - dy ) > 0 )
           goto Split;
 
         /* No reason to split. */
@@ -1227,9 +1260,7 @@
                        TPos    area,
                        TCoord  acount )
   {
-    FT_Span*  span;
-    int       count;
-    int       coverage;
+    int  coverage;
 
 
     /* compute the coverage line's coverage, depending on the    */
@@ -1271,6 +1302,10 @@
 
     if ( coverage )
     {
+      FT_Span*  span;
+      int       count;
+
+
       /* see whether we can add this span to the current list */
       count = ras.num_gray_spans;
       span  = ras.gray_spans + count - 1;
@@ -1400,7 +1435,26 @@
       ras.render_span( ras.span_y, ras.num_gray_spans,
                        ras.gray_spans, ras.render_span_data );
 
+#ifdef FT_DEBUG_LEVEL_TRACE
+
+    if ( ras.num_gray_spans > 0 )
+    {
+      FT_Span*  span;
+      int       n;
+
+
+      FT_TRACE7(( "y = %3d ", ras.span_y ));
+      span = ras.gray_spans;
+      for ( n = 0; n < ras.num_gray_spans; n++, span++ )
+        FT_TRACE7(( "[%d..%d]:%02x ",
+                    span->x, span->x + span->len - 1, span->coverage ));
+      FT_TRACE7(( "\n" ));
+    }
+
     FT_TRACE7(( "gray_sweep: end\n" ));
+
+#endif /* FT_DEBUG_LEVEL_TRACE */
+
   }
 
 
@@ -1467,7 +1521,7 @@
 
 
     if ( !outline || !func_interface )
-      return ErrRaster_Invalid_Argument;
+      return FT_THROW( Invalid_Argument );
 
     shift = func_interface->shift;
     delta = func_interface->delta;
@@ -1680,7 +1734,7 @@
     return error;
 
   Invalid_Outline:
-    return ErrRaster_Invalid_Outline;
+    return FT_THROW( Invalid_Outline );
   }
 
 #endif /* _STANDALONE_ */
@@ -1718,7 +1772,7 @@
       gray_record_cell( RAS_VAR );
     }
     else
-      error = ErrRaster_Memory_Overflow;
+      error = FT_THROW( Memory_Overflow );
 
     return error;
   }
@@ -1871,21 +1925,21 @@
 
 
     if ( !raster || !raster->buffer || !raster->buffer_size )
-      return ErrRaster_Invalid_Argument;
+      return FT_THROW( Invalid_Argument );
 
     if ( !outline )
-      return ErrRaster_Invalid_Outline;
+      return FT_THROW( Invalid_Outline );
 
     /* return immediately if the outline is empty */
     if ( outline->n_points == 0 || outline->n_contours <= 0 )
       return 0;
 
     if ( !outline->contours || !outline->points )
-      return ErrRaster_Invalid_Outline;
+      return FT_THROW( Invalid_Outline );
 
     if ( outline->n_points !=
            outline->contours[outline->n_contours - 1] + 1 )
-      return ErrRaster_Invalid_Outline;
+      return FT_THROW( Invalid_Outline );
 
     worker = raster->worker;
 
@@ -1893,19 +1947,19 @@
     if ( !( params->flags & FT_RASTER_FLAG_DIRECT ) )
     {
       if ( !target_map )
-        return ErrRaster_Invalid_Argument;
+        return FT_THROW( Invalid_Argument );
 
       /* nothing to do */
       if ( !target_map->width || !target_map->rows )
         return 0;
 
       if ( !target_map->buffer )
-        return ErrRaster_Invalid_Argument;
+        return FT_THROW( Invalid_Argument );
     }
 
     /* this version does not support monochrome rendering */
     if ( !( params->flags & FT_RASTER_FLAG_AA ) )
-      return ErrRaster_Invalid_Mode;
+      return FT_THROW( Invalid_Mode );
 
     /* compute clipping box */
     if ( !( params->flags & FT_RASTER_FLAG_DIRECT ) )
diff --git a/src/smooth/ftsmooth.c b/src/smooth/ftsmooth.c
index 00499cc..89088cd 100644
--- a/src/smooth/ftsmooth.c
+++ b/src/smooth/ftsmooth.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Anti-aliasing renderer interface (body).                             */
 /*                                                                         */
-/*  Copyright 2000-2006, 2009-2012 by                                      */
+/*  Copyright 2000-2006, 2009-2013 by                                      */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -61,12 +61,12 @@
                        const FT_Matrix*  matrix,
                        const FT_Vector*  delta )
   {
-    FT_Error  error = Smooth_Err_Ok;
+    FT_Error  error = FT_Err_Ok;
 
 
     if ( slot->format != render->glyph_format )
     {
-      error = Smooth_Err_Invalid_Argument;
+      error = FT_THROW( Invalid_Argument );
       goto Exit;
     }
 
@@ -109,31 +109,43 @@
 #ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
     FT_Pos       height_org, width_org;
 #endif
-    FT_Bitmap*   bitmap;
-    FT_Memory    memory;
-    FT_Int       hmul = mode == FT_RENDER_MODE_LCD;
-    FT_Int       vmul = mode == FT_RENDER_MODE_LCD_V;
-    FT_Pos       x_shift, y_shift, x_left, y_top;
+    FT_Bitmap*   bitmap  = &slot->bitmap;
+    FT_Memory    memory  = render->root.memory;
+    FT_Int       hmul    = mode == FT_RENDER_MODE_LCD;
+    FT_Int       vmul    = mode == FT_RENDER_MODE_LCD_V;
+    FT_Pos       x_shift = 0;
+    FT_Pos       y_shift = 0;
+    FT_Pos       x_left, y_top;
 
     FT_Raster_Params  params;
 
+    FT_Bool  have_translated_origin = FALSE;
+    FT_Bool  have_outline_shifted   = FALSE;
+    FT_Bool  have_buffer            = FALSE;
+
 
     /* check glyph image format */
     if ( slot->format != render->glyph_format )
     {
-      error = Smooth_Err_Invalid_Argument;
+      error = FT_THROW( Invalid_Argument );
       goto Exit;
     }
 
     /* check mode */
     if ( mode != required_mode )
-      return Smooth_Err_Cannot_Render_Glyph;
+    {
+      error = FT_THROW( Cannot_Render_Glyph );
+      goto Exit;
+    }
 
     outline = &slot->outline;
 
     /* translate the outline to the new origin if needed */
     if ( origin )
+    {
       FT_Outline_Translate( outline, origin->x, origin->y );
+      have_translated_origin = TRUE;
+    }
 
     /* compute the control box, and grid fit it */
     FT_Outline_Get_CBox( outline, &cbox );
@@ -148,24 +160,23 @@
       FT_ERROR(( "ft_smooth_render_generic: glyph too large:"
                  " xMin = %d, xMax = %d\n",
                  cbox.xMin >> 6, cbox.xMax >> 6 ));
-      return Smooth_Err_Raster_Overflow;
+      error = FT_THROW( Raster_Overflow );
+      goto Exit;
     }
     else
-      width  = ( cbox.xMax - cbox.xMin ) >> 6;
+      width = ( cbox.xMax - cbox.xMin ) >> 6;
 
     if ( cbox.yMin < 0 && cbox.yMax > FT_INT_MAX + cbox.yMin )
     {
       FT_ERROR(( "ft_smooth_render_generic: glyph too large:"
                  " yMin = %d, yMax = %d\n",
                  cbox.yMin >> 6, cbox.yMax >> 6 ));
-      return Smooth_Err_Raster_Overflow;
+      error = FT_THROW( Raster_Overflow );
+      goto Exit;
     }
     else
       height = ( cbox.yMax - cbox.yMin ) >> 6;
 
-    bitmap = &slot->bitmap;
-    memory = render->root.memory;
-
 #ifndef FT_CONFIG_OPTION_SUBPIXEL_RENDERING
     width_org  = width;
     height_org = height;
@@ -221,13 +232,14 @@
 
 #if FT_UINT_MAX > 0xFFFFU
 
-    /* Required check is ( pitch * height < FT_ULONG_MAX ),     */
-    /* but we care realistic cases only. Always pitch <= width. */
+    /* Required check is (pitch * height < FT_ULONG_MAX),        */
+    /* but we care realistic cases only.  Always pitch <= width. */
     if ( width > 0x7FFF || height > 0x7FFF )
     {
       FT_ERROR(( "ft_smooth_render_generic: glyph too large: %u x %u\n",
                  width, height ));
-      return Smooth_Err_Raster_Overflow;
+      error = FT_THROW( Raster_Overflow );
+      goto Exit;
     }
 
 #endif
@@ -240,9 +252,12 @@
 
     /* translate outline to render it into the bitmap */
     FT_Outline_Translate( outline, -x_shift, -y_shift );
+    have_outline_shifted = TRUE;
 
     if ( FT_ALLOC( bitmap->buffer, (FT_ULong)pitch * height ) )
       goto Exit;
+    else
+      have_buffer = TRUE;
 
     slot->internal->flags |= FT_GLYPH_OWN_BITMAP;
 
@@ -288,6 +303,9 @@
           vec->y /= 3;
     }
 
+    if ( error )
+      goto Exit;
+
     if ( slot->library->lcd_filter_func )
       slot->library->lcd_filter_func( bitmap, mode, slot->library );
 
@@ -295,6 +313,8 @@
 
     /* render outline into bitmap */
     error = render->raster_render( render->raster, &params );
+    if ( error )
+      goto Exit;
 
     /* expand it horizontally */
     if ( hmul )
@@ -346,25 +366,35 @@
 
 #endif /* !FT_CONFIG_OPTION_SUBPIXEL_RENDERING */
 
-    FT_Outline_Translate( outline, x_shift, y_shift );
-
     /*
      * XXX: on 16bit system, we return an error for huge bitmap
      * to prevent an overflow.
      */
     if ( x_left > FT_INT_MAX || y_top > FT_INT_MAX )
-      return Smooth_Err_Invalid_Pixel_Size;
-
-    if ( error )
+    {
+      error = FT_THROW( Invalid_Pixel_Size );
       goto Exit;
+    }
 
     slot->format      = FT_GLYPH_FORMAT_BITMAP;
     slot->bitmap_left = (FT_Int)x_left;
     slot->bitmap_top  = (FT_Int)y_top;
 
+    /* everything is fine; don't deallocate buffer */
+    have_buffer = FALSE;
+
+    error = FT_Err_Ok;
+
   Exit:
-    if ( outline && origin )
+    if ( have_outline_shifted )
+      FT_Outline_Translate( outline, x_shift, y_shift );
+    if ( have_translated_origin )
       FT_Outline_Translate( outline, -origin->x, -origin->y );
+    if ( have_buffer )
+    {
+      FT_FREE( bitmap->buffer );
+      slot->internal->flags &= ~FT_GLYPH_OWN_BITMAP;
+    }
 
     return error;
   }
diff --git a/src/smooth/ftspic.c b/src/smooth/ftspic.c
index 601bcf9..67a2b83 100644
--- a/src/smooth/ftspic.c
+++ b/src/smooth/ftspic.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType position independent code services for smooth module.   */
 /*                                                                         */
-/*  Copyright 2009, 2010 by                                                */
+/*  Copyright 2009, 2010, 2012, 2013 by                                    */
 /*  Oran Agra and Mickey Gabel.                                            */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -22,17 +22,19 @@
 #include "ftspic.h"
 #include "ftsmerrs.h"
 
+
 #ifdef FT_CONFIG_OPTION_PIC
 
   /* forward declaration of PIC init functions from ftgrays.c */
   void
   FT_Init_Class_ft_grays_raster( FT_Raster_Funcs*  funcs );
 
+
   void
   ft_smooth_renderer_class_pic_free( FT_Library  library )
   {
     FT_PIC_Container*  pic_container = &library->pic_container;
-    FT_Memory  memory = library->memory;
+    FT_Memory          memory        = library->memory;
 
 
     if ( pic_container->smooth )
@@ -42,6 +44,7 @@
 
       if ( --container->ref_count )
         return;
+
       FT_FREE( container );
       pic_container->smooth = NULL;
     }
@@ -52,8 +55,8 @@
   ft_smooth_renderer_class_pic_init( FT_Library  library )
   {
     FT_PIC_Container*  pic_container = &library->pic_container;
-    FT_Error           error         = Smooth_Err_Ok;
-    SmoothPIC*         container;
+    FT_Error           error         = FT_Err_Ok;
+    SmoothPIC*         container     = NULL;
     FT_Memory          memory        = library->memory;
 
 
@@ -66,37 +69,45 @@
     }
 
     /* allocate pointer, clear and set global container pointer */
-    if ( FT_ALLOC ( container, sizeof ( *container ) ) )
+    if ( FT_ALLOC( container, sizeof ( *container ) ) )
       return error;
     FT_MEM_SET( container, 0, sizeof ( *container ) );
     pic_container->smooth = container;
+
     container->ref_count = 1;
 
-    /* initialize pointer table - this is how the module usually expects this data */
+    /* initialize pointer table -                       */
+    /* this is how the module usually expects this data */
     FT_Init_Class_ft_grays_raster( &container->ft_grays_raster );
-/*Exit:*/
-    if ( error )
-      ft_smooth_renderer_class_pic_free( library );
+
     return error;
   }
 
+
   /* re-route these init and free functions to the above functions */
-  FT_Error ft_smooth_lcd_renderer_class_pic_init( FT_Library  library )
+  FT_Error
+  ft_smooth_lcd_renderer_class_pic_init( FT_Library  library )
   {
     return ft_smooth_renderer_class_pic_init( library );
   }
 
-  void ft_smooth_lcd_renderer_class_pic_free( FT_Library  library )
+
+  void
+  ft_smooth_lcd_renderer_class_pic_free( FT_Library  library )
   {
     ft_smooth_renderer_class_pic_free( library );
   }
 
-  FT_Error ft_smooth_lcdv_renderer_class_pic_init( FT_Library  library )
+
+  FT_Error
+  ft_smooth_lcdv_renderer_class_pic_init( FT_Library  library )
   {
     return ft_smooth_renderer_class_pic_init( library );
   }
 
-  void ft_smooth_lcdv_renderer_class_pic_free( FT_Library  library )
+
+  void
+  ft_smooth_lcdv_renderer_class_pic_free( FT_Library  library )
   {
     ft_smooth_renderer_class_pic_free( library );
   }
diff --git a/src/smooth/ftspic.h b/src/smooth/ftspic.h
index 4686f5e..334b51c 100644
--- a/src/smooth/ftspic.h
+++ b/src/smooth/ftspic.h
@@ -25,18 +25,23 @@
 #include FT_INTERNAL_PIC_H
 
 #ifndef FT_CONFIG_OPTION_PIC
-#define FT_GRAYS_RASTER_GET        ft_grays_raster
+
+#define FT_GRAYS_RASTER_GET  ft_grays_raster
 
 #else /* FT_CONFIG_OPTION_PIC */
 
-  typedef struct SmoothPIC_
+  typedef struct  SmoothPIC_
   {
-    int ref_count;
-    FT_Raster_Funcs ft_grays_raster;
+    int              ref_count;
+    FT_Raster_Funcs  ft_grays_raster;
+
   } SmoothPIC;
 
-#define GET_PIC(lib)               ((SmoothPIC*)((lib)->pic_container.smooth))
-#define FT_GRAYS_RASTER_GET        (GET_PIC(library)->ft_grays_raster)
+
+#define GET_PIC( lib ) \
+          ( (SmoothPIC*)( (lib)->pic_container.smooth ) )
+#define FT_GRAYS_RASTER_GET  ( GET_PIC( library )->ft_grays_raster )
+
 
   /* see ftspic.c for the implementation */
   void
diff --git a/src/truetype/truetype.c b/src/truetype/truetype.c
index 4bd1209..576912b 100644
--- a/src/truetype/truetype.c
+++ b/src/truetype/truetype.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    FreeType TrueType driver component (body only).                      */
 /*                                                                         */
-/*  Copyright 1996-2001, 2004, 2006 by                                     */
+/*  Copyright 1996-2001, 2004, 2006, 2012 by                               */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -27,6 +27,7 @@
 
 #ifdef TT_USE_BYTECODE_INTERPRETER
 #include "ttinterp.c"
+#include "ttsubpix.c"
 #endif
 
 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
diff --git a/src/truetype/ttdriver.c b/src/truetype/ttdriver.c
index 3669d45..fb25706 100644
--- a/src/truetype/ttdriver.c
+++ b/src/truetype/ttdriver.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    TrueType font driver implementation (body).                          */
 /*                                                                         */
-/*  Copyright 1996-2012 by                                                 */
+/*  Copyright 1996-2013 by                                                 */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -29,6 +29,8 @@
 
 #include FT_SERVICE_TRUETYPE_ENGINE_H
 #include FT_SERVICE_TRUETYPE_GLYF_H
+#include FT_SERVICE_PROPERTIES_H
+#include FT_TRUETYPE_DRIVER_H
 
 #include "ttdriver.h"
 #include "ttgload.h"
@@ -52,6 +54,73 @@
 #define FT_COMPONENT  trace_ttdriver
 
 
+  /*
+   *  PROPERTY SERVICE
+   *
+   */
+  static FT_Error
+  tt_property_set( FT_Module    module,         /* TT_Driver */
+                   const char*  property_name,
+                   const void*  value )
+  {
+    FT_Error   error  = FT_Err_Ok;
+    TT_Driver  driver = (TT_Driver)module;
+
+
+    if ( !ft_strcmp( property_name, "interpreter-version" ) )
+    {
+      FT_UInt*  interpreter_version = (FT_UInt*)value;
+
+
+#ifndef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+      if ( *interpreter_version != TT_INTERPRETER_VERSION_35 )
+        error = FT_ERR( Unimplemented_Feature );
+      else
+#endif
+        driver->interpreter_version = *interpreter_version;
+
+      return error;
+    }
+
+    FT_TRACE0(( "tt_property_set: missing property `%s'\n",
+                property_name ));
+    return FT_THROW( Missing_Property );
+  }
+
+
+  static FT_Error
+  tt_property_get( FT_Module    module,         /* TT_Driver */
+                   const char*  property_name,
+                   const void*  value )
+  {
+    FT_Error   error  = FT_Err_Ok;
+    TT_Driver  driver = (TT_Driver)module;
+
+    FT_UInt  interpreter_version = driver->interpreter_version;
+
+
+    if ( !ft_strcmp( property_name, "interpreter-version" ) )
+    {
+      FT_UInt*  val = (FT_UInt*)value;
+
+
+      *val = interpreter_version;
+
+      return error;
+    }
+
+    FT_TRACE0(( "tt_property_get: missing property `%s'\n",
+                property_name ));
+    return FT_THROW( Missing_Property );
+  }
+
+
+  FT_DEFINE_SERVICE_PROPERTIESREC(
+    tt_service_properties,
+    (FT_Properties_SetFunc)tt_property_set,
+    (FT_Properties_GetFunc)tt_property_get )
+
+
   /*************************************************************************/
   /*************************************************************************/
   /*************************************************************************/
@@ -163,7 +232,7 @@
       }
     }
 
-    return TT_Err_Ok;
+    return FT_Err_Ok;
   }
 
   /*************************************************************************/
@@ -187,7 +256,7 @@
   {
     TT_Face   ttface = (TT_Face)size->face;
     TT_Size   ttsize = (TT_Size)size;
-    FT_Error  error  = TT_Err_Ok;
+    FT_Error  error  = FT_Err_Ok;
 
 
     ttsize->strike_index = strike_index;
@@ -221,7 +290,7 @@
                    FT_Size_Request  req )
   {
     TT_Size   ttsize = (TT_Size)size;
-    FT_Error  error  = TT_Err_Ok;
+    FT_Error  error  = FT_Err_Ok;
 
 
 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
@@ -294,13 +363,13 @@
 
 
     if ( !slot )
-      return TT_Err_Invalid_Slot_Handle;
+      return FT_THROW( Invalid_Slot_Handle );
 
     if ( !size )
-      return TT_Err_Invalid_Size_Handle;
+      return FT_THROW( Invalid_Size_Handle );
 
     if ( !face )
-      return TT_Err_Invalid_Argument;
+      return FT_THROW( Invalid_Argument );
 
 #ifdef FT_CONFIG_OPTION_INCREMENTAL
     if ( glyph_index >= (FT_UInt)face->num_glyphs &&
@@ -308,7 +377,7 @@
 #else
     if ( glyph_index >= (FT_UInt)face->num_glyphs )
 #endif
-      return TT_Err_Invalid_Argument;
+      return FT_THROW( Invalid_Argument );
 
     if ( load_flags & FT_LOAD_NO_HINTING )
     {
@@ -353,13 +422,13 @@
   /*************************************************************************/
 
 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
-  FT_DEFINE_SERVICE_MULTIMASTERSREC(tt_service_gx_multi_masters,
+  FT_DEFINE_SERVICE_MULTIMASTERSREC(
+    tt_service_gx_multi_masters,
     (FT_Get_MM_Func)        NULL,
     (FT_Set_MM_Design_Func) NULL,
     (FT_Set_MM_Blend_Func)  TT_Set_MM_Blend,
     (FT_Get_MM_Var_Func)    TT_Get_MM_Var,
-    (FT_Set_Var_Design_Func)TT_Set_Var_Design
-  )
+    (FT_Set_Var_Design_Func)TT_Set_Var_Design )
 #endif
 
   static const FT_Service_TrueTypeEngineRec  tt_service_truetype_engine =
@@ -379,25 +448,28 @@
 #endif /* TT_USE_BYTECODE_INTERPRETER */
   };
 
-  FT_DEFINE_SERVICE_TTGLYFREC(tt_service_truetype_glyf,
-    (TT_Glyf_GetLocationFunc)tt_face_get_location
-  )
+  FT_DEFINE_SERVICE_TTGLYFREC(
+    tt_service_truetype_glyf,
+    (TT_Glyf_GetLocationFunc)tt_face_get_location )
 
 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
-  FT_DEFINE_SERVICEDESCREC4(tt_services,
+  FT_DEFINE_SERVICEDESCREC5(
+    tt_services,
     FT_SERVICE_ID_XF86_NAME,       FT_XF86_FORMAT_TRUETYPE,
-    FT_SERVICE_ID_MULTI_MASTERS,   &FT_TT_SERVICE_GX_MULTI_MASTERS_GET,
+    FT_SERVICE_ID_MULTI_MASTERS,   &TT_SERVICE_GX_MULTI_MASTERS_GET,
     FT_SERVICE_ID_TRUETYPE_ENGINE, &tt_service_truetype_engine,
-    FT_SERVICE_ID_TT_GLYF,         &FT_TT_SERVICE_TRUETYPE_GLYF_GET
-  )
+    FT_SERVICE_ID_TT_GLYF,         &TT_SERVICE_TRUETYPE_GLYF_GET,
+    FT_SERVICE_ID_PROPERTIES,      &TT_SERVICE_PROPERTIES_GET )
 #else
-  FT_DEFINE_SERVICEDESCREC3(tt_services,
+  FT_DEFINE_SERVICEDESCREC4(
+    tt_services,
     FT_SERVICE_ID_XF86_NAME,       FT_XF86_FORMAT_TRUETYPE,
     FT_SERVICE_ID_TRUETYPE_ENGINE, &tt_service_truetype_engine,
-    FT_SERVICE_ID_TT_GLYF,         &FT_TT_SERVICE_TRUETYPE_GLYF_GET
-  )
+    FT_SERVICE_ID_TT_GLYF,         &TT_SERVICE_TRUETYPE_GLYF_GET,
+    FT_SERVICE_ID_PROPERTIES,      &TT_SERVICE_PROPERTIES_GET )
 #endif
 
+
   FT_CALLBACK_DEF( FT_Module_Interface )
   tt_get_interface( FT_Module    driver,    /* TT_Driver */
                     const char*  tt_interface )
@@ -408,7 +480,7 @@
     SFNT_Service         sfnt;
 
 
-    /* FT_TT_SERVICES_GET derefers `library' in PIC mode */
+    /* TT_SERVICES_GET derefers `library' in PIC mode */
 #ifdef FT_CONFIG_OPTION_PIC
     if ( !driver )
       return NULL;
@@ -417,7 +489,7 @@
       return NULL;
 #endif
 
-    result = ft_service_list_lookup( FT_TT_SERVICES_GET, tt_interface );
+    result = ft_service_list_lookup( TT_SERVICES_GET, tt_interface );
     if ( result != NULL )
       return result;
 
@@ -445,18 +517,19 @@
   /* The FT_DriverInterface structure is defined in ftdriver.h. */
 
 #ifdef TT_USE_BYTECODE_INTERPRETER
-#define TT_HINTER_FLAG   FT_MODULE_DRIVER_HAS_HINTER
+#define TT_HINTER_FLAG  FT_MODULE_DRIVER_HAS_HINTER
 #else
-#define TT_HINTER_FLAG   0
+#define TT_HINTER_FLAG  0
 #endif
 
 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
-#define TT_SIZE_SELECT    tt_size_select
+#define TT_SIZE_SELECT  tt_size_select
 #else
-#define TT_SIZE_SELECT    0
+#define TT_SIZE_SELECT  0
 #endif
 
-  FT_DEFINE_DRIVER( tt_driver_class,
+  FT_DEFINE_DRIVER(
+    tt_driver_class,
 
       FT_MODULE_FONT_DRIVER     |
       FT_MODULE_DRIVER_SCALABLE |
@@ -485,9 +558,6 @@
     tt_slot_init,
     0,                       /* FT_Slot_DoneFunc */
 
-    ft_stub_set_char_sizes,  /* FT_CONFIG_OPTION_OLD_INTERNALS */
-    ft_stub_set_pixel_sizes, /* FT_CONFIG_OPTION_OLD_INTERNALS */
-
     tt_glyph_load,
 
     tt_get_kerning,
diff --git a/src/truetype/ttgload.c b/src/truetype/ttgload.c
index ce8c888..f640a6c 100644
--- a/src/truetype/ttgload.c
+++ b/src/truetype/ttgload.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    TrueType Glyph Loader (body).                                        */
 /*                                                                         */
-/*  Copyright 1996-2012                                                    */
+/*  Copyright 1996-2013                                                    */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -23,6 +23,7 @@
 #include FT_INTERNAL_SFNT_H
 #include FT_TRUETYPE_TAGS_H
 #include FT_OUTLINE_H
+#include FT_TRUETYPE_DRIVER_H
 
 #include "ttgload.h"
 #include "ttpload.h"
@@ -32,6 +33,7 @@
 #endif
 
 #include "tterrors.h"
+#include "ttsubpix.h"
 
 
   /*************************************************************************/
@@ -131,7 +133,10 @@
   tt_get_metrics( TT_Loader  loader,
                   FT_UInt    glyph_index )
   {
-    TT_Face  face = (TT_Face)loader->face;
+    TT_Face    face   = (TT_Face)loader->face;
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+    TT_Driver  driver = (TT_Driver)FT_FACE_DRIVER( face );
+#endif
 
     FT_Short   left_bearing = 0, top_bearing = 0;
     FT_UShort  advance_width = 0, advance_height = 0;
@@ -149,6 +154,18 @@
     loader->top_bearing  = top_bearing;
     loader->vadvance     = advance_height;
 
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+    if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
+    {
+      if ( loader->exec )
+        loader->exec->sph_tweak_flags = 0;
+
+      /* this may not be the right place for this, but it works */
+      if ( loader->exec && loader->exec->ignore_x_mode )
+        sph_set_tweaks( loader, glyph_index );
+    }
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
     if ( !loader->linear_def )
     {
       loader->linear_def = 1;
@@ -252,10 +269,6 @@
   }
 
 
-#undef  IS_HINTED
-#define IS_HINTED( flags )  ( ( flags & FT_LOAD_NO_HINTING ) == 0 )
-
-
   /*************************************************************************/
   /*                                                                       */
   /* The following functions are used by default with TrueType fonts.      */
@@ -286,7 +299,7 @@
     loader->cursor = stream->cursor;
     loader->limit  = stream->limit;
 
-    return TT_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
@@ -308,7 +321,7 @@
 
 
     if ( p + 10 > limit )
-      return TT_Err_Invalid_Outline;
+      return FT_THROW( Invalid_Outline );
 
     loader->n_contours = FT_NEXT_SHORT( p );
 
@@ -324,7 +337,7 @@
                                             loader->bbox.yMax ));
     loader->cursor = p;
 
-    return TT_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
@@ -409,14 +422,14 @@
     {
       FT_TRACE0(( "TT_Load_Simple_Glyph: too many instructions (%d)\n",
                   n_ins ));
-      error = TT_Err_Too_Many_Hints;
+      error = FT_THROW( Too_Many_Hints );
       goto Fail;
     }
 
     if ( ( limit - p ) < n_ins )
     {
       FT_TRACE0(( "TT_Load_Simple_Glyph: instruction count mismatch\n" ));
-      error = TT_Err_Too_Many_Hints;
+      error = FT_THROW( Too_Many_Hints );
       goto Fail;
     }
 
@@ -546,7 +559,7 @@
     return error;
 
   Invalid_Outline:
-    error = TT_Err_Invalid_Outline;
+    error = FT_THROW( Invalid_Outline );
     goto Fail;
   }
 
@@ -667,7 +680,7 @@
     return error;
 
   Invalid_Composite:
-    error = TT_Err_Invalid_Composite;
+    error = FT_THROW( Invalid_Composite );
     goto Fail;
   }
 
@@ -714,6 +727,11 @@
   TT_Hint_Glyph( TT_Loader  loader,
                  FT_Bool    is_composite )
   {
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+    TT_Face    face   = (TT_Face)loader->face;
+    TT_Driver  driver = (TT_Driver)FT_FACE_DRIVER( face );
+#endif
+
     TT_GlyphZone  zone = &loader->zone;
     FT_Pos        origin;
 
@@ -813,7 +831,18 @@
       loader->pp4 = zone->cur[zone->n_points - 1];
     }
 
-    return TT_Err_Ok;
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+    if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
+    {
+      if ( loader->exec->sph_tweak_flags & SPH_TWEAK_DEEMBOLDEN )
+        FT_Outline_EmboldenXY( &loader->gloader->current.outline, -24, 0 );
+
+      else if ( loader->exec->sph_tweak_flags & SPH_TWEAK_EMBOLDEN )
+        FT_Outline_EmboldenXY( &loader->gloader->current.outline, 24, 0 );
+    }
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
+    return FT_Err_Ok;
   }
 
 
@@ -831,7 +860,7 @@
   TT_Process_Simple_Glyph( TT_Loader  loader )
   {
     FT_GlyphLoader  gloader = loader->gloader;
-    FT_Error        error   = TT_Err_Ok;
+    FT_Error        error   = FT_Err_Ok;
     FT_Outline*     outline;
     FT_Int          n_points;
 
@@ -889,25 +918,83 @@
                      loader->zone.n_points + 4 );
     }
 
-    /* scale the glyph */
-    if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
     {
-      FT_Vector*  vec     = outline->points;
-      FT_Vector*  limit   = outline->points + n_points;
-      FT_Fixed    x_scale = ((TT_Size)loader->size)->metrics.x_scale;
-      FT_Fixed    y_scale = ((TT_Size)loader->size)->metrics.y_scale;
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+      TT_Face    face   = (TT_Face)loader->face;
+      TT_Driver  driver = (TT_Driver)FT_FACE_DRIVER( face );
+
+      FT_String*  family         = face->root.family_name;
+      FT_Int      ppem           = loader->size->metrics.x_ppem;
+      FT_String*  style          = face->root.style_name;
+      FT_Int      x_scale_factor = 1000;
+#endif
+
+      FT_Vector*  vec   = outline->points;
+      FT_Vector*  limit = outline->points + n_points;
+
+      FT_Fixed  x_scale = 0; /* pacify compiler */
+      FT_Fixed  y_scale = 0;
+
+      FT_Bool  do_scale = FALSE;
 
 
-      for ( ; vec < limit; vec++ )
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+
+      if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
       {
-        vec->x = FT_MulFix( vec->x, x_scale );
-        vec->y = FT_MulFix( vec->y, y_scale );
+        /* scale, but only if enabled and only if TT hinting is being used */
+        if ( IS_HINTED( loader->load_flags ) )
+          x_scale_factor = sph_test_tweak_x_scaling( face,
+                                                     family,
+                                                     ppem,
+                                                     style,
+                                                     loader->glyph_index );
+        /* scale the glyph */
+        if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ||
+             x_scale_factor != 1000                         )
+        {
+          x_scale = FT_MulDiv( ((TT_Size)loader->size)->metrics.x_scale,
+                               x_scale_factor, 1000 );
+          y_scale = ((TT_Size)loader->size)->metrics.y_scale;
+
+          /* compensate for any scaling by de/emboldening; */
+          /* the amount was determined via experimentation */
+          if ( x_scale_factor != 1000 && ppem > 11 )
+            FT_Outline_EmboldenXY( outline,
+                                   FT_MulFix( 1280 * ppem,
+                                              1000 - x_scale_factor ),
+                                   0 );
+          do_scale = TRUE;
+        }
+      }
+      else
+
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
+      {
+        /* scale the glyph */
+        if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 )
+        {
+          x_scale = ((TT_Size)loader->size)->metrics.x_scale;
+          y_scale = ((TT_Size)loader->size)->metrics.y_scale;
+
+          do_scale = TRUE;
+        }
       }
 
-      loader->pp1 = outline->points[n_points - 4];
-      loader->pp2 = outline->points[n_points - 3];
-      loader->pp3 = outline->points[n_points - 2];
-      loader->pp4 = outline->points[n_points - 1];
+      if ( do_scale )
+      {
+        for ( ; vec < limit; vec++ )
+        {
+          vec->x = FT_MulFix( vec->x, x_scale );
+          vec->y = FT_MulFix( vec->y, y_scale );
+        }
+
+        loader->pp1 = outline->points[n_points - 4];
+        loader->pp2 = outline->points[n_points - 3];
+        loader->pp3 = outline->points[n_points - 2];
+        loader->pp4 = outline->points[n_points - 1];
+      }
     }
 
     if ( IS_HINTED( loader->load_flags ) )
@@ -974,7 +1061,7 @@
       l += num_base_points;
       if ( k >= num_base_points ||
            l >= num_points      )
-        return TT_Err_Invalid_Composite;
+        return FT_THROW( Invalid_Composite );
 
       p1 = gloader->base.outline.points + k;
       p2 = gloader->base.outline.points + l;
@@ -988,7 +1075,7 @@
       y = subglyph->arg2;
 
       if ( !x && !y )
-        return TT_Err_Ok;
+        return FT_Err_Ok;
 
   /* Use a default value dependent on                                     */
   /* TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED.  This is useful for old TT */
@@ -1033,16 +1120,10 @@
   /*                                                                       */
   /* This algorithm is a guess and works much better than the above.       */
   /*                                                                       */
-        FT_Fixed  mac_xscale = FT_SqrtFixed(
-                                 (FT_Int32)FT_MulFix( subglyph->transform.xx,
-                                                      subglyph->transform.xx ) +
-                                 (FT_Int32)FT_MulFix( subglyph->transform.xy,
-                                                      subglyph->transform.xy ) );
-        FT_Fixed  mac_yscale = FT_SqrtFixed(
-                                 (FT_Int32)FT_MulFix( subglyph->transform.yy,
-                                                      subglyph->transform.yy ) +
-                                 (FT_Int32)FT_MulFix( subglyph->transform.yx,
-                                                      subglyph->transform.yx ) );
+        FT_Fixed  mac_xscale = FT_Hypot( subglyph->transform.xx,
+                                         subglyph->transform.xy );
+        FT_Fixed  mac_yscale = FT_Hypot( subglyph->transform.yy,
+                                         subglyph->transform.yx );
 
 
         x = FT_MulFix( x, mac_xscale );
@@ -1074,7 +1155,7 @@
                        base_vec + num_base_points,
                        x, y );
 
-    return TT_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
@@ -1143,7 +1224,7 @@
           FT_TRACE1(( "TT_Process_Composite_Glyph: "
                       "too many instructions (%d) for glyph with length %d\n",
                       n_ins, loader->byte_len ));
-          return TT_Err_Too_Many_Hints;
+          return FT_THROW( Too_Many_Hints );
         }
 
         tmp = loader->exec->glyphSize;
@@ -1157,7 +1238,7 @@
           return error;
       }
       else if ( n_ins == 0 )
-        return TT_Err_Ok;
+        return FT_Err_Ok;
 
       if ( FT_STREAM_READ( loader->exec->glyphIns, n_ins ) )
         return error;
@@ -1213,7 +1294,7 @@
                        FT_UInt    recurse_count,
                        FT_Bool    header_only )
   {
-    FT_Error        error        = TT_Err_Ok;
+    FT_Error        error        = FT_Err_Ok;
     FT_Fixed        x_scale, y_scale;
     FT_ULong        offset;
     TT_Face         face         = (TT_Face)loader->face;
@@ -1236,14 +1317,14 @@
     if ( recurse_count > 1                                   &&
          recurse_count > face->max_profile.maxComponentDepth )
     {
-      error = TT_Err_Invalid_Composite;
+      error = FT_THROW( Invalid_Composite );
       goto Exit;
     }
 
     /* check glyph index */
     if ( glyph_index >= (FT_UInt)face->root.num_glyphs )
     {
-      error = TT_Err_Invalid_Glyph_Index;
+      error = FT_THROW( Invalid_Glyph_Index );
       goto Exit;
     }
 
@@ -1307,7 +1388,7 @@
 #endif /* FT_CONFIG_OPTION_INCREMENTAL */
       {
         FT_TRACE2(( "no `glyf' table but non-zero `loca' entry\n" ));
-        error = TT_Err_Invalid_Table;
+        error = FT_THROW( Invalid_Table );
         goto Exit;
       }
 
@@ -1374,7 +1455,7 @@
         loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale );
       }
 
-      error = TT_Err_Ok;
+      error = FT_Err_Ok;
       goto Exit;
     }
 
@@ -1588,7 +1669,7 @@
     else
     {
       /* invalid composite count (negative but not -1) */
-      error = TT_Err_Invalid_Outline;
+      error = FT_THROW( Invalid_Outline );
       goto Exit;
     }
 
@@ -1618,11 +1699,15 @@
   compute_glyph_metrics( TT_Loader  loader,
                          FT_UInt    glyph_index )
   {
+    TT_Face    face   = (TT_Face)loader->face;
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+    TT_Driver  driver = (TT_Driver)FT_FACE_DRIVER( face );
+#endif
+
     FT_BBox       bbox;
-    TT_Face       face = (TT_Face)loader->face;
     FT_Fixed      y_scale;
     TT_GlyphSlot  glyph = loader->glyph;
-    TT_Size       size = (TT_Size)loader->size;
+    TT_Size       size  = (TT_Size)loader->size;
 
 
     y_scale = 0x10000L;
@@ -1653,8 +1738,30 @@
                                            size->root.metrics.x_ppem,
                                            glyph_index );
 
-      if ( widthp )
-        glyph->metrics.horiAdvance = *widthp << 6;
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+
+      if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
+      {
+        FT_Bool  ignore_x_mode;
+
+
+        ignore_x_mode = FT_BOOL( FT_LOAD_TARGET_MODE( loader->load_flags ) !=
+                                 FT_RENDER_MODE_MONO );
+
+        if ( widthp                                                   &&
+             ( ( ignore_x_mode && loader->exec->compatible_widths ) ||
+                !ignore_x_mode                                      ||
+                SPH_OPTION_BITMAP_WIDTHS                            ) )
+          glyph->metrics.horiAdvance = *widthp << 6;
+      }
+      else
+
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
+      {
+        if ( widthp )
+          glyph->metrics.horiAdvance = *widthp << 6;
+      }
     }
 
     /* set glyph dimensions */
@@ -1833,7 +1940,9 @@
   {
     TT_Face    face;
     FT_Stream  stream;
+#ifdef TT_USE_BYTECODE_INTERPRETER
     FT_Bool    pedantic = FT_BOOL( load_flags & FT_LOAD_PEDANTIC );
+#endif
 
 
     face   = (TT_Face)glyph->face;
@@ -1849,6 +1958,23 @@
       TT_ExecContext  exec;
       FT_Bool         grayscale;
 
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+      TT_Driver  driver = (TT_Driver)FT_FACE_DRIVER( face );
+
+      FT_Bool  subpixel_hinting  = FALSE;
+      FT_Bool  grayscale_hinting = TRUE;
+
+#if 0
+      /* not used yet */
+      FT_Bool  compatible_widths;
+      FT_Bool  symmetrical_smoothing;
+      FT_Bool  bgr;
+      FT_Bool  subpixel_positioned;
+#endif
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
+      FT_Bool  reexecute = FALSE;
+
 
       if ( !size->cvt_ready )
       {
@@ -1863,25 +1989,114 @@
       exec = size->debug ? size->context
                          : ( (TT_Driver)FT_FACE_DRIVER( face ) )->context;
       if ( !exec )
-        return TT_Err_Could_Not_Find_Context;
+        return FT_THROW( Could_Not_Find_Context );
 
-      grayscale =
-        FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != FT_RENDER_MODE_MONO );
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+
+      if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
+      {
+        subpixel_hinting = FT_BOOL( ( FT_LOAD_TARGET_MODE( load_flags )
+                                      != FT_RENDER_MODE_MONO )          &&
+                                    SPH_OPTION_SET_SUBPIXEL             );
+
+        if ( subpixel_hinting )
+          grayscale = grayscale_hinting = FALSE;
+        else if ( SPH_OPTION_SET_GRAYSCALE )
+        {
+          grayscale = grayscale_hinting = TRUE;
+          subpixel_hinting              = FALSE;
+        }
+        else
+          grayscale = grayscale_hinting = FALSE;
+
+        if ( FT_IS_TRICKY( glyph->face ) )
+          subpixel_hinting = grayscale_hinting = FALSE;
+
+        exec->ignore_x_mode      = subpixel_hinting || grayscale_hinting;
+        exec->rasterizer_version = SPH_OPTION_SET_RASTERIZER_VERSION;
+        if ( exec->sph_tweak_flags & SPH_TWEAK_RASTERIZER_35 )
+          exec->rasterizer_version = TT_INTERPRETER_VERSION_35;
+
+#if 1
+        exec->compatible_widths     = SPH_OPTION_SET_COMPATIBLE_WIDTHS;
+        exec->symmetrical_smoothing = FALSE;
+        exec->bgr                   = FALSE;
+        exec->subpixel_positioned   = TRUE;
+#else /* 0 */
+        exec->compatible_widths =
+          FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
+                   TT_LOAD_COMPATIBLE_WIDTHS );
+        exec->symmetrical_smoothing =
+          FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
+                   TT_LOAD_SYMMETRICAL_SMOOTHING );
+        exec->bgr =
+          FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
+                   TT_LOAD_BGR );
+        exec->subpixel_positioned =
+          FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
+                   TT_LOAD_SUBPIXEL_POSITIONED );
+#endif /* 0 */
+
+      }
+      else
+
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
+      {
+        grayscale = FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) !=
+                             FT_RENDER_MODE_MONO );
+      }
 
       TT_Load_Context( exec, face, size );
 
-      /* a change from mono to grayscale rendering (and vice versa) */
-      /* requires a re-execution of the CVT program                 */
-      if ( grayscale != exec->grayscale )
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+
+      if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 )
+      {
+        /* a change from mono to subpixel rendering (and vice versa) */
+        /* requires a re-execution of the CVT program                */
+        if ( subpixel_hinting != exec->subpixel_hinting )
+        {
+          FT_TRACE4(( "tt_loader_init: subpixel hinting change,"
+                      " re-executing `prep' table\n" ));
+
+          exec->subpixel_hinting = subpixel_hinting;
+          reexecute              = TRUE;
+        }
+
+        /* a change from mono to grayscale rendering (and vice versa) */
+        /* requires a re-execution of the CVT program                 */
+        if ( grayscale != exec->grayscale_hinting )
+        {
+          FT_TRACE4(( "tt_loader_init: grayscale hinting change,"
+                      " re-executing `prep' table\n" ));
+
+          exec->grayscale_hinting = grayscale_hinting;
+          reexecute               = TRUE;
+        }
+      }
+      else
+
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
+      {
+        /* a change from mono to grayscale rendering (and vice versa) */
+        /* requires a re-execution of the CVT program                 */
+        if ( grayscale != exec->grayscale )
+        {
+          FT_TRACE4(( "tt_loader_init: grayscale change,"
+                      " re-executing `prep' table\n" ));
+
+          exec->grayscale = grayscale;
+          reexecute       = TRUE;
+        }
+      }
+
+      if ( reexecute )
       {
         FT_UInt  i;
 
 
-        FT_TRACE4(( "tt_loader_init: grayscale change,"
-                    " re-executing `prep' table\n" ));
-
-        exec->grayscale = grayscale;
-
         for ( i = 0; i < size->cvt_size; i++ )
           size->cvt[i] = FT_MulFix( face->cvt[i], size->ttmetrics.scale );
         tt_size_run_prep( size, pedantic );
@@ -1918,7 +2133,7 @@
       FT_Error  error = face->goto_table( face, TTAG_glyf, stream, 0 );
 
 
-      if ( error == TT_Err_Table_Missing )
+      if ( FT_ERR_EQ( error, Table_Missing ) )
         loader->glyf_offset = 0;
       else if ( error )
       {
@@ -1946,7 +2161,7 @@
     loader->glyph  = (FT_GlyphSlot)glyph;
     loader->stream = stream;
 
-    return TT_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
@@ -1983,13 +2198,11 @@
                  FT_UInt       glyph_index,
                  FT_Int32      load_flags )
   {
-    TT_Face       face;
     FT_Error      error;
     TT_LoaderRec  loader;
 
 
-    face   = (TT_Face)glyph->face;
-    error  = TT_Err_Ok;
+    error = FT_Err_Ok;
 
 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
 
@@ -2003,10 +2216,7 @@
       error = load_sbit_image( size, glyph, glyph_index, load_flags );
       if ( !error )
       {
-        FT_Face  root = &face->root;
-
-
-        if ( FT_IS_SCALABLE( root ) )
+        if ( FT_IS_SCALABLE( glyph->face ) )
         {
           /* for the bbox we need the header only */
           (void)tt_loader_init( &loader, size, glyph, load_flags, TRUE );
@@ -2014,9 +2224,16 @@
           glyph->linearHoriAdvance = loader.linear;
           glyph->linearVertAdvance = loader.top_bearing + loader.bbox.yMax -
                                        loader.vadvance;
+
+          /* sanity check: if `horiAdvance' in the sbit metric */
+          /* structure isn't set, use `linearHoriAdvance'      */
+          if ( !glyph->metrics.horiAdvance && glyph->linearHoriAdvance )
+            glyph->metrics.horiAdvance =
+              FT_MulFix( glyph->linearHoriAdvance,
+                         size->root.metrics.x_scale );
         }
 
-        return TT_Err_Ok;
+        return FT_Err_Ok;
       }
     }
 
@@ -2024,10 +2241,10 @@
 
     /* if FT_LOAD_NO_SCALE is not set, `ttmetrics' must be valid */
     if ( !( load_flags & FT_LOAD_NO_SCALE ) && !size->ttmetrics.valid )
-      return TT_Err_Invalid_Size_Handle;
+      return FT_THROW( Invalid_Size_Handle );
 
     if ( load_flags & FT_LOAD_SBITS_ONLY )
-      return TT_Err_Invalid_Argument;
+      return FT_THROW( Invalid_Argument );
 
     error = tt_loader_init( &loader, size, glyph, load_flags, FALSE );
     if ( error )
diff --git a/src/truetype/ttgxvar.c b/src/truetype/ttgxvar.c
index 69b702f..7899d36 100644
--- a/src/truetype/ttgxvar.c
+++ b/src/truetype/ttgxvar.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    TrueType GX Font Variation loader                                    */
 /*                                                                         */
-/*  Copyright 2004-2011 by                                                 */
+/*  Copyright 2004-2013 by                                                 */
 /*  David Turner, Robert Wilhelm, Werner Lemberg, and George Williams.     */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -61,9 +61,9 @@
 
 
 #define FT_Stream_FTell( stream )  \
-          ( (stream)->cursor - (stream)->base )
+          (FT_ULong)( (stream)->cursor - (stream)->base )
 #define FT_Stream_SeekSet( stream, off ) \
-              ( (stream)->cursor = (stream)->base+(off) )
+          ( (stream)->cursor = (stream)->base + (off) )
 
 
   /*************************************************************************/
@@ -91,7 +91,9 @@
   /* indicates that there is a delta for every point without needing to    */
   /* enumerate all of them.                                                */
   /*                                                                       */
-#define ALL_POINTS  (FT_UShort*)( -1 )
+
+  /* ensure that value `0' has the same width as a pointer */
+#define ALL_POINTS  (FT_UShort*)~(FT_PtrDist)0
 
 
 #define GX_PT_POINTS_ARE_WORDS      0x80
@@ -130,7 +132,7 @@
     FT_Int     j;
     FT_Int     first;
     FT_Memory  memory = stream->memory;
-    FT_Error   error  = TT_Err_Ok;
+    FT_Error   error  = FT_Err_Ok;
 
     FT_UNUSED( error );
 
@@ -215,7 +217,7 @@
     FT_Offset  i;
     FT_UInt    j;
     FT_Memory  memory = stream->memory;
-    FT_Error   error  = TT_Err_Ok;
+    FT_Error   error  = FT_Err_Ok;
 
     FT_UNUSED( error );
 
@@ -283,7 +285,7 @@
     FT_Memory       memory = stream->memory;
     GX_Blend        blend  = face->blend;
     GX_AVarSegment  segment;
-    FT_Error        error = TT_Err_Ok;
+    FT_Error        error = FT_Err_Ok;
     FT_ULong        version;
     FT_Long         axisCount;
     FT_Int          i, j;
@@ -412,7 +414,7 @@
     if ( gvar_head.version   != (FT_Long)0x00010000L              ||
          gvar_head.axisCount != (FT_UShort)blend->mmvar->num_axis )
     {
-      error = TT_Err_Invalid_Table;
+      error = FT_THROW( Invalid_Table );
       goto Exit;
     }
 
@@ -501,11 +503,9 @@
                       FT_Fixed*  im_end_coords )
   {
     FT_UInt   i;
-    FT_Fixed  apply;
-    FT_Fixed  temp;
+    FT_Fixed  apply = 0x10000L;
 
 
-    apply = 0x10000L;
     for ( i = 0; i < blend->num_axis; ++i )
     {
       if ( tuple_coords[i] == 0 )
@@ -525,11 +525,10 @@
 
       else if ( !( tupleIndex & GX_TI_INTERMEDIATE_TUPLE ) )
         /* not an intermediate tuple */
-        apply = FT_MulDiv( apply,
+        apply = FT_MulFix( apply,
                            blend->normalizedcoords[i] > 0
                              ? blend->normalizedcoords[i]
-                             : -blend->normalizedcoords[i],
-                           0x10000L );
+                             : -blend->normalizedcoords[i] );
 
       else if ( blend->normalizedcoords[i] <= im_start_coords[i] ||
                 blend->normalizedcoords[i] >= im_end_coords[i]   )
@@ -539,20 +538,14 @@
       }
 
       else if ( blend->normalizedcoords[i] < tuple_coords[i] )
-      {
-        temp = FT_MulDiv( blend->normalizedcoords[i] - im_start_coords[i],
-                          0x10000L,
-                          tuple_coords[i] - im_start_coords[i]);
-        apply = FT_MulDiv( apply, temp, 0x10000L );
-      }
+        apply = FT_MulDiv( apply,
+                           blend->normalizedcoords[i] - im_start_coords[i],
+                           tuple_coords[i] - im_start_coords[i] );
 
       else
-      {
-        temp = FT_MulDiv( im_end_coords[i] - blend->normalizedcoords[i],
-                          0x10000L,
-                          im_end_coords[i] - tuple_coords[i] );
-        apply = FT_MulDiv( apply, temp, 0x10000L );
-      }
+        apply = FT_MulDiv( apply,
+                           im_end_coords[i] - blend->normalizedcoords[i],
+                           im_end_coords[i] - tuple_coords[i] );
     }
 
     return apply;
@@ -619,7 +612,7 @@
     FT_Stream            stream = face->root.stream;
     FT_Memory            memory = face->root.memory;
     FT_ULong             table_len;
-    FT_Error             error  = TT_Err_Ok;
+    FT_Error             error  = FT_Err_Ok;
     FT_ULong             fvar_start;
     FT_Int               i, j;
     FT_MM_Var*           mmvar = NULL;
@@ -690,7 +683,7 @@
            fvar_head.offsetToData + fvar_head.axisCount * 20U +
              fvar_head.instanceCount * fvar_head.instanceSize > table_len )
       {
-        error = TT_Err_Invalid_Table;
+        error = FT_THROW( Invalid_Table );
         goto Exit;
       }
 
@@ -712,7 +705,7 @@
       mmvar->num_axis =
         fvar_head.axisCount;
       mmvar->num_designs =
-        (FT_UInt)-1;           /* meaningless in this context; each glyph */
+        ~0U;                   /* meaningless in this context; each glyph */
                                /* may have a different number of designs  */
                                /* (or tuples, as called by Apple)         */
       mmvar->num_namedstyles =
@@ -856,7 +849,7 @@
                    FT_UInt    num_coords,
                    FT_Fixed*  coords )
   {
-    FT_Error    error = TT_Err_Ok;
+    FT_Error    error = FT_Err_Ok;
     GX_Blend    blend;
     FT_MM_Var*  mmvar;
     FT_UInt     i;
@@ -884,14 +877,14 @@
 
     if ( num_coords != mmvar->num_axis )
     {
-      error = TT_Err_Invalid_Argument;
+      error = FT_THROW( Invalid_Argument );
       goto Exit;
     }
 
     for ( i = 0; i < num_coords; ++i )
       if ( coords[i] < -0x00010000L || coords[i] > 0x00010000L )
       {
-        error = TT_Err_Invalid_Argument;
+        error = FT_THROW( Invalid_Argument );
         goto Exit;
       }
 
@@ -992,7 +985,7 @@
                      FT_UInt    num_coords,
                      FT_Fixed*  coords )
   {
-    FT_Error        error      = TT_Err_Ok;
+    FT_Error        error      = FT_Err_Ok;
     FT_Fixed*       normalized = NULL;
     GX_Blend        blend;
     FT_MM_Var*      mmvar;
@@ -1013,7 +1006,7 @@
 
     if ( num_coords != mmvar->num_axis )
     {
-      error = TT_Err_Invalid_Argument;
+      error = FT_THROW( Invalid_Argument );
       goto Exit;
     }
 
@@ -1029,24 +1022,16 @@
     {
       if ( coords[i] > a->maximum || coords[i] < a->minimum )
       {
-        error = TT_Err_Invalid_Argument;
+        error = FT_THROW( Invalid_Argument );
         goto Exit;
       }
 
       if ( coords[i] < a->def )
-      {
-        normalized[i] = -FT_MulDiv( coords[i] - a->def,
-                                    0x10000L,
-                                    a->minimum - a->def );
-      }
+        normalized[i] = -FT_DivFix( coords[i] - a->def, a->minimum - a->def );
       else if ( a->maximum == a->def )
         normalized[i] = 0;
       else
-      {
-        normalized[i] = FT_MulDiv( coords[i] - a->def,
-                                   0x10000L,
-                                   a->maximum - a->def );
-      }
+        normalized[i] = FT_DivFix( coords[i] - a->def, a->maximum - a->def );
     }
 
     if ( !blend->avar_checked )
@@ -1061,15 +1046,11 @@
           if ( normalized[i] < av->correspondence[j].fromCoord )
           {
             normalized[i] =
-              FT_MulDiv(
-                FT_MulDiv(
-                  normalized[i] - av->correspondence[j - 1].fromCoord,
-                  0x10000L,
-                  av->correspondence[j].fromCoord -
-                    av->correspondence[j - 1].fromCoord ),
-                av->correspondence[j].toCoord -
-                  av->correspondence[j - 1].toCoord,
-                0x10000L ) +
+              FT_MulDiv( normalized[i] - av->correspondence[j - 1].fromCoord,
+                         av->correspondence[j].toCoord -
+                           av->correspondence[j - 1].toCoord,
+                         av->correspondence[j].fromCoord -
+                           av->correspondence[j - 1].fromCoord ) +
               av->correspondence[j - 1].toCoord;
             break;
           }
@@ -1141,7 +1122,7 @@
     {
       FT_TRACE2(( "tt_face_vary_cvt: no blend specified\n" ));
 
-      error = TT_Err_Ok;
+      error = FT_Err_Ok;
       goto Exit;
     }
 
@@ -1149,7 +1130,7 @@
     {
       FT_TRACE2(( "tt_face_vary_cvt: no `cvt ' table\n" ));
 
-      error = TT_Err_Ok;
+      error = FT_Err_Ok;
       goto Exit;
     }
 
@@ -1158,13 +1139,13 @@
     {
       FT_TRACE2(( "is missing\n" ));
 
-      error = TT_Err_Ok;
+      error = FT_Err_Ok;
       goto Exit;
     }
 
     if ( FT_FRAME_ENTER( table_len ) )
     {
-      error = TT_Err_Ok;
+      error = FT_Err_Ok;
       goto Exit;
     }
 
@@ -1173,7 +1154,7 @@
     {
       FT_TRACE2(( "bad table version\n" ));
 
-      error = TT_Err_Ok;
+      error = FT_Err_Ok;
       goto FExit;
     }
 
@@ -1344,7 +1325,7 @@
 
 
     if ( !face->doblend || blend == NULL )
-      return TT_Err_Invalid_Argument;
+      return FT_THROW( Invalid_Argument );
 
     /* to be freed by the caller */
     if ( FT_NEW_ARRAY( delta_xy, n_points ) )
@@ -1354,7 +1335,7 @@
     if ( glyph_index >= blend->gv_glyphcnt      ||
          blend->glyphoffsets[glyph_index] ==
            blend->glyphoffsets[glyph_index + 1] )
-      return TT_Err_Ok;               /* no variation data for this glyph */
+      return FT_Err_Ok;               /* no variation data for this glyph */
 
     if ( FT_STREAM_SEEK( blend->glyphoffsets[glyph_index] )   ||
          FT_FRAME_ENTER( blend->glyphoffsets[glyph_index + 1] -
@@ -1404,7 +1385,7 @@
       }
       else if ( ( tupleIndex & GX_TI_TUPLE_INDEX_MASK ) >= blend->tuplecount )
       {
-        error = TT_Err_Invalid_Table;
+        error = FT_THROW( Invalid_Table );
         goto Fail3;
       }
       else
diff --git a/src/truetype/ttinterp.c b/src/truetype/ttinterp.c
index 3acb24a..798d4a9 100644
--- a/src/truetype/ttinterp.c
+++ b/src/truetype/ttinterp.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    TrueType bytecode interpreter (body).                                */
 /*                                                                         */
-/*  Copyright 1996-2012                                                    */
+/*  Copyright 1996-2013                                                    */
 /*  by David Turner, Robert Wilhelm, and Werner Lemberg.                   */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -25,20 +25,16 @@
 #include FT_INTERNAL_CALC_H
 #include FT_TRIGONOMETRY_H
 #include FT_SYSTEM_H
+#include FT_TRUETYPE_DRIVER_H
 
 #include "ttinterp.h"
-
 #include "tterrors.h"
+#include "ttsubpix.h"
 
 
 #ifdef TT_USE_BYTECODE_INTERPRETER
 
 
-#define TT_MULFIX           FT_MulFix
-#define TT_MULDIV           FT_MulDiv
-#define TT_MULDIV_NO_ROUND  FT_MulDiv_No_Round
-
-
   /*************************************************************************/
   /*                                                                       */
   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
@@ -52,7 +48,7 @@
   /*                                                                       */
   /* In order to detect infinite loops in the code, we set up a counter    */
   /* within the run loop.  A single stroke of interpretation is now        */
-  /* limited to a maximal number of opcodes defined below.                 */
+  /* limited to a maximum number of opcodes defined below.                 */
   /*                                                                       */
 #define MAX_RUNNABLE_OPCODES  1000000L
 
@@ -136,6 +132,11 @@
 #define FT_UNUSED_ARG  FT_UNUSED_EXEC; FT_UNUSED( args )
 
 
+#define SUBPIXEL_HINTING                                                    \
+          ( ((TT_Driver)FT_FACE_DRIVER( CUR.face ))->interpreter_version == \
+            TT_INTERPRETER_VERSION_38 )
+
+
   /*************************************************************************/
   /*                                                                       */
   /* The following macros hide the use of EXEC_ARG and EXEC_ARG_ to        */
@@ -232,6 +233,14 @@
 #define BOUNDS( x, n )   ( (FT_UInt)(x)  >= (FT_UInt)(n)  )
 #define BOUNDSL( x, n )  ( (FT_ULong)(x) >= (FT_ULong)(n) )
 
+  /*************************************************************************/
+  /*                                                                       */
+  /* This macro computes (a*2^14)/b and complements TT_MulFix14.           */
+  /*                                                                       */
+#define TT_DivFix14( a, b ) \
+          FT_DivFix( a, (b) << 2 )
+
+
 #undef  SUCCESS
 #define SUCCESS  0
 
@@ -301,7 +310,7 @@
     exec->IP       = IP;
     exec->curRange = range;
 
-    return TT_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
@@ -337,7 +346,7 @@
     exec->codeRangeTable[range - 1].base = (FT_Byte*)base;
     exec->codeRangeTable[range - 1].size = length;
 
-    return TT_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
@@ -370,7 +379,7 @@
     exec->codeRangeTable[range - 1].base = NULL;
     exec->codeRangeTable[range - 1].size = 0;
 
-    return TT_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
@@ -428,7 +437,7 @@
 
     FT_FREE( exec );
 
-    return TT_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
@@ -478,7 +487,7 @@
     exec->face = NULL;
     exec->size = NULL;
 
-    return TT_Err_Ok;
+    return FT_Err_Ok;
 
   Fail_Memory:
     FT_ERROR(( "Init_Context: not enough memory for %p\n", exec ));
@@ -530,7 +539,7 @@
       *size = new_max;
     }
 
-    return TT_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
@@ -637,7 +646,7 @@
 
     exec->instruction_trap = FALSE;
 
-    return TT_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
@@ -680,7 +689,7 @@
     for ( i = 0; i < TT_MAX_CODE_RANGES; i++ )
       size->codeRangeTable[i] = exec->codeRangeTable[i];
 
-    return TT_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
@@ -716,7 +725,7 @@
 
 
     if ( ( error = TT_Goto_CodeRange( exec, tt_coderange_glyph, 0 ) )
-           != TT_Err_Ok )
+           != FT_Err_Ok )
       return error;
 
     exec->zp0 = exec->pts;
@@ -753,7 +762,7 @@
     if ( !debug )
       return TT_RunIns( exec );
     else
-      return TT_Err_Ok;
+      return FT_Err_Ok;
 #endif
   }
 
@@ -1463,7 +1472,7 @@
 
 #else
 
-  /* compute (a*b)/2^14 with maximal accuracy and rounding */
+  /* compute (a*b)/2^14 with maximum accuracy and rounding */
   static FT_Int32
   TT_MulFix14( FT_Int32  a,
                FT_Int    b )
@@ -1476,7 +1485,7 @@
     l  = (FT_UInt32)( ( a & 0xFFFFU ) * b );
     m  = ( a >> 16 ) * b;
 
-    lo = l + (FT_UInt32)( m << 16 );
+    lo = l + ( (FT_UInt32)m << 16 );
     hi = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo < l );
 
     /* divide the result by 2^14 with rounding */
@@ -1488,12 +1497,12 @@
     l   = lo + 0x2000U;
     hi += l < lo;
 
-    return ( hi << 18 ) | ( l >> 14 );
+    return (FT_Int32)( ( (FT_UInt32)hi << 18 ) | ( l >> 14 ) );
   }
 #endif
 
 
-  /* compute (ax*bx+ay*by)/2^14 with maximal accuracy and rounding */
+  /* compute (ax*bx+ay*by)/2^14 with maximum accuracy and rounding */
   static FT_Int32
   TT_DotFix14( FT_Int32  ax,
                FT_Int32  ay,
@@ -1508,14 +1517,14 @@
     l = (FT_UInt32)( ( ax & 0xFFFFU ) * bx );
     m = ( ax >> 16 ) * bx;
 
-    lo1 = l + (FT_UInt32)( m << 16 );
+    lo1 = l + ( (FT_UInt32)m << 16 );
     hi1 = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo1 < l );
 
     /* compute ay*by as 64-bit value */
     l = (FT_UInt32)( ( ay & 0xFFFFU ) * by );
     m = ( ay >> 16 ) * by;
 
-    lo2 = l + (FT_UInt32)( m << 16 );
+    lo2 = l + ( (FT_UInt32)m << 16 );
     hi2 = ( m >> 16 ) + ( (FT_Int32)l >> 31 ) + ( lo2 < l );
 
     /* add them */
@@ -1531,100 +1540,10 @@
     l   = lo + 0x2000U;
     hi += ( l < lo );
 
-    return ( hi << 18 ) | ( l >> 14 );
+    return (FT_Int32)( ( (FT_UInt32)hi << 18 ) | ( l >> 14 ) );
   }
 
 
-  /* return length of given vector */
-
-#if 0
-
-  static FT_Int32
-  TT_VecLen( FT_Int32  x,
-             FT_Int32  y )
-  {
-    FT_Int32   m, hi1, hi2, hi;
-    FT_UInt32  l, lo1, lo2, lo;
-
-
-    /* compute x*x as 64-bit value */
-    lo = (FT_UInt32)( x & 0xFFFFU );
-    hi = x >> 16;
-
-    l  = lo * lo;
-    m  = hi * lo;
-    hi = hi * hi;
-
-    lo1 = l + (FT_UInt32)( m << 17 );
-    hi1 = hi + ( m >> 15 ) + ( lo1 < l );
-
-    /* compute y*y as 64-bit value */
-    lo = (FT_UInt32)( y & 0xFFFFU );
-    hi = y >> 16;
-
-    l  = lo * lo;
-    m  = hi * lo;
-    hi = hi * hi;
-
-    lo2 = l + (FT_UInt32)( m << 17 );
-    hi2 = hi + ( m >> 15 ) + ( lo2 < l );
-
-    /* add them to get 'x*x+y*y' as 64-bit value */
-    lo = lo1 + lo2;
-    hi = hi1 + hi2 + ( lo < lo1 );
-
-    /* compute the square root of this value */
-    {
-      FT_UInt32  root, rem, test_div;
-      FT_Int     count;
-
-
-      root = 0;
-
-      {
-        rem   = 0;
-        count = 32;
-        do
-        {
-          rem      = ( rem << 2 ) | ( (FT_UInt32)hi >> 30 );
-          hi       = (  hi << 2 ) | (            lo >> 30 );
-          lo     <<= 2;
-          root   <<= 1;
-          test_div = ( root << 1 ) + 1;
-
-          if ( rem >= test_div )
-          {
-            rem  -= test_div;
-            root += 1;
-          }
-        } while ( --count );
-      }
-
-      return (FT_Int32)root;
-    }
-  }
-
-#else
-
-  /* this version uses FT_Vector_Length which computes the same value */
-  /* much, much faster..                                              */
-  /*                                                                  */
-  static FT_F26Dot6
-  TT_VecLen( FT_F26Dot6  X,
-             FT_F26Dot6  Y )
-  {
-    FT_Vector  v;
-
-
-    v.x = X;
-    v.y = Y;
-
-    return FT_Vector_Length( &v );
-  }
-
-#endif
-
-
   /*************************************************************************/
   /*                                                                       */
   /* <Function>                                                            */
@@ -1661,14 +1580,14 @@
 
         else
         {
-          FT_Long  x, y;
+          FT_F26Dot6  x, y;
 
 
-          x = TT_MULDIV( CUR.GS.projVector.x,
-                         CUR.tt_metrics.x_ratio, 0x4000 );
-          y = TT_MULDIV( CUR.GS.projVector.y,
-                         CUR.tt_metrics.y_ratio, 0x4000 );
-          CUR.tt_metrics.ratio = TT_VecLen( x, y );
+          x = TT_MulFix14( CUR.tt_metrics.x_ratio,
+                           CUR.GS.projVector.x );
+          y = TT_MulFix14( CUR.tt_metrics.y_ratio,
+                           CUR.GS.projVector.y );
+          CUR.tt_metrics.ratio = FT_Hypot( x, y );
         }
       }
     }
@@ -1679,7 +1598,7 @@
   static FT_Long
   Current_Ppem( EXEC_OP )
   {
-    return TT_MULFIX( CUR.tt_metrics.ppem, CURRENT_Ratio() );
+    return FT_MulFix( CUR.tt_metrics.ppem, CURRENT_Ratio() );
   }
 
 
@@ -1700,7 +1619,7 @@
   FT_CALLBACK_DEF( FT_F26Dot6 )
   Read_CVT_Stretched( EXEC_OP_ FT_ULong  idx )
   {
-    return TT_MULFIX( CUR.cvt[idx], CURRENT_Ratio() );
+    return FT_MulFix( CUR.cvt[idx], CURRENT_Ratio() );
   }
 
 
@@ -1786,7 +1705,7 @@
 
     if ( aRange < 1 || aRange > 3 )
     {
-      CUR.error = TT_Err_Bad_Argument;
+      CUR.error = FT_THROW( Bad_Argument );
       return FAILURE;
     }
 
@@ -1794,7 +1713,7 @@
 
     if ( range->base == NULL )     /* invalid coderange */
     {
-      CUR.error = TT_Err_Invalid_CodeRange;
+      CUR.error = FT_THROW( Invalid_CodeRange );
       return FAILURE;
     }
 
@@ -1804,7 +1723,7 @@
 
     if ( aIP > range->size )
     {
-      CUR.error = TT_Err_Code_Overflow;
+      CUR.error = FT_THROW( Code_Overflow );
       return FAILURE;
     }
 
@@ -1850,9 +1769,12 @@
 
     if ( v != 0 )
     {
-      zone->cur[point].x += TT_MULDIV( distance,
-                                       v * 0x10000L,
-                                       CUR.F_dot_P );
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+      if ( !SUBPIXEL_HINTING                                     ||
+           ( !CUR.ignore_x_mode                                ||
+             ( CUR.sph_tweak_flags & SPH_TWEAK_ALLOW_X_DMOVE ) ) )
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+        zone->cur[point].x += FT_MulDiv( distance, v, CUR.F_dot_P );
 
       zone->tags[point] |= FT_CURVE_TAG_TOUCH_X;
     }
@@ -1861,9 +1783,7 @@
 
     if ( v != 0 )
     {
-      zone->cur[point].y += TT_MULDIV( distance,
-                                       v * 0x10000L,
-                                       CUR.F_dot_P );
+      zone->cur[point].y += FT_MulDiv( distance, v, CUR.F_dot_P );
 
       zone->tags[point] |= FT_CURVE_TAG_TOUCH_Y;
     }
@@ -1902,16 +1822,12 @@
     v = CUR.GS.freeVector.x;
 
     if ( v != 0 )
-      zone->org[point].x += TT_MULDIV( distance,
-                                       v * 0x10000L,
-                                       CUR.F_dot_P );
+      zone->org[point].x += FT_MulDiv( distance, v, CUR.F_dot_P );
 
     v = CUR.GS.freeVector.y;
 
     if ( v != 0 )
-      zone->org[point].y += TT_MULDIV( distance,
-                                       v * 0x10000L,
-                                       CUR.F_dot_P );
+      zone->org[point].y += FT_MulDiv( distance, v, CUR.F_dot_P );
   }
 
 
@@ -1932,7 +1848,12 @@
   {
     FT_UNUSED_EXEC;
 
-    zone->cur[point].x += distance;
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+    if ( !SUBPIXEL_HINTING  ||
+         !CUR.ignore_x_mode )
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+      zone->cur[point].x += distance;
+
     zone->tags[point]  |= FT_CURVE_TAG_TOUCH_X;
   }
 
@@ -2193,7 +2114,7 @@
     }
     else
     {
-      val = - FT_PIX_CEIL( compensation - distance );
+      val = -FT_PIX_CEIL( compensation - distance );
       if ( val > 0 )
         val = 0;
     }
@@ -2404,8 +2325,9 @@
   /*    Sets Super Round parameters.                                       */
   /*                                                                       */
   /* <Input>                                                               */
-  /*    GridPeriod :: Grid period                                          */
-  /*    selector   :: SROUND opcode                                        */
+  /*    GridPeriod :: The grid period.                                     */
+  /*                                                                       */
+  /*    selector   :: The SROUND opcode.                                   */
   /*                                                                       */
   static void
   SetSuperRound( EXEC_OP_ FT_F26Dot6  GridPeriod,
@@ -2617,13 +2539,10 @@
 
       if ( CUR.GS.dualVector.x == 0x4000 )
         CUR.func_dualproj = Project_x;
+      else if ( CUR.GS.dualVector.y == 0x4000 )
+        CUR.func_dualproj = Project_y;
       else
-      {
-        if ( CUR.GS.dualVector.y == 0x4000 )
-          CUR.func_dualproj = Project_y;
-        else
-          CUR.func_dualproj = Dual_Project;
-      }
+        CUR.func_dualproj = Dual_Project;
 
       /* Force recalculation of cached aspect ratio */
       CUR.tt_metrics.ratio = 0;
@@ -2633,61 +2552,50 @@
 #endif /* TT_CONFIG_OPTION_UNPATENTED_HINTING */
 
     if ( CUR.GS.freeVector.x == 0x4000 )
-      CUR.F_dot_P       = CUR.GS.projVector.x * 0x10000L;
+      CUR.F_dot_P = CUR.GS.projVector.x;
+    else if ( CUR.GS.freeVector.y == 0x4000 )
+      CUR.F_dot_P = CUR.GS.projVector.y;
     else
-    {
-      if ( CUR.GS.freeVector.y == 0x4000 )
-        CUR.F_dot_P       = CUR.GS.projVector.y * 0x10000L;
-      else
-        CUR.F_dot_P = (FT_Long)CUR.GS.projVector.x * CUR.GS.freeVector.x * 4 +
-                      (FT_Long)CUR.GS.projVector.y * CUR.GS.freeVector.y * 4;
-    }
+      CUR.F_dot_P = ( (FT_Long)CUR.GS.projVector.x * CUR.GS.freeVector.x +
+                      (FT_Long)CUR.GS.projVector.y * CUR.GS.freeVector.y ) >>
+                    14;
 
     if ( CUR.GS.projVector.x == 0x4000 )
       CUR.func_project = (TT_Project_Func)Project_x;
+    else if ( CUR.GS.projVector.y == 0x4000 )
+      CUR.func_project = (TT_Project_Func)Project_y;
     else
-    {
-      if ( CUR.GS.projVector.y == 0x4000 )
-        CUR.func_project = (TT_Project_Func)Project_y;
-      else
-        CUR.func_project = (TT_Project_Func)Project;
-    }
+      CUR.func_project = (TT_Project_Func)Project;
 
     if ( CUR.GS.dualVector.x == 0x4000 )
       CUR.func_dualproj = (TT_Project_Func)Project_x;
+    else if ( CUR.GS.dualVector.y == 0x4000 )
+      CUR.func_dualproj = (TT_Project_Func)Project_y;
     else
-    {
-      if ( CUR.GS.dualVector.y == 0x4000 )
-        CUR.func_dualproj = (TT_Project_Func)Project_y;
-      else
-        CUR.func_dualproj = (TT_Project_Func)Dual_Project;
-    }
+      CUR.func_dualproj = (TT_Project_Func)Dual_Project;
 
     CUR.func_move      = (TT_Move_Func)Direct_Move;
     CUR.func_move_orig = (TT_Move_Func)Direct_Move_Orig;
 
-    if ( CUR.F_dot_P == 0x40000000L )
+    if ( CUR.F_dot_P == 0x4000L )
     {
       if ( CUR.GS.freeVector.x == 0x4000 )
       {
         CUR.func_move      = (TT_Move_Func)Direct_Move_X;
         CUR.func_move_orig = (TT_Move_Func)Direct_Move_Orig_X;
       }
-      else
+      else if ( CUR.GS.freeVector.y == 0x4000 )
       {
-        if ( CUR.GS.freeVector.y == 0x4000 )
-        {
-          CUR.func_move      = (TT_Move_Func)Direct_Move_Y;
-          CUR.func_move_orig = (TT_Move_Func)Direct_Move_Orig_Y;
-        }
+        CUR.func_move      = (TT_Move_Func)Direct_Move_Y;
+        CUR.func_move_orig = (TT_Move_Func)Direct_Move_Orig_Y;
       }
     }
 
     /* at small sizes, F_dot_P can become too small, resulting   */
     /* in overflows and `spikes' in a number of glyphs like `w'. */
 
-    if ( FT_ABS( CUR.F_dot_P ) < 0x4000000L )
-      CUR.F_dot_P = 0x40000000L;
+    if ( FT_ABS( CUR.F_dot_P ) < 0x400L )
+      CUR.F_dot_P = 0x4000L;
 
     /* Disable cached aspect ratio */
     CUR.tt_metrics.ratio = 0;
@@ -2716,98 +2624,33 @@
   /*    In case Vx and Vy are both zero, Normalize() returns SUCCESS, and  */
   /*    R is undefined.                                                    */
   /*                                                                       */
-
-
   static FT_Bool
   Normalize( EXEC_OP_ FT_F26Dot6      Vx,
                       FT_F26Dot6      Vy,
                       FT_UnitVector*  R )
   {
     FT_F26Dot6  W;
-    FT_Bool     S1, S2;
 
     FT_UNUSED_EXEC;
 
 
-    if ( FT_ABS( Vx ) < 0x10000L && FT_ABS( Vy ) < 0x10000L )
+    if ( FT_ABS( Vx ) < 0x4000L && FT_ABS( Vy ) < 0x4000L )
     {
-      Vx *= 0x100;
-      Vy *= 0x100;
-
-      W = TT_VecLen( Vx, Vy );
-
-      if ( W == 0 )
+      if ( Vx == 0 && Vy == 0 )
       {
         /* XXX: UNDOCUMENTED! It seems that it is possible to try   */
         /*      to normalize the vector (0,0).  Return immediately. */
         return SUCCESS;
       }
 
-      R->x = (FT_F2Dot14)FT_MulDiv( Vx, 0x4000L, W );
-      R->y = (FT_F2Dot14)FT_MulDiv( Vy, 0x4000L, W );
-
-      return SUCCESS;
+      Vx *= 0x4000;
+      Vy *= 0x4000;
     }
 
-    W = TT_VecLen( Vx, Vy );
+    W = FT_Hypot( Vx, Vy );
 
-    Vx = FT_MulDiv( Vx, 0x4000L, W );
-    Vy = FT_MulDiv( Vy, 0x4000L, W );
-
-    W = Vx * Vx + Vy * Vy;
-
-    /* Now, we want that Sqrt( W ) = 0x4000 */
-    /* Or 0x10000000 <= W < 0x10004000      */
-
-    if ( Vx < 0 )
-    {
-      Vx = -Vx;
-      S1 = TRUE;
-    }
-    else
-      S1 = FALSE;
-
-    if ( Vy < 0 )
-    {
-      Vy = -Vy;
-      S2 = TRUE;
-    }
-    else
-      S2 = FALSE;
-
-    while ( W < 0x10000000L )
-    {
-      /* We need to increase W by a minimal amount */
-      if ( Vx < Vy )
-        Vx++;
-      else
-        Vy++;
-
-      W = Vx * Vx + Vy * Vy;
-    }
-
-    while ( W >= 0x10004000L )
-    {
-      /* We need to decrease W by a minimal amount */
-      if ( Vx < Vy )
-        Vx--;
-      else
-        Vy--;
-
-      W = Vx * Vx + Vy * Vy;
-    }
-
-    /* Note that in various cases, we can only  */
-    /* compute a Sqrt(W) of 0x3FFF, eg. Vx = Vy */
-
-    if ( S1 )
-      Vx = -Vx;
-
-    if ( S2 )
-      Vy = -Vy;
-
-    R->x = (FT_F2Dot14)Vx;   /* Type conversion */
-    R->y = (FT_F2Dot14)Vy;   /* Type conversion */
+    R->x = (FT_F2Dot14)TT_DivFix14( Vx, W );
+    R->y = (FT_F2Dot14)TT_DivFix14( Vy, W );
 
     return SUCCESS;
   }
@@ -2835,7 +2678,7 @@
          BOUNDS( aIdx2, CUR.zp1.n_points ) )
     {
       if ( CUR.pedantic_hinting )
-        CUR.error = TT_Err_Invalid_Reference;
+        CUR.error = FT_THROW( Invalid_Reference );
       return FAILURE;
     }
 
@@ -3091,10 +2934,10 @@
     CUR.func_round = (TT_Round_Func)Round_Super_45;
 
 
-#define DO_SLOOP                       \
-    if ( args[0] < 0 )                 \
-      CUR.error = TT_Err_Bad_Argument; \
-    else                               \
+#define DO_SLOOP                            \
+    if ( args[0] < 0 )                      \
+      CUR.error = FT_THROW( Bad_Argument ); \
+    else                                    \
       CUR.GS.loop = args[0];
 
 
@@ -3110,14 +2953,9 @@
     CUR.GS.single_width_cutin = (FT_F26Dot6)args[0];
 
 
-    /* XXX: UNDOCUMENTED! or bug in the Windows engine?   */
-    /*                                                    */
-    /*      It seems that the value that is read here is  */
-    /*      expressed in 16.16 format rather than in font */
-    /*      units.                                        */
-    /*                                                    */
-#define DO_SSW                                                 \
-    CUR.GS.single_width_value = (FT_F26Dot6)( args[0] >> 10 );
+#define DO_SSW                                                     \
+    CUR.GS.single_width_value = FT_MulFix( args[0],                \
+                                           CUR.tt_metrics.scale );
 
 
 #define DO_FLIPON            \
@@ -3181,21 +3019,21 @@
     args[0] = CUR.top;
 
 
-#define DO_CINDEX                             \
-  {                                           \
-    FT_Long  L;                               \
-                                              \
-                                              \
-    L = args[0];                              \
-                                              \
-    if ( L <= 0 || L > CUR.args )             \
-    {                                         \
-      if ( CUR.pedantic_hinting )             \
-        CUR.error = TT_Err_Invalid_Reference; \
-      args[0] = 0;                            \
-    }                                         \
-    else                                      \
-      args[0] = CUR.stack[CUR.args - L];      \
+#define DO_CINDEX                                  \
+  {                                                \
+    FT_Long  L;                                    \
+                                                   \
+                                                   \
+    L = args[0];                                   \
+                                                   \
+    if ( L <= 0 || L > CUR.args )                  \
+    {                                              \
+      if ( CUR.pedantic_hinting )                  \
+        CUR.error = FT_THROW( Invalid_Reference ); \
+      args[0] = 0;                                 \
+    }                                              \
+    else                                           \
+      args[0] = CUR.stack[CUR.args - L];           \
   }
 
 
@@ -3203,24 +3041,24 @@
     if ( args[1] != 0 )                                           \
     {                                                             \
       if ( args[0] == 0 && CUR.args == 0 )                        \
-        CUR.error = TT_Err_Bad_Argument;                          \
+        CUR.error = FT_THROW( Bad_Argument );                     \
       CUR.IP += args[0];                                          \
       if ( CUR.IP < 0                                          || \
            ( CUR.callTop > 0                                 &&   \
              CUR.IP > CUR.callStack[CUR.callTop - 1].Cur_End ) )  \
-        CUR.error = TT_Err_Bad_Argument;                          \
+        CUR.error = FT_THROW( Bad_Argument );                     \
       CUR.step_ins = FALSE;                                       \
     }
 
 
 #define DO_JMPR                                                 \
     if ( args[0] == 0 && CUR.args == 0 )                        \
-      CUR.error = TT_Err_Bad_Argument;                          \
+      CUR.error = FT_THROW( Bad_Argument );                     \
     CUR.IP += args[0];                                          \
     if ( CUR.IP < 0                                          || \
          ( CUR.callTop > 0                                 &&   \
            CUR.IP > CUR.callStack[CUR.callTop - 1].Cur_End ) )  \
-      CUR.error = TT_Err_Bad_Argument;                          \
+      CUR.error = FT_THROW( Bad_Argument );                     \
     CUR.step_ins = FALSE;
 
 
@@ -3228,12 +3066,12 @@
     if ( args[1] == 0 )                                           \
     {                                                             \
       if ( args[0] == 0 && CUR.args == 0 )                        \
-        CUR.error = TT_Err_Bad_Argument;                          \
+        CUR.error = FT_THROW( Bad_Argument );                     \
       CUR.IP += args[0];                                          \
       if ( CUR.IP < 0                                          || \
            ( CUR.callTop > 0                                 &&   \
              CUR.IP > CUR.callStack[CUR.callTop - 1].Cur_End ) )  \
-        CUR.error = TT_Err_Bad_Argument;                          \
+        CUR.error = FT_THROW( Bad_Argument );                     \
       CUR.step_ins = FALSE;                                       \
     }
 
@@ -3292,13 +3130,13 @@
 
 #define DO_DIV                                               \
     if ( args[1] == 0 )                                      \
-      CUR.error = TT_Err_Divide_By_Zero;                     \
+      CUR.error = FT_THROW( Divide_By_Zero );                \
     else                                                     \
-      args[0] = TT_MULDIV_NO_ROUND( args[0], 64L, args[1] );
+      args[0] = FT_MulDiv_No_Round( args[0], 64L, args[1] );
 
 
 #define DO_MUL                                    \
-    args[0] = TT_MULDIV( args[0], args[1], 64L );
+    args[0] = FT_MulDiv( args[0], args[1], 64L );
 
 
 #define DO_ABS                   \
@@ -3316,6 +3154,45 @@
 #define DO_CEILING                    \
     args[0] = FT_PIX_CEIL( args[0] );
 
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+
+#define DO_RS                                             \
+   {                                                      \
+     FT_ULong  I = (FT_ULong)args[0];                     \
+                                                          \
+                                                          \
+     if ( BOUNDSL( I, CUR.storeSize ) )                   \
+     {                                                    \
+       if ( CUR.pedantic_hinting )                        \
+         ARRAY_BOUND_ERROR;                               \
+       else                                               \
+         args[0] = 0;                                     \
+     }                                                    \
+     else                                                 \
+     {                                                    \
+       /* subpixel hinting - avoid Typeman Dstroke and */ \
+       /* IStroke and Vacuform rounds                  */ \
+                                                          \
+       if ( SUBPIXEL_HINTING                           && \
+            CUR.ignore_x_mode                          && \
+            ( ( I == 24                            &&     \
+                ( CUR.face->sph_found_func_flags &        \
+                  ( SPH_FDEF_SPACING_1 |                  \
+                    SPH_FDEF_SPACING_2 )         ) ) ||   \
+              ( I == 22                      &&           \
+                ( CUR.sph_in_func_flags    &              \
+                  SPH_FDEF_TYPEMAN_STROKES ) )       ||   \
+              ( I == 8                             &&     \
+                ( CUR.face->sph_found_func_flags &        \
+                  SPH_FDEF_VACUFORM_ROUND_1      ) &&     \
+                  CUR.iup_called                   ) ) )  \
+         args[0] = 0;                                     \
+       else                                               \
+         args[0] = CUR.storage[I];                        \
+     }                                                    \
+   }
+
+#else /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
 
 #define DO_RS                           \
    {                                    \
@@ -3335,6 +3212,8 @@
        args[0] = CUR.storage[I];        \
    }
 
+#endif /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
 
 #define DO_WS                           \
    {                                    \
@@ -3402,12 +3281,12 @@
        }                                                        \
      }                                                          \
      else                                                       \
-       CUR.cvt[I] = TT_MULFIX( args[1], CUR.tt_metrics.scale ); \
+       CUR.cvt[I] = FT_MulFix( args[1], CUR.tt_metrics.scale ); \
    }
 
 
-#define DO_DEBUG                     \
-    CUR.error = TT_Err_Debug_OpCode;
+#define DO_DEBUG                          \
+    CUR.error = FT_THROW( Debug_OpCode );
 
 
 #define DO_ROUND                                                   \
@@ -3435,10 +3314,10 @@
 
 
 #undef  ARRAY_BOUND_ERROR
-#define ARRAY_BOUND_ERROR                   \
-    {                                       \
-      CUR.error = TT_Err_Invalid_Reference; \
-      return;                               \
+#define ARRAY_BOUND_ERROR                        \
+    {                                            \
+      CUR.error = FT_THROW( Invalid_Reference ); \
+      return;                                    \
     }
 
 
@@ -4417,7 +4296,7 @@
     if ( L <= 0 || L > CUR.args )
     {
       if ( CUR.pedantic_hinting )
-        CUR.error = TT_Err_Invalid_Reference;
+        CUR.error = FT_THROW( Invalid_Reference );
     }
     else
     {
@@ -4487,7 +4366,7 @@
     }
 
   Fail_Overflow:
-    CUR.error = TT_Err_Code_Overflow;
+    CUR.error = FT_THROW( Code_Overflow );
     return FAILURE;
   }
 
@@ -4592,6 +4471,106 @@
     TT_DefRecord*  rec;
     TT_DefRecord*  limit;
 
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+    /* arguments to opcodes are skipped by `SKIP_Code' */
+    FT_Byte    opcode_pattern[9][12] = {
+                 /* #0 inline delta function 1 */
+                 {
+                   0x4B, /* PPEM    */
+                   0x53, /* GTEQ    */
+                   0x23, /* SWAP    */
+                   0x4B, /* PPEM    */
+                   0x51, /* LTEQ    */
+                   0x5A, /* AND     */
+                   0x58, /* IF      */
+                   0x38, /*   SHPIX */
+                   0x1B, /* ELSE    */
+                   0x21, /*   POP   */
+                   0x21, /*   POP   */
+                   0x59  /* EIF     */
+                 },
+                 /* #1 inline delta function 2 */
+                 {
+                   0x4B, /* PPEM    */
+                   0x54, /* EQ      */
+                   0x58, /* IF      */
+                   0x38, /*   SHPIX */
+                   0x1B, /* ELSE    */
+                   0x21, /*   POP   */
+                   0x21, /*   POP   */
+                   0x59  /* EIF     */
+                 },
+                 /* #2 diagonal stroke function */
+                 {
+                   0x20, /* DUP     */
+                   0x20, /* DUP     */
+                   0xB0, /* PUSHB_1 */
+                         /*   1     */
+                   0x60, /* ADD     */
+                   0x46, /* GC_cur  */
+                   0xB0, /* PUSHB_1 */
+                         /*   64    */
+                   0x23, /* SWAP    */
+                   0x42  /* WS      */
+                 },
+                 /* #3 VacuFormRound function */
+                 {
+                   0x45, /* RCVT    */
+                   0x23, /* SWAP    */
+                   0x46, /* GC_cur  */
+                   0x60, /* ADD     */
+                   0x20, /* DUP     */
+                   0xB0  /* PUSHB_1 */
+                         /*   38    */
+                 },
+                 /* #4 TTFautohint bytecode (old) */
+                 {
+                   0x20, /* DUP     */
+                   0x64, /* ABS     */
+                   0xB0, /* PUSHB_1 */
+                         /*   32    */
+                   0x60, /* ADD     */
+                   0x66, /* FLOOR   */
+                   0x23, /* SWAP    */
+                   0xB0  /* PUSHB_1 */
+                 },
+                 /* #5 spacing function 1 */
+                 {
+                   0x01, /* SVTCA_x */
+                   0xB0, /* PUSHB_1 */
+                         /*   24    */
+                   0x43, /* RS      */
+                   0x58  /* IF      */
+                 },
+                 /* #6 spacing function 2 */
+                 {
+                   0x01, /* SVTCA_x */
+                   0x18, /* RTG     */
+                   0xB0, /* PUSHB_1 */
+                         /*   24    */
+                   0x43, /* RS      */
+                   0x58  /* IF      */
+                 },
+                 /* #7 TypeMan Talk DiagEndCtrl function */
+                 {
+                   0x01, /* SVTCA_x */
+                   0x20, /* DUP     */
+                   0xB0, /* PUSHB_1 */
+                         /*   3     */
+                   0x25, /* CINDEX  */
+                 },
+                 /* #8 TypeMan Talk Align */
+                 {
+                   0x06, /* SPVTL   */
+                   0x7D, /* RDTG    */
+                 },
+               };
+    FT_UShort  opcode_patterns   = 9;
+    FT_UShort  opcode_pointer[9] = {  0, 0, 0, 0, 0, 0, 0, 0, 0 };
+    FT_UShort  opcode_size[9]    = { 12, 8, 8, 6, 7, 4, 5, 4, 2 };
+    FT_UShort  i;
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
 
     /* some font programs are broken enough to redefine functions! */
     /* We will then parse the current table.                       */
@@ -4611,7 +4590,7 @@
       /* check that there is enough room for new functions */
       if ( CUR.numFDefs >= CUR.maxFDefs )
       {
-        CUR.error = TT_Err_Too_Many_Function_Defs;
+        CUR.error = FT_THROW( Too_Many_Function_Defs );
         return;
       }
       CUR.numFDefs++;
@@ -4621,28 +4600,149 @@
     /* func # must be within unsigned 16-bit integer */
     if ( n > 0xFFFFU )
     {
-      CUR.error = TT_Err_Too_Many_Function_Defs;
+      CUR.error = FT_THROW( Too_Many_Function_Defs );
       return;
     }
 
-    rec->range  = CUR.curRange;
-    rec->opc    = (FT_UInt16)n;
-    rec->start  = CUR.IP + 1;
-    rec->active = TRUE;
+    rec->range          = CUR.curRange;
+    rec->opc            = (FT_UInt16)n;
+    rec->start          = CUR.IP + 1;
+    rec->active         = TRUE;
+    rec->inline_delta   = FALSE;
+    rec->sph_fdef_flags = 0x0000;
 
     if ( n > CUR.maxFunc )
       CUR.maxFunc = (FT_UInt16)n;
 
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+    /* We don't know for sure these are typeman functions, */
+    /* however they are only active when RS 22 is called   */
+    if ( n >= 64 && n <= 66 )
+      rec->sph_fdef_flags |= SPH_FDEF_TYPEMAN_STROKES;
+#endif
+
     /* Now skip the whole function definition. */
     /* We don't allow nested IDEFS & FDEFs.    */
 
     while ( SKIP_Code() == SUCCESS )
     {
+
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+
+      if ( SUBPIXEL_HINTING )
+      {
+        for ( i = 0; i < opcode_patterns; i++ )
+        {
+          if ( opcode_pointer[i] < opcode_size[i]                 &&
+               CUR.opcode == opcode_pattern[i][opcode_pointer[i]] )
+          {
+            opcode_pointer[i] += 1;
+
+            if ( opcode_pointer[i] == opcode_size[i] )
+            {
+              FT_TRACE7(( "sph: Function %d, opcode ptrn: %d, %s %s\n",
+                          i, n,
+                          CUR.face->root.family_name,
+                          CUR.face->root.style_name ));
+
+              switch ( i )
+              {
+              case 0:
+                rec->sph_fdef_flags            |= SPH_FDEF_INLINE_DELTA_1;
+                CUR.face->sph_found_func_flags |= SPH_FDEF_INLINE_DELTA_1;
+                break;
+
+              case 1:
+                rec->sph_fdef_flags            |= SPH_FDEF_INLINE_DELTA_2;
+                CUR.face->sph_found_func_flags |= SPH_FDEF_INLINE_DELTA_2;
+                break;
+
+              case 2:
+                switch ( n )
+                {
+                  /* needs to be implemented still */
+                case 58:
+                  rec->sph_fdef_flags            |= SPH_FDEF_DIAGONAL_STROKE;
+                  CUR.face->sph_found_func_flags |= SPH_FDEF_DIAGONAL_STROKE;
+                }
+                break;
+
+              case 3:
+                switch ( n )
+                {
+                case 0:
+                  rec->sph_fdef_flags            |= SPH_FDEF_VACUFORM_ROUND_1;
+                  CUR.face->sph_found_func_flags |= SPH_FDEF_VACUFORM_ROUND_1;
+                }
+                break;
+
+              case 4:
+                /* probably not necessary to detect anymore */
+                rec->sph_fdef_flags            |= SPH_FDEF_TTFAUTOHINT_1;
+                CUR.face->sph_found_func_flags |= SPH_FDEF_TTFAUTOHINT_1;
+                break;
+
+              case 5:
+                switch ( n )
+                {
+                case 0:
+                case 1:
+                case 2:
+                case 4:
+                case 7:
+                case 8:
+                  rec->sph_fdef_flags            |= SPH_FDEF_SPACING_1;
+                  CUR.face->sph_found_func_flags |= SPH_FDEF_SPACING_1;
+                }
+                break;
+
+              case 6:
+                switch ( n )
+                {
+                case 0:
+                case 1:
+                case 2:
+                case 4:
+                case 7:
+                case 8:
+                  rec->sph_fdef_flags            |= SPH_FDEF_SPACING_2;
+                  CUR.face->sph_found_func_flags |= SPH_FDEF_SPACING_2;
+                }
+                break;
+
+               case 7:
+                 rec->sph_fdef_flags            |= SPH_FDEF_TYPEMAN_DIAGENDCTRL;
+                 CUR.face->sph_found_func_flags |= SPH_FDEF_TYPEMAN_DIAGENDCTRL;
+                 break;
+
+               case 8:
+#if 0
+                 rec->sph_fdef_flags            |= SPH_FDEF_TYPEMAN_DIAGENDCTRL;
+                 CUR.face->sph_found_func_flags |= SPH_FDEF_TYPEMAN_DIAGENDCTRL;
+#endif
+                 break;
+              }
+              opcode_pointer[i] = 0;
+            }
+          }
+
+          else
+            opcode_pointer[i] = 0;
+        }
+
+        /* Set sph_compatibility_mode only when deltas are detected */
+        CUR.face->sph_compatibility_mode =
+          ( ( CUR.face->sph_found_func_flags & SPH_FDEF_INLINE_DELTA_1 ) |
+            ( CUR.face->sph_found_func_flags & SPH_FDEF_INLINE_DELTA_2 ) );
+      }
+
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
       switch ( CUR.opcode )
       {
       case 0x89:    /* IDEF */
       case 0x2C:    /* FDEF */
-        CUR.error = TT_Err_Nested_DEFS;
+        CUR.error = FT_THROW( Nested_DEFS );
         return;
 
       case 0x2D:   /* ENDF */
@@ -4667,9 +4767,13 @@
     FT_UNUSED_ARG;
 
 
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+    CUR.sph_in_func_flags = 0x0000;
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
     if ( CUR.callTop <= 0 )     /* We encountered an ENDF without a call */
     {
-      CUR.error = TT_Err_ENDF_In_Exec_Stream;
+      CUR.error = FT_THROW( ENDF_In_Exec_Stream );
       return;
     }
 
@@ -4751,10 +4855,21 @@
     if ( !def->active )
       goto Fail;
 
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+    if ( SUBPIXEL_HINTING                                              &&
+         CUR.ignore_x_mode                                             &&
+         ( ( CUR.iup_called                                        &&
+             ( CUR.sph_tweak_flags & SPH_TWEAK_NO_CALL_AFTER_IUP ) ) ||
+           ( def->sph_fdef_flags & SPH_FDEF_VACUFORM_ROUND_1 )       ) )
+      goto Fail;
+    else
+      CUR.sph_in_func_flags = def->sph_fdef_flags;
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
     /* check the call stack */
     if ( CUR.callTop >= CUR.callSize )
     {
-      CUR.error = TT_Err_Stack_Overflow;
+      CUR.error = FT_THROW( Stack_Overflow );
       return;
     }
 
@@ -4772,10 +4887,11 @@
                         def->start );
 
     CUR.step_ins = FALSE;
+
     return;
 
   Fail:
-    CUR.error = TT_Err_Invalid_Reference;
+    CUR.error = FT_THROW( Invalid_Reference );
   }
 
 
@@ -4828,10 +4944,19 @@
     if ( !def->active )
       goto Fail;
 
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+    if ( SUBPIXEL_HINTING                                    &&
+         CUR.ignore_x_mode                                   &&
+         ( def->sph_fdef_flags & SPH_FDEF_VACUFORM_ROUND_1 ) )
+      goto Fail;
+    else
+      CUR.sph_in_func_flags = def->sph_fdef_flags;
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
     /* check stack */
     if ( CUR.callTop >= CUR.callSize )
     {
-      CUR.error = TT_Err_Stack_Overflow;
+      CUR.error = FT_THROW( Stack_Overflow );
       return;
     }
 
@@ -4851,10 +4976,11 @@
 
       CUR.step_ins = FALSE;
     }
+
     return;
 
   Fail:
-    CUR.error = TT_Err_Invalid_Reference;
+    CUR.error = FT_THROW( Invalid_Reference );
   }
 
 
@@ -4885,7 +5011,7 @@
       /* check that there is enough room for a new instruction */
       if ( CUR.numIDefs >= CUR.maxIDefs )
       {
-        CUR.error = TT_Err_Too_Many_Instruction_Defs;
+        CUR.error = FT_THROW( Too_Many_Instruction_Defs );
         return;
       }
       CUR.numIDefs++;
@@ -4894,7 +5020,7 @@
     /* opcode must be unsigned 8-bit integer */
     if ( 0 > args[0] || args[0] > 0x00FF )
     {
-      CUR.error = TT_Err_Too_Many_Instruction_Defs;
+      CUR.error = FT_THROW( Too_Many_Instruction_Defs );
       return;
     }
 
@@ -4915,7 +5041,7 @@
       {
       case 0x89:   /* IDEF */
       case 0x2C:   /* FDEF */
-        CUR.error = TT_Err_Nested_DEFS;
+        CUR.error = FT_THROW( Nested_DEFS );
         return;
       case 0x2D:   /* ENDF */
         return;
@@ -4949,7 +5075,7 @@
 
     if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
     {
-      CUR.error = TT_Err_Stack_Overflow;
+      CUR.error = FT_THROW( Stack_Overflow );
       return;
     }
 
@@ -4976,7 +5102,7 @@
 
     if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
     {
-      CUR.error = TT_Err_Stack_Overflow;
+      CUR.error = FT_THROW( Stack_Overflow );
       return;
     }
 
@@ -5006,7 +5132,7 @@
 
     if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
     {
-      CUR.error = TT_Err_Stack_Overflow;
+      CUR.error = FT_THROW( Stack_Overflow );
       return;
     }
 
@@ -5031,7 +5157,7 @@
 
     if ( BOUNDS( L, CUR.stackSize + 1 - CUR.top ) )
     {
-      CUR.error = TT_Err_Stack_Overflow;
+      CUR.error = FT_THROW( Stack_Overflow );
       return;
     }
 
@@ -5074,7 +5200,7 @@
     if ( BOUNDSL( L, CUR.zp2.n_points ) )
     {
       if ( CUR.pedantic_hinting )
-        CUR.error = TT_Err_Invalid_Reference;
+        CUR.error = FT_THROW( Invalid_Reference );
       R = 0;
     }
     else
@@ -5111,7 +5237,7 @@
     if ( BOUNDS( L, CUR.zp2.n_points ) )
     {
       if ( CUR.pedantic_hinting )
-        CUR.error = TT_Err_Invalid_Reference;
+        CUR.error = FT_THROW( Invalid_Reference );
       return;
     }
 
@@ -5155,7 +5281,7 @@
          BOUNDS( K, CUR.zp1.n_points ) )
     {
       if ( CUR.pedantic_hinting )
-        CUR.error = TT_Err_Invalid_Reference;
+        CUR.error = FT_THROW( Invalid_Reference );
       D = 0;
     }
     else
@@ -5184,15 +5310,15 @@
           {
             /* this should be faster */
             D = CUR_Func_dualproj( vec1, vec2 );
-            D = TT_MULFIX( D, CUR.metrics.x_scale );
+            D = FT_MulFix( D, CUR.metrics.x_scale );
           }
           else
           {
             FT_Vector  vec;
 
 
-            vec.x = TT_MULFIX( vec1->x - vec2->x, CUR.metrics.x_scale );
-            vec.y = TT_MULFIX( vec1->y - vec2->y, CUR.metrics.y_scale );
+            vec.x = FT_MulFix( vec1->x - vec2->x, CUR.metrics.x_scale );
+            vec.y = FT_MulFix( vec1->y - vec2->y, CUR.metrics.y_scale );
 
             D = CUR_fast_dualproj( &vec );
           }
@@ -5200,6 +5326,13 @@
       }
     }
 
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+    /* Disable Type 2 Vacuform Rounds - e.g. Arial Narrow */
+    if ( SUBPIXEL_HINTING                       &&
+         CUR.ignore_x_mode && FT_ABS( D ) == 64 )
+      D += 1;
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
     args[0] = D;
   }
 
@@ -5225,7 +5358,7 @@
          BOUNDS( p1, CUR.zp2.n_points ) )
     {
       if ( CUR.pedantic_hinting )
-        CUR.error = TT_Err_Invalid_Reference;
+        CUR.error = FT_THROW( Invalid_Reference );
       return;
     }
 
@@ -5265,6 +5398,12 @@
 
       A = v1->x - v2->x;
       B = v1->y - v2->y;
+
+      if ( A == 0 && B == 0 )
+      {
+        A    = 0x4000;
+        aOpc = 0;
+      }
     }
 
     if ( ( aOpc & 1 ) != 0 )
@@ -5303,7 +5442,7 @@
 
     default:
       if ( CUR.pedantic_hinting )
-        CUR.error = TT_Err_Invalid_Reference;
+        CUR.error = FT_THROW( Invalid_Reference );
       return;
     }
 
@@ -5332,7 +5471,7 @@
 
     default:
       if ( CUR.pedantic_hinting )
-        CUR.error = TT_Err_Invalid_Reference;
+        CUR.error = FT_THROW( Invalid_Reference );
       return;
     }
 
@@ -5361,7 +5500,7 @@
 
     default:
       if ( CUR.pedantic_hinting )
-        CUR.error = TT_Err_Invalid_Reference;
+        CUR.error = FT_THROW( Invalid_Reference );
       return;
     }
 
@@ -5390,7 +5529,7 @@
 
     default:
       if ( CUR.pedantic_hinting )
-        CUR.error = TT_Err_Invalid_Reference;
+        CUR.error = FT_THROW( Invalid_Reference );
       return;
     }
 
@@ -5421,7 +5560,7 @@
     if ( K < 1 || K > 2 )
     {
       if ( CUR.pedantic_hinting )
-        CUR.error = TT_Err_Invalid_Reference;
+        CUR.error = FT_THROW( Invalid_Reference );
       return;
     }
 
@@ -5519,7 +5658,7 @@
     if ( CUR.top < CUR.GS.loop )
     {
       if ( CUR.pedantic_hinting )
-        CUR.error = TT_Err_Too_Few_Arguments;
+        CUR.error = FT_THROW( Too_Few_Arguments );
       goto Fail;
     }
 
@@ -5533,7 +5672,7 @@
       {
         if ( CUR.pedantic_hinting )
         {
-          CUR.error = TT_Err_Invalid_Reference;
+          CUR.error = FT_THROW( Invalid_Reference );
           return;
         }
       }
@@ -5568,7 +5707,7 @@
          BOUNDS( L, CUR.pts.n_points ) )
     {
       if ( CUR.pedantic_hinting )
-        CUR.error = TT_Err_Invalid_Reference;
+        CUR.error = FT_THROW( Invalid_Reference );
       return;
     }
 
@@ -5596,7 +5735,7 @@
          BOUNDS( L, CUR.pts.n_points ) )
     {
       if ( CUR.pedantic_hinting )
-        CUR.error = TT_Err_Invalid_Reference;
+        CUR.error = FT_THROW( Invalid_Reference );
       return;
     }
 
@@ -5630,7 +5769,7 @@
     if ( BOUNDS( p, zp.n_points ) )
     {
       if ( CUR.pedantic_hinting )
-        CUR.error = TT_Err_Invalid_Reference;
+        CUR.error = FT_THROW( Invalid_Reference );
       *refp = 0;
       return FAILURE;
     }
@@ -5657,12 +5796,8 @@
     else
 #endif
     {
-      *x = TT_MULDIV( d,
-                      (FT_Long)CUR.GS.freeVector.x * 0x10000L,
-                      CUR.F_dot_P );
-      *y = TT_MULDIV( d,
-                      (FT_Long)CUR.GS.freeVector.y * 0x10000L,
-                      CUR.F_dot_P );
+      *x = FT_MulDiv( d, (FT_Long)CUR.GS.freeVector.x, CUR.F_dot_P );
+      *y = FT_MulDiv( d, (FT_Long)CUR.GS.freeVector.y, CUR.F_dot_P );
     }
 
     return SUCCESS;
@@ -5732,7 +5867,7 @@
     if ( CUR.top < CUR.GS.loop )
     {
       if ( CUR.pedantic_hinting )
-        CUR.error = TT_Err_Invalid_Reference;
+        CUR.error = FT_THROW( Invalid_Reference );
       goto Fail;
     }
 
@@ -5748,11 +5883,18 @@
       {
         if ( CUR.pedantic_hinting )
         {
-          CUR.error = TT_Err_Invalid_Reference;
+          CUR.error = FT_THROW( Invalid_Reference );
           return;
         }
       }
       else
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+      /* doesn't follow Cleartype spec but produces better result */
+      if ( SUBPIXEL_HINTING  &&
+           CUR.ignore_x_mode )
+        MOVE_Zp2_Point( point, 0, dy, TRUE );
+      else
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
         MOVE_Zp2_Point( point, dx, dy, TRUE );
 
       CUR.GS.loop--;
@@ -5772,7 +5914,7 @@
   /*                                                                       */
   /* UNDOCUMENTED: According to Greg Hitchcock, there is one (virtual)     */
   /*               contour in the twilight zone, namely contour number     */
-  /*               zero.                                                   */
+  /*               zero which includes all points of it.                   */
   /*                                                                       */
   static void
   Ins_SHC( INS_ARG )
@@ -5791,7 +5933,7 @@
     if ( BOUNDS( contour, bounds ) )
     {
       if ( CUR.pedantic_hinting )
-        CUR.error = TT_Err_Invalid_Reference;
+        CUR.error = FT_THROW( Invalid_Reference );
       return;
     }
 
@@ -5839,7 +5981,7 @@
     if ( BOUNDS( args[0], 2 ) )
     {
       if ( CUR.pedantic_hinting )
-        CUR.error = TT_Err_Invalid_Reference;
+        CUR.error = FT_THROW( Invalid_Reference );
       return;
     }
 
@@ -5877,12 +6019,15 @@
   {
     FT_F26Dot6  dx, dy;
     FT_UShort   point;
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+    FT_Int      B1, B2;
+#endif
 
 
     if ( CUR.top < CUR.GS.loop + 1 )
     {
       if ( CUR.pedantic_hinting )
-        CUR.error = TT_Err_Invalid_Reference;
+        CUR.error = FT_THROW( Invalid_Reference );
       goto Fail;
     }
 
@@ -5891,13 +6036,13 @@
     {
       if ( CUR.GS.both_x_axis )
       {
-        dx = TT_MulFix14( (FT_UInt32)args[0], 0x4000 );
+        dx = (FT_UInt32)args[0];
         dy = 0;
       }
       else
       {
         dx = 0;
-        dy = TT_MulFix14( (FT_UInt32)args[0], 0x4000 );
+        dy = (FT_UInt32)args[0];
       }
     }
     else
@@ -5917,13 +6062,95 @@
       {
         if ( CUR.pedantic_hinting )
         {
-          CUR.error = TT_Err_Invalid_Reference;
+          CUR.error = FT_THROW( Invalid_Reference );
           return;
         }
       }
       else
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+      {
+        /*  If not using ignore_x_mode rendering, allow ZP2 move.          */
+        /*  If inline deltas aren't allowed, skip ZP2 move.                */
+        /*  If using ignore_x_mode rendering, allow ZP2 point move if:     */
+        /*   - freedom vector is y and sph_compatibility_mode is off       */
+        /*   - the glyph is composite and the move is in the Y direction   */
+        /*   - the glyph is specifically set to allow SHPIX moves          */
+        /*   - the move is on a previously Y-touched point                 */
+
+        if ( SUBPIXEL_HINTING  &&
+             CUR.ignore_x_mode )
+        {
+          /* save point for later comparison */
+          if ( CUR.GS.freeVector.y != 0 )
+            B1 = CUR.zp2.cur[point].y;
+          else
+            B1 = CUR.zp2.cur[point].x;
+
+          if ( !CUR.face->sph_compatibility_mode &&
+               CUR.GS.freeVector.y != 0          )
+          {
+            MOVE_Zp2_Point( point, dx, dy, TRUE );
+
+            /* save new point */
+            if ( CUR.GS.freeVector.y != 0 )
+            {
+              B2 = CUR.zp2.cur[point].y;
+
+              /* reverse any disallowed moves */
+              if ( ( CUR.sph_tweak_flags & SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES ) &&
+                   ( B1 & 63 ) != 0                                          &&
+                   ( B2 & 63 ) != 0                                          &&
+                    B1 != B2                                                 )
+                MOVE_Zp2_Point( point, -dx, -dy, TRUE );
+            }
+          }
+          else if ( CUR.face->sph_compatibility_mode )
+          {
+            if ( CUR.sph_tweak_flags & SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES )
+            {
+              dx = FT_PIX_ROUND( B1 + dx ) - B1;
+              dy = FT_PIX_ROUND( B1 + dy ) - B1;
+            }
+
+            /* skip post-iup deltas */
+            if ( CUR.iup_called                                          &&
+                 ( ( CUR.sph_in_func_flags & SPH_FDEF_INLINE_DELTA_1 ) ||
+                   ( CUR.sph_in_func_flags & SPH_FDEF_INLINE_DELTA_2 ) ) )
+              goto Skip;
+
+            if ( !( CUR.sph_tweak_flags & SPH_TWEAK_ALWAYS_SKIP_DELTAP ) &&
+                  ( ( CUR.is_composite && CUR.GS.freeVector.y != 0 ) ||
+                    ( CUR.zp2.tags[point] & FT_CURVE_TAG_TOUCH_Y )   ||
+                    ( CUR.sph_tweak_flags & SPH_TWEAK_DO_SHPIX )     )   )
+              MOVE_Zp2_Point( point, 0, dy, TRUE );
+
+            /* save new point */
+            if ( CUR.GS.freeVector.y != 0 )
+            {
+              B2 = CUR.zp2.cur[point].y;
+
+              /* reverse any disallowed moves */
+              if ( ( B1 & 63 ) == 0 &&
+                   ( B2 & 63 ) != 0 &&
+                   B1 != B2         )
+                MOVE_Zp2_Point( point, 0, -dy, TRUE );
+            }
+          }
+          else if ( CUR.sph_in_func_flags & SPH_FDEF_TYPEMAN_DIAGENDCTRL )
+            MOVE_Zp2_Point( point, dx, dy, TRUE );
+        }
+        else
+          MOVE_Zp2_Point( point, dx, dy, TRUE );
+      }
+
+    Skip:
+
+#else /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
         MOVE_Zp2_Point( point, dx, dy, TRUE );
 
+#endif /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
       CUR.GS.loop--;
     }
 
@@ -5945,6 +6172,21 @@
     FT_UShort   point;
     FT_F26Dot6  distance;
 
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+    FT_F26Dot6  control_value_cutin;
+
+
+    if ( SUBPIXEL_HINTING )
+    {
+      control_value_cutin = CUR.GS.control_value_cutin;
+
+      if ( CUR.ignore_x_mode                                 &&
+           CUR.GS.freeVector.x != 0                          &&
+           !( CUR.sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) )
+        control_value_cutin = 0;
+    }
+
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
 
     point = (FT_UShort)args[0];
 
@@ -5952,7 +6194,7 @@
          BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
     {
       if ( CUR.pedantic_hinting )
-        CUR.error = TT_Err_Invalid_Reference;
+        CUR.error = FT_THROW( Invalid_Reference );
       return;
     }
 
@@ -5968,6 +6210,15 @@
     distance = CUR_Func_project( CUR.zp1.cur + point,
                                  CUR.zp0.cur + CUR.GS.rp0 );
 
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+    /* subpixel hinting - make MSIRP respect CVT cut-in; */
+    if ( SUBPIXEL_HINTING                                    &&
+         CUR.ignore_x_mode                                   &&
+         CUR.GS.freeVector.x != 0                            &&
+         FT_ABS( distance - args[1] ) >= control_value_cutin )
+      distance = args[1];
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
     CUR_Func_move( &CUR.zp1, point, args[1] - distance );
 
     CUR.GS.rp1 = CUR.GS.rp0;
@@ -5988,8 +6239,8 @@
   Ins_MDAP( INS_ARG )
   {
     FT_UShort   point;
-    FT_F26Dot6  cur_dist,
-                distance;
+    FT_F26Dot6  cur_dist;
+    FT_F26Dot6  distance;
 
 
     point = (FT_UShort)args[0];
@@ -5997,15 +6248,25 @@
     if ( BOUNDS( point, CUR.zp0.n_points ) )
     {
       if ( CUR.pedantic_hinting )
-        CUR.error = TT_Err_Invalid_Reference;
+        CUR.error = FT_THROW( Invalid_Reference );
       return;
     }
 
     if ( ( CUR.opcode & 1 ) != 0 )
     {
       cur_dist = CUR_fast_project( &CUR.zp0.cur[point] );
-      distance = CUR_Func_round( cur_dist,
-                                 CUR.tt_metrics.compensations[0] ) - cur_dist;
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+      if ( SUBPIXEL_HINTING         &&
+           CUR.ignore_x_mode        &&
+           CUR.GS.freeVector.x != 0 )
+        distance = ROUND_None(
+                     cur_dist,
+                     CUR.tt_metrics.compensations[0] ) - cur_dist;
+      else
+#endif
+        distance = CUR_Func_round(
+                     cur_dist,
+                     CUR.tt_metrics.compensations[0] ) - cur_dist;
     }
     else
       distance = 0;
@@ -6028,18 +6289,29 @@
   {
     FT_ULong    cvtEntry;
     FT_UShort   point;
-    FT_F26Dot6  distance,
-                org_dist;
+    FT_F26Dot6  distance;
+    FT_F26Dot6  org_dist;
+    FT_F26Dot6  control_value_cutin;
 
 
-    cvtEntry = (FT_ULong)args[1];
-    point    = (FT_UShort)args[0];
+    control_value_cutin = CUR.GS.control_value_cutin;
+    cvtEntry            = (FT_ULong)args[1];
+    point               = (FT_UShort)args[0];
+
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+    if ( SUBPIXEL_HINTING                                  &&
+         CUR.ignore_x_mode                                 &&
+         CUR.GS.freeVector.x != 0                          &&
+         CUR.GS.freeVector.y == 0                          &&
+         !( CUR.sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) )
+      control_value_cutin = 0;
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
 
     if ( BOUNDS( point,     CUR.zp0.n_points ) ||
          BOUNDSL( cvtEntry, CUR.cvtSize )      )
     {
       if ( CUR.pedantic_hinting )
-        CUR.error = TT_Err_Invalid_Reference;
+        CUR.error = FT_THROW( Invalid_Reference );
       goto Fail;
     }
 
@@ -6067,21 +6339,45 @@
 
     if ( CUR.GS.gep0 == 0 )   /* If in twilight zone */
     {
-      CUR.zp0.org[point].x = TT_MulFix14( (FT_UInt32)distance,
-                                          CUR.GS.freeVector.x );
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+      /* Only adjust if not in sph_compatibility_mode or ignore_x_mode. */
+      /* Determined via experimentation and may be incorrect...         */
+      if ( !SUBPIXEL_HINTING                     ||
+           ( !CUR.ignore_x_mode                ||
+             !CUR.face->sph_compatibility_mode ) )
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+        CUR.zp0.org[point].x = TT_MulFix14( (FT_UInt32)distance,
+                                            CUR.GS.freeVector.x );
       CUR.zp0.org[point].y = TT_MulFix14( (FT_UInt32)distance,
                                           CUR.GS.freeVector.y ),
       CUR.zp0.cur[point]   = CUR.zp0.org[point];
     }
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+    if ( SUBPIXEL_HINTING                              &&
+         CUR.ignore_x_mode                             &&
+         ( CUR.sph_tweak_flags & SPH_TWEAK_MIAP_HACK ) &&
+         distance > 0                                  &&
+         CUR.GS.freeVector.y != 0                      )
+      distance = 0;
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
 
     org_dist = CUR_fast_project( &CUR.zp0.cur[point] );
 
-    if ( ( CUR.opcode & 1 ) != 0 )   /* rounding and control cutin flag */
+    if ( ( CUR.opcode & 1 ) != 0 )   /* rounding and control cut-in flag */
     {
-      if ( FT_ABS( distance - org_dist ) > CUR.GS.control_value_cutin )
+      if ( FT_ABS( distance - org_dist ) > control_value_cutin )
         distance = org_dist;
 
-      distance = CUR_Func_round( distance, CUR.tt_metrics.compensations[0] );
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+      if ( SUBPIXEL_HINTING         &&
+           CUR.ignore_x_mode        &&
+           CUR.GS.freeVector.x != 0 )
+        distance = ROUND_None( distance,
+                               CUR.tt_metrics.compensations[0] );
+      else
+#endif
+        distance = CUR_Func_round( distance,
+                                   CUR.tt_metrics.compensations[0] );
     }
 
     CUR_Func_move( &CUR.zp0, point, distance - org_dist );
@@ -6102,16 +6398,26 @@
   Ins_MDRP( INS_ARG )
   {
     FT_UShort   point;
-    FT_F26Dot6  org_dist, distance;
+    FT_F26Dot6  org_dist, distance, minimum_distance;
 
 
+    minimum_distance = CUR.GS.minimum_distance;
+
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+    if ( SUBPIXEL_HINTING                                  &&
+         CUR.ignore_x_mode                                 &&
+         CUR.GS.freeVector.x != 0                          &&
+         !( CUR.sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) )
+      minimum_distance = 0;
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
     point = (FT_UShort)args[0];
 
     if ( BOUNDS( point,      CUR.zp1.n_points ) ||
          BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
     {
       if ( CUR.pedantic_hinting )
-        CUR.error = TT_Err_Invalid_Reference;
+        CUR.error = FT_THROW( Invalid_Reference );
       goto Fail;
     }
 
@@ -6138,15 +6444,15 @@
       {
         /* this should be faster */
         org_dist = CUR_Func_dualproj( vec1, vec2 );
-        org_dist = TT_MULFIX( org_dist, CUR.metrics.x_scale );
+        org_dist = FT_MulFix( org_dist, CUR.metrics.x_scale );
       }
       else
       {
         FT_Vector  vec;
 
 
-        vec.x = TT_MULFIX( vec1->x - vec2->x, CUR.metrics.x_scale );
-        vec.y = TT_MULFIX( vec1->y - vec2->y, CUR.metrics.y_scale );
+        vec.x = FT_MulFix( vec1->x - vec2->x, CUR.metrics.x_scale );
+        vec.y = FT_MulFix( vec1->y - vec2->y, CUR.metrics.y_scale );
 
         org_dist = CUR_fast_dualproj( &vec );
       }
@@ -6166,9 +6472,20 @@
     /* round flag */
 
     if ( ( CUR.opcode & 4 ) != 0 )
+    {
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+      if ( SUBPIXEL_HINTING         &&
+           CUR.ignore_x_mode        &&
+           CUR.GS.freeVector.x != 0 )
+        distance = ROUND_None(
+                     org_dist,
+                     CUR.tt_metrics.compensations[CUR.opcode & 3] );
+      else
+#endif
       distance = CUR_Func_round(
                    org_dist,
                    CUR.tt_metrics.compensations[CUR.opcode & 3] );
+    }
     else
       distance = ROUND_None(
                    org_dist,
@@ -6180,13 +6497,13 @@
     {
       if ( org_dist >= 0 )
       {
-        if ( distance < CUR.GS.minimum_distance )
-          distance = CUR.GS.minimum_distance;
+        if ( distance < minimum_distance )
+          distance = minimum_distance;
       }
       else
       {
-        if ( distance > -CUR.GS.minimum_distance )
-          distance = -CUR.GS.minimum_distance;
+        if ( distance > -minimum_distance )
+          distance = -minimum_distance;
       }
     }
 
@@ -6221,11 +6538,28 @@
     FT_F26Dot6  cvt_dist,
                 distance,
                 cur_dist,
-                org_dist;
+                org_dist,
+                control_value_cutin,
+                minimum_distance;
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+    FT_Int      B1;
+    FT_Int      B2;
+    FT_Bool     reverse_move = FALSE;
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
 
 
-    point    = (FT_UShort)args[0];
-    cvtEntry = (FT_ULong)( args[1] + 1 );
+    minimum_distance    = CUR.GS.minimum_distance;
+    control_value_cutin = CUR.GS.control_value_cutin;
+    point               = (FT_UShort)args[0];
+    cvtEntry            = (FT_ULong)( args[1] + 1 );
+
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+    if ( SUBPIXEL_HINTING                                  &&
+         CUR.ignore_x_mode                                 &&
+         CUR.GS.freeVector.x != 0                          &&
+         !( CUR.sph_tweak_flags & SPH_TWEAK_NORMAL_ROUND ) )
+      control_value_cutin = minimum_distance = 0;
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
 
     /* XXX: UNDOCUMENTED! cvt[-1] = 0 always */
 
@@ -6234,7 +6568,7 @@
          BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
     {
       if ( CUR.pedantic_hinting )
-        CUR.error = TT_Err_Invalid_Reference;
+        CUR.error = FT_THROW( Invalid_Reference );
       goto Fail;
     }
 
@@ -6280,7 +6614,20 @@
         cvt_dist = -cvt_dist;
     }
 
-    /* control value cutin and round */
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+    if ( SUBPIXEL_HINTING                                         &&
+         CUR.ignore_x_mode                                        &&
+         CUR.GS.freeVector.y != 0                                 &&
+         ( CUR.sph_tweak_flags & SPH_TWEAK_TIMES_NEW_ROMAN_HACK ) )
+    {
+      if ( cur_dist < -64 )
+        cvt_dist -= 16;
+      else if ( cur_dist > 64 && cur_dist < 84 )
+        cvt_dist += 32;
+    }
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
+    /* control value cut-in and round */
 
     if ( ( CUR.opcode & 4 ) != 0 )
     {
@@ -6301,7 +6648,7 @@
         /*      `ttinst2.doc', version 1.66, is thus incorrect since  */
         /*      it implies `>=' instead of `>'.                       */
 
-        if ( FT_ABS( cvt_dist - org_dist ) > CUR.GS.control_value_cutin )
+        if ( FT_ABS( cvt_dist - org_dist ) > control_value_cutin )
           cvt_dist = org_dist;
       }
 
@@ -6310,9 +6657,23 @@
                    CUR.tt_metrics.compensations[CUR.opcode & 3] );
     }
     else
+    {
+
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+      /* do cvt cut-in always in MIRP for sph */
+      if ( SUBPIXEL_HINTING           &&
+           CUR.ignore_x_mode          &&
+           CUR.GS.gep0 == CUR.GS.gep1 )
+      {
+        if ( FT_ABS( cvt_dist - org_dist ) > control_value_cutin )
+          cvt_dist = org_dist;
+      }
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
       distance = ROUND_None(
                    cvt_dist,
                    CUR.tt_metrics.compensations[CUR.opcode & 3] );
+    }
 
     /* minimum distance test */
 
@@ -6320,18 +6681,65 @@
     {
       if ( org_dist >= 0 )
       {
-        if ( distance < CUR.GS.minimum_distance )
-          distance = CUR.GS.minimum_distance;
+        if ( distance < minimum_distance )
+          distance = minimum_distance;
       }
       else
       {
-        if ( distance > -CUR.GS.minimum_distance )
-          distance = -CUR.GS.minimum_distance;
+        if ( distance > -minimum_distance )
+          distance = -minimum_distance;
       }
     }
 
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+    if ( SUBPIXEL_HINTING )
+    {
+      B1 = CUR.zp1.cur[point].y;
+
+      /* Round moves if necessary */
+      if ( CUR.ignore_x_mode                                          &&
+           CUR.GS.freeVector.y != 0                                   &&
+           ( CUR.sph_tweak_flags & SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES ) )
+        distance = FT_PIX_ROUND( B1 + distance - cur_dist ) - B1 + cur_dist;
+
+      if ( CUR.ignore_x_mode                                      &&
+           CUR.GS.freeVector.y != 0                               &&
+           ( CUR.opcode & 16 ) == 0                               &&
+           ( CUR.opcode & 8 ) == 0                                &&
+           ( CUR.sph_tweak_flags & SPH_TWEAK_COURIER_NEW_2_HACK ) )
+        distance += 64;
+    }
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
     CUR_Func_move( &CUR.zp1, point, distance - cur_dist );
 
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+    if ( SUBPIXEL_HINTING )
+    {
+      B2 = CUR.zp1.cur[point].y;
+
+      /* Reverse move if necessary */
+      if ( CUR.ignore_x_mode )
+      {
+        if ( CUR.face->sph_compatibility_mode                          &&
+             CUR.GS.freeVector.y != 0                                  &&
+             ( B1 & 63 ) == 0                                          &&
+             ( B2 & 63 ) != 0                                          )
+          reverse_move = TRUE;
+
+        if ( ( CUR.sph_tweak_flags & SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES ) &&
+             CUR.GS.freeVector.y != 0                                  &&
+             ( B2 & 63 ) != 0                                          &&
+             ( B1 & 63 ) != 0                                          )
+          reverse_move = TRUE;
+      }
+
+      if ( reverse_move )
+        CUR_Func_move( &CUR.zp1, point, -( distance - cur_dist ) );
+    }
+
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
   Fail:
     CUR.GS.rp1 = CUR.GS.rp0;
 
@@ -6357,11 +6765,22 @@
     FT_UNUSED_ARG;
 
 
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+    if ( SUBPIXEL_HINTING                                         &&
+         CUR.ignore_x_mode                                        &&
+         CUR.iup_called                                           &&
+         ( CUR.sph_tweak_flags & SPH_TWEAK_NO_ALIGNRP_AFTER_IUP ) )
+    {
+      CUR.error = FT_THROW( Invalid_Reference );
+      goto Fail;
+    }
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
     if ( CUR.top < CUR.GS.loop ||
          BOUNDS( CUR.GS.rp0, CUR.zp0.n_points ) )
     {
       if ( CUR.pedantic_hinting )
-        CUR.error = TT_Err_Invalid_Reference;
+        CUR.error = FT_THROW( Invalid_Reference );
       goto Fail;
     }
 
@@ -6375,7 +6794,7 @@
       {
         if ( CUR.pedantic_hinting )
         {
-          CUR.error = TT_Err_Invalid_Reference;
+          CUR.error = FT_THROW( Invalid_Reference );
           return;
         }
       }
@@ -6409,7 +6828,7 @@
                 a0, a1,
                 b0, b1;
 
-    FT_F26Dot6  discriminant;
+    FT_F26Dot6  discriminant, dotproduct;
 
     FT_F26Dot6  dx,  dy,
                 dax, day,
@@ -6434,10 +6853,12 @@
          BOUNDS( point, CUR.zp2.n_points ) )
     {
       if ( CUR.pedantic_hinting )
-        CUR.error = TT_Err_Invalid_Reference;
+        CUR.error = FT_THROW( Invalid_Reference );
       return;
     }
 
+    /* Cramer's rule */
+
     dbx = CUR.zp0.cur[b1].x - CUR.zp0.cur[b0].x;
     dby = CUR.zp0.cur[b1].y - CUR.zp0.cur[b0].y;
 
@@ -6449,15 +6870,25 @@
 
     CUR.zp2.tags[point] |= FT_CURVE_TAG_TOUCH_BOTH;
 
-    discriminant = TT_MULDIV( dax, -dby, 0x40 ) +
-                   TT_MULDIV( day, dbx, 0x40 );
+    discriminant = FT_MulDiv( dax, -dby, 0x40 ) +
+                   FT_MulDiv( day, dbx, 0x40 );
+    dotproduct   = FT_MulDiv( dax, dbx, 0x40 ) +
+                   FT_MulDiv( day, dby, 0x40 );
 
-    if ( FT_ABS( discriminant ) >= 0x40 )
+    /* The discriminant above is actually a cross product of vectors     */
+    /* da and db. Together with the dot product, they can be used as     */
+    /* surrogates for sine and cosine of the angle between the vectors.  */
+    /* Indeed,                                                           */
+    /*       dotproduct   = |da||db|cos(angle)                           */
+    /*       discriminant = |da||db|sin(angle)     .                     */
+    /* We use these equations to reject grazing intersections by         */
+    /* thresholding abs(tan(angle)) at 1/19, corresponding to 3 degrees. */
+    if ( 19 * FT_ABS( discriminant ) > FT_ABS( dotproduct ) )
     {
-      val = TT_MULDIV( dx, -dby, 0x40 ) + TT_MULDIV( dy, dbx, 0x40 );
+      val = FT_MulDiv( dx, -dby, 0x40 ) + FT_MulDiv( dy, dbx, 0x40 );
 
-      R.x = TT_MULDIV( val, dax, discriminant );
-      R.y = TT_MULDIV( val, day, discriminant );
+      R.x = FT_MulDiv( val, dax, discriminant );
+      R.y = FT_MulDiv( val, day, discriminant );
 
       CUR.zp2.cur[point].x = CUR.zp1.cur[a0].x + R.x;
       CUR.zp2.cur[point].y = CUR.zp1.cur[a0].y + R.y;
@@ -6498,7 +6929,7 @@
          BOUNDS( p2, CUR.zp0.n_points ) )
     {
       if ( CUR.pedantic_hinting )
-        CUR.error = TT_Err_Invalid_Reference;
+        CUR.error = FT_THROW( Invalid_Reference );
       return;
     }
 
@@ -6533,7 +6964,7 @@
     if ( CUR.top < CUR.GS.loop )
     {
       if ( CUR.pedantic_hinting )
-        CUR.error = TT_Err_Invalid_Reference;
+        CUR.error = FT_THROW( Invalid_Reference );
       goto Fail;
     }
 
@@ -6547,7 +6978,7 @@
     if ( BOUNDS( CUR.GS.rp1, CUR.zp0.n_points ) )
     {
       if ( CUR.pedantic_hinting )
-        CUR.error = TT_Err_Invalid_Reference;
+        CUR.error = FT_THROW( Invalid_Reference );
       goto Fail;
     }
 
@@ -6581,9 +7012,9 @@
         FT_Vector  vec;
 
 
-        vec.x = TT_MULFIX( CUR.zp1.orus[CUR.GS.rp2].x - orus_base->x,
+        vec.x = FT_MulFix( CUR.zp1.orus[CUR.GS.rp2].x - orus_base->x,
                            CUR.metrics.x_scale );
-        vec.y = TT_MULFIX( CUR.zp1.orus[CUR.GS.rp2].y - orus_base->y,
+        vec.y = FT_MulFix( CUR.zp1.orus[CUR.GS.rp2].y - orus_base->y,
                            CUR.metrics.y_scale );
 
         old_range = CUR_fast_dualproj( &vec );
@@ -6603,7 +7034,7 @@
       {
         if ( CUR.pedantic_hinting )
         {
-          CUR.error = TT_Err_Invalid_Reference;
+          CUR.error = FT_THROW( Invalid_Reference );
           return;
         }
         continue;
@@ -6618,9 +7049,9 @@
         FT_Vector  vec;
 
 
-        vec.x = TT_MULFIX( CUR.zp2.orus[point].x - orus_base->x,
+        vec.x = FT_MulFix( CUR.zp2.orus[point].x - orus_base->x,
                            CUR.metrics.x_scale );
-        vec.y = TT_MULFIX( CUR.zp2.orus[point].y - orus_base->y,
+        vec.y = FT_MulFix( CUR.zp2.orus[point].y - orus_base->y,
                            CUR.metrics.y_scale );
 
         org_dist = CUR_fast_dualproj( &vec );
@@ -6629,9 +7060,24 @@
       cur_dist = CUR_Func_project ( &CUR.zp2.cur[point], cur_base );
 
       if ( org_dist )
-        new_dist = ( old_range != 0 )
-                     ? TT_MULDIV( org_dist, cur_range, old_range )
-                     : cur_dist;
+      {
+        if ( old_range )
+          new_dist = FT_MulDiv( org_dist, cur_range, old_range );
+        else
+        {
+          /* This is the same as what MS does for the invalid case:  */
+          /*                                                         */
+          /*   delta = (Original_Pt - Original_RP1) -                */
+          /*           (Current_Pt - Current_RP1)                    */
+          /*                                                         */
+          /* In FreeType speak:                                      */
+          /*                                                         */
+          /*   new_dist = cur_dist -                                 */
+          /*              org_dist - cur_dist;                       */
+
+          new_dist = -org_dist;
+        }
+      }
       else
         new_dist = 0;
 
@@ -6662,7 +7108,7 @@
     if ( BOUNDS( point, CUR.zp0.n_points ) )
     {
       if ( CUR.pedantic_hinting )
-        CUR.error = TT_Err_Invalid_Reference;
+        CUR.error = FT_THROW( Invalid_Reference );
       return;
     }
 
@@ -6791,12 +7237,12 @@
           if ( !scale_valid )
           {
             scale_valid = 1;
-            scale       = TT_MULDIV( org2 + delta2 - ( org1 + delta1 ),
-                                     0x10000L, orus2 - orus1 );
+            scale       = FT_DivFix( org2 + delta2 - ( org1 + delta1 ),
+                                     orus2 - orus1 );
           }
 
           x = ( org1 + delta1 ) +
-              TT_MULFIX( worker->orus[i].x - orus1, scale );
+              FT_MulFix( worker->orus[i].x - orus1, scale );
         }
         worker->curs[i].x = x;
       }
@@ -6851,6 +7297,16 @@
     contour = 0;
     point   = 0;
 
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+    if ( SUBPIXEL_HINTING  &&
+         CUR.ignore_x_mode )
+    {
+      CUR.iup_called = TRUE;
+      if ( CUR.sph_tweak_flags & SPH_TWEAK_SKIP_IUP )
+        return;
+    }
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
     do
     {
       end_point   = CUR.pts.contours[contour] - CUR.pts.first_point;
@@ -6920,6 +7376,16 @@
     FT_UShort  A;
     FT_ULong   C;
     FT_Long    B;
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+    FT_UShort  B1, B2;
+
+
+    if ( SUBPIXEL_HINTING                                        &&
+         CUR.ignore_x_mode                                       &&
+         CUR.iup_called                                          &&
+         ( CUR.sph_tweak_flags & SPH_TWEAK_NO_DELTAP_AFTER_IUP ) )
+      goto Fail;
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
 
 
 #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING
@@ -6932,7 +7398,7 @@
       if ( CUR.args < n )
       {
         if ( CUR.pedantic_hinting )
-          CUR.error = TT_Err_Too_Few_Arguments;
+          CUR.error = FT_THROW( Too_Few_Arguments );
         n = CUR.args;
       }
 
@@ -6950,7 +7416,7 @@
       if ( CUR.args < 2 )
       {
         if ( CUR.pedantic_hinting )
-          CUR.error = TT_Err_Too_Few_Arguments;
+          CUR.error = FT_THROW( Too_Few_Arguments );
         CUR.args = 0;
         goto Fail;
       }
@@ -6993,12 +7459,82 @@
             B++;
           B = B * 64 / ( 1L << CUR.GS.delta_shift );
 
-          CUR_Func_move( &CUR.zp0, A, B );
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+
+          if ( SUBPIXEL_HINTING )
+          {
+            /*
+             *  Allow delta move if
+             *
+             *  - not using ignore_x_mode rendering
+             *  - glyph is specifically set to allow it
+             *  - glyph is composite and freedom vector is not subpixel
+             *    vector
+             */
+            if ( !CUR.ignore_x_mode                                   ||
+                 ( CUR.sph_tweak_flags & SPH_TWEAK_ALWAYS_DO_DELTAP ) ||
+                 ( CUR.is_composite && CUR.GS.freeVector.y != 0 )     )
+              CUR_Func_move( &CUR.zp0, A, B );
+
+            /* Otherwise apply subpixel hinting and */
+            /* compatibility mode rules             */
+            else if ( CUR.ignore_x_mode )
+            {
+              if ( CUR.GS.freeVector.y != 0 )
+                B1 = CUR.zp0.cur[A].y;
+              else
+                B1 = CUR.zp0.cur[A].x;
+
+#if 0
+              /* Standard Subpixel Hinting: Allow y move.       */
+              /* This messes up dejavu and may not be needed... */
+              if ( !CUR.face->sph_compatibility_mode &&
+                   CUR.GS.freeVector.y != 0          )
+                CUR_Func_move( &CUR.zp0, A, B );
+              else
+#endif /* 0 */
+
+              /* Compatibility Mode: Allow x or y move if point touched in */
+              /* Y direction.                                              */
+              if ( CUR.face->sph_compatibility_mode                      &&
+                   !( CUR.sph_tweak_flags & SPH_TWEAK_ALWAYS_SKIP_DELTAP ) )
+              {
+                /* save the y value of the point now; compare after move */
+                B1 = CUR.zp0.cur[A].y;
+
+                if ( CUR.sph_tweak_flags & SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES )
+                  B = FT_PIX_ROUND( B1 + B ) - B1;
+
+                /* Allow delta move if using sph_compatibility_mode,   */
+                /* IUP has not been called, and point is touched on Y. */
+                if ( !CUR.iup_called                            &&
+                     ( CUR.zp0.tags[A] & FT_CURVE_TAG_TOUCH_Y ) )
+                  CUR_Func_move( &CUR.zp0, A, B );
+              }
+
+              B2 = CUR.zp0.cur[A].y;
+
+              /* Reverse this move if it results in a disallowed move */
+              if ( CUR.GS.freeVector.y != 0                           &&
+                   ( ( CUR.face->sph_compatibility_mode           &&
+                       ( B1 & 63 ) == 0                           &&
+                       ( B2 & 63 ) != 0                           ) ||
+                     ( ( CUR.sph_tweak_flags                    &
+                         SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES_DELTAP ) &&
+                       ( B1 & 63 ) != 0                           &&
+                       ( B2 & 63 ) != 0                           ) ) )
+                CUR_Func_move( &CUR.zp0, A, -B );
+            }
+          }
+          else
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
+            CUR_Func_move( &CUR.zp0, A, B );
         }
       }
       else
         if ( CUR.pedantic_hinting )
-          CUR.error = TT_Err_Invalid_Reference;
+          CUR.error = FT_THROW( Invalid_Reference );
     }
 
   Fail:
@@ -7030,7 +7566,7 @@
       if ( CUR.args < n )
       {
         if ( CUR.pedantic_hinting )
-          CUR.error = TT_Err_Too_Few_Arguments;
+          CUR.error = FT_THROW( Too_Few_Arguments );
         n = CUR.args;
       }
 
@@ -7047,7 +7583,7 @@
       if ( CUR.args < 2 )
       {
         if ( CUR.pedantic_hinting )
-          CUR.error = TT_Err_Too_Few_Arguments;
+          CUR.error = FT_THROW( Too_Few_Arguments );
         CUR.args = 0;
         goto Fail;
       }
@@ -7061,7 +7597,7 @@
       {
         if ( CUR.pedantic_hinting )
         {
-          CUR.error = TT_Err_Invalid_Reference;
+          CUR.error = FT_THROW( Invalid_Reference );
           return;
         }
       }
@@ -7123,22 +7659,119 @@
 
     K = 0;
 
-    /* We return MS rasterizer version 1.7 for the font scaler. */
-    if ( ( args[0] & 1 ) != 0 )
-      K = 35;
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+    /********************************/
+    /* RASTERIZER VERSION           */
+    /* Selector Bit:  0             */
+    /* Return Bit(s): 0-7           */
+    /*                              */
+    if ( SUBPIXEL_HINTING     &&
+         ( args[0] & 1 ) != 0 &&
+         CUR.ignore_x_mode    )
+    {
+      K = CUR.rasterizer_version;
+      FT_TRACE7(( "Setting rasterizer version %d\n",
+                  CUR.rasterizer_version ));
+    }
+    else
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+      if ( ( args[0] & 1 ) != 0 )
+        K = TT_INTERPRETER_VERSION_35;
 
-    /* Has the glyph been rotated? */
+    /********************************/
+    /* GLYPH ROTATED                */
+    /* Selector Bit:  1             */
+    /* Return Bit(s): 8             */
+    /*                              */
     if ( ( args[0] & 2 ) != 0 && CUR.tt_metrics.rotated )
       K |= 0x80;
 
-    /* Has the glyph been stretched? */
+    /********************************/
+    /* GLYPH STRETCHED              */
+    /* Selector Bit:  2             */
+    /* Return Bit(s): 9             */
+    /*                              */
     if ( ( args[0] & 4 ) != 0 && CUR.tt_metrics.stretched )
       K |= 1 << 8;
 
-    /* Are we hinting for grayscale? */
+    /********************************/
+    /* HINTING FOR GRAYSCALE        */
+    /* Selector Bit:  5             */
+    /* Return Bit(s): 12            */
+    /*                              */
     if ( ( args[0] & 32 ) != 0 && CUR.grayscale )
       K |= 1 << 12;
 
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+
+    if ( SUBPIXEL_HINTING                                    &&
+         CUR.ignore_x_mode                                   &&
+         CUR.rasterizer_version >= TT_INTERPRETER_VERSION_35 )
+    {
+      /********************************/
+      /* HINTING FOR GRAYSCALE        */
+      /* Selector Bit:  5             */
+      /* Return Bit(s): 12            */
+      /*                              */
+      if ( ( args[0] & 32 ) != 0 && CUR.grayscale_hinting )
+        K |= 1 << 12;
+
+      /********************************/
+      /* HINTING FOR SUBPIXEL         */
+      /* Selector Bit:  6             */
+      /* Return Bit(s): 13            */
+      /*                              */
+      if ( ( args[0] & 64 ) != 0        &&
+           CUR.subpixel_hinting         &&
+           CUR.rasterizer_version >= 37 )
+      {
+        K |= 1 << 13;
+
+        /* the stuff below is irrelevant if subpixel_hinting is not set */
+
+        /********************************/
+        /* COMPATIBLE WIDTHS ENABLED    */
+        /* Selector Bit:  7             */
+        /* Return Bit(s): 14            */
+        /*                              */
+        /* Functionality still needs to be added */
+        if ( ( args[0] & 128 ) != 0 && CUR.compatible_widths )
+          K |= 1 << 14;
+
+        /********************************/
+        /* SYMMETRICAL SMOOTHING        */
+        /* Selector Bit:  8             */
+        /* Return Bit(s): 15            */
+        /*                              */
+        /* Functionality still needs to be added */
+        if ( ( args[0] & 256 ) != 0 && CUR.symmetrical_smoothing )
+          K |= 1 << 15;
+
+        /********************************/
+        /* HINTING FOR BGR?             */
+        /* Selector Bit:  9             */
+        /* Return Bit(s): 16            */
+        /*                              */
+        /* Functionality still needs to be added */
+        if ( ( args[0] & 512 ) != 0 && CUR.bgr )
+          K |= 1 << 16;
+
+        if ( CUR.rasterizer_version >= 38 )
+        {
+          /********************************/
+          /* SUBPIXEL POSITIONED?         */
+          /* Selector Bit:  10            */
+          /* Return Bit(s): 17            */
+          /*                              */
+          /* Functionality still needs to be added */
+          if ( ( args[0] & 1024 ) != 0 && CUR.subpixel_positioned )
+            K |= 1 << 17;
+        }
+      }
+    }
+
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
     args[0] = K;
   }
 
@@ -7161,7 +7794,7 @@
 
         if ( CUR.callTop >= CUR.callSize )
         {
-          CUR.error = TT_Err_Stack_Overflow;
+          CUR.error = FT_THROW( Stack_Overflow );
           return;
         }
 
@@ -7180,7 +7813,7 @@
       }
     }
 
-    CUR.error = TT_Err_Invalid_Opcode;
+    CUR.error = FT_THROW( Invalid_Opcode );
   }
 
 
@@ -7507,13 +8140,31 @@
   FT_EXPORT_DEF( FT_Error )
   TT_RunIns( TT_ExecContext  exc )
   {
-    FT_Long  ins_counter = 0;  /* executed instructions counter */
+    FT_Long    ins_counter = 0;  /* executed instructions counter */
+    FT_UShort  i;
+
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+    FT_Byte    opcode_pattern[1][2] = {
+                  /* #8 TypeMan Talk Align */
+                  {
+                    0x06, /* SPVTL   */
+                    0x7D, /* RDTG    */
+                  },
+                };
+    FT_UShort  opcode_patterns   = 1;
+    FT_UShort  opcode_pointer[1] = { 0 };
+    FT_UShort  opcode_size[1]    = { 1 };
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
 
 
 #ifdef TT_CONFIG_OPTION_STATIC_RASTER
     cur = *exc;
 #endif
 
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+    CUR.iup_called = FALSE;
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
     /* set CVT functions */
     CUR.tt_metrics.ratio = 0;
     if ( CUR.metrics.x_ppem != CUR.metrics.y_ppem )
@@ -7560,12 +8211,9 @@
       /* One can also interpret it as the index of the last argument.    */
       if ( CUR.args < 0 )
       {
-        FT_UShort  i;
-
-
         if ( CUR.pedantic_hinting )
         {
-          CUR.error = TT_Err_Too_Few_Arguments;
+          CUR.error = FT_THROW( Too_Few_Arguments );
           goto LErrorLabel_;
         }
 
@@ -7582,12 +8230,45 @@
       /* statement.                                                     */
       if ( CUR.new_top > CUR.stackSize )
       {
-        CUR.error = TT_Err_Stack_Overflow;
+        CUR.error = FT_THROW( Stack_Overflow );
         goto LErrorLabel_;
       }
 
       CUR.step_ins = TRUE;
-      CUR.error    = TT_Err_Ok;
+      CUR.error    = FT_Err_Ok;
+
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+
+      if ( SUBPIXEL_HINTING )
+      {
+        for ( i = 0; i < opcode_patterns; i++ )
+        {
+          if ( opcode_pointer[i] < opcode_size[i]                 &&
+               CUR.opcode == opcode_pattern[i][opcode_pointer[i]] )
+          {
+            opcode_pointer[i] += 1;
+
+            if ( opcode_pointer[i] == opcode_size[i] )
+            {
+              FT_TRACE7(( "sph: opcode ptrn: %d, %s %s\n",
+                          i,
+                          CUR.face->root.family_name,
+                          CUR.face->root.style_name ));
+
+              switch ( i )
+              {
+              case 0:
+                break;
+              }
+              opcode_pointer[i] = 0;
+            }
+          }
+          else
+            opcode_pointer[i] = 0;
+        }
+      }
+
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
 
 #ifdef TT_CONFIG_OPTION_INTERPRETER_SWITCH
 
@@ -7801,7 +8482,6 @@
           Ins_MDAP( EXEC_ARG_ args );
           break;
 
-
         case 0x30:  /* IUP */
         case 0x31:  /* IUP */
           Ins_IUP( EXEC_ARG_ args );
@@ -7861,7 +8541,7 @@
           break;
 
       Set_Invalid_Ref:
-            CUR.error = TT_Err_Invalid_Reference;
+            CUR.error = FT_THROW( Invalid_Reference );
           break;
 
         case 0x43:  /* RS */
@@ -8151,11 +8831,12 @@
 
 #endif /* TT_CONFIG_OPTION_INTERPRETER_SWITCH */
 
-      if ( CUR.error != TT_Err_Ok )
+      if ( CUR.error )
       {
         switch ( CUR.error )
         {
-        case TT_Err_Invalid_Opcode: /* looking for redefined instructions */
+          /* looking for redefined instructions */
+        case FT_ERR( Invalid_Opcode ):
           {
             TT_DefRecord*  def   = CUR.IDefs;
             TT_DefRecord*  limit = def + CUR.numIDefs;
@@ -8170,7 +8851,7 @@
 
                 if ( CUR.callTop >= CUR.callSize )
                 {
-                  CUR.error = TT_Err_Invalid_Reference;
+                  CUR.error = FT_THROW( Invalid_Reference );
                   goto LErrorLabel_;
                 }
 
@@ -8190,7 +8871,7 @@
             }
           }
 
-          CUR.error = TT_Err_Invalid_Opcode;
+          CUR.error = FT_THROW( Invalid_Opcode );
           goto LErrorLabel_;
 
 #if 0
@@ -8216,14 +8897,14 @@
       /* increment instruction counter and check if we didn't */
       /* run this program for too long (e.g. infinite loops). */
       if ( ++ins_counter > MAX_RUNNABLE_OPCODES )
-        return TT_Err_Execution_Too_Long;
+        return FT_THROW( Execution_Too_Long );
 
     LSuiteLabel_:
       if ( CUR.IP >= CUR.codeSize )
       {
         if ( CUR.callTop > 0 )
         {
-          CUR.error = TT_Err_Code_Overflow;
+          CUR.error = FT_THROW( Code_Overflow );
           goto LErrorLabel_;
         }
         else
@@ -8237,10 +8918,10 @@
     *exc = cur;
 #endif
 
-    return TT_Err_Ok;
+    return FT_Err_Ok;
 
   LErrorCodeOverflow_:
-    CUR.error = TT_Err_Code_Overflow;
+    CUR.error = FT_THROW( Code_Overflow );
 
   LErrorLabel_:
 
diff --git a/src/truetype/ttinterp.h b/src/truetype/ttinterp.h
index 6d0fc03..69f5011 100644
--- a/src/truetype/ttinterp.h
+++ b/src/truetype/ttinterp.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    TrueType bytecode interpreter (specification).                       */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2010 by       */
+/*  Copyright 1996-2007, 2010, 2012-2013 by                                */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -107,6 +107,48 @@
   } TT_CallRec, *TT_CallStack;
 
 
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* These structures define rules used to tweak subpixel hinting for      */
+  /* various fonts.  "", 0, "", NULL value indicates to match any value.   */
+  /*                                                                       */
+
+#define SPH_MAX_NAME_SIZE      32
+#define SPH_MAX_CLASS_MEMBERS  100
+
+  typedef struct  SPH_TweakRule_
+  {
+    const char      family[SPH_MAX_NAME_SIZE];
+    const FT_UInt   ppem;
+    const char      style[SPH_MAX_NAME_SIZE];
+    const FT_ULong  glyph;
+
+  } SPH_TweakRule;
+
+
+  typedef struct  SPH_ScaleRule_
+  {
+    const char      family[SPH_MAX_NAME_SIZE];
+    const FT_UInt   ppem;
+    const char      style[SPH_MAX_NAME_SIZE];
+    const FT_ULong  glyph;
+    const FT_ULong  scale;
+
+  } SPH_ScaleRule;
+
+
+  typedef struct  SPH_Font_Class_
+  {
+    const char  name[SPH_MAX_NAME_SIZE];
+    const char  member[SPH_MAX_CLASS_MEMBERS][SPH_MAX_NAME_SIZE];
+
+  } SPH_Font_Class;
+
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
+
   /*************************************************************************/
   /*                                                                       */
   /* The main structure for the interpreter which collects all necessary   */
@@ -218,12 +260,43 @@
 
     FT_Bool            grayscale;      /* are we hinting for grayscale? */
 
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+    TT_Round_Func      func_round_sphn;   /* subpixel rounding function */
+
+    FT_Bool            grayscale_hinting; /* Using grayscale hinting?      */
+    FT_Bool            subpixel_hinting;  /* Using subpixel hinting?       */
+    FT_Bool            native_hinting;    /* Using native hinting?         */
+    FT_Bool            ignore_x_mode;     /* Standard rendering mode for   */
+                                          /* subpixel hinting.  On if gray */
+                                          /* or subpixel hinting is on )   */
+
+    /* The following 4 aren't fully implemented but here for MS rasterizer */
+    /* compatibility.                                                      */
+    FT_Bool            compatible_widths;     /* compatible widths?        */
+    FT_Bool            symmetrical_smoothing; /* symmetrical_smoothing?    */
+    FT_Bool            bgr;                   /* bgr instead of rgb?       */
+    FT_Bool            subpixel_positioned;   /* subpixel positioned       */
+                                              /* (DirectWrite ClearType)?  */
+
+    FT_Int             rasterizer_version;    /* MS rasterizer version     */
+
+    FT_Bool            iup_called;            /* IUP called for glyph?     */
+
+    FT_ULong           sph_tweak_flags;       /* flags to control          */
+                                              /* hint tweaks               */
+
+    FT_ULong           sph_in_func_flags;     /* flags to indicate if in   */
+                                              /* special functions         */
+
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
   } TT_ExecContextRec;
 
 
   extern const TT_GraphicsState  tt_default_graphics_state;
 
 
+#ifdef TT_USE_BYTECODE_INTERPRETER
   FT_LOCAL( FT_Error )
   TT_Goto_CodeRange( TT_ExecContext  exec,
                      FT_Int          range,
@@ -246,6 +319,7 @@
               FT_Long    multiplier,
               void*      _pbuff,
               FT_ULong   new_max );
+#endif /* TT_USE_BYTECODE_INTERPRETER */
 
 
   /*************************************************************************/
@@ -270,6 +344,8 @@
   FT_EXPORT( TT_ExecContext )
   TT_New_Context( TT_Driver  driver );
 
+
+#ifdef TT_USE_BYTECODE_INTERPRETER
   FT_LOCAL( FT_Error )
   TT_Done_Context( TT_ExecContext  exec );
 
@@ -285,6 +361,7 @@
   FT_LOCAL( FT_Error )
   TT_Run_Context( TT_ExecContext  exec,
                   FT_Bool         debug );
+#endif /* TT_USE_BYTECODE_INTERPRETER */
 
 
   /*************************************************************************/
diff --git a/src/truetype/ttobjs.c b/src/truetype/ttobjs.c
index 814c713..7897efa 100644
--- a/src/truetype/ttobjs.c
+++ b/src/truetype/ttobjs.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Objects manager (body).                                              */
 /*                                                                         */
-/*  Copyright 1996-2011                                                    */
+/*  Copyright 1996-2013                                                    */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -21,6 +21,7 @@
 #include FT_INTERNAL_STREAM_H
 #include FT_TRUETYPE_TAGS_H
 #include FT_INTERNAL_SFNT_H
+#include FT_TRUETYPE_DRIVER_H
 
 #include "ttgload.h"
 #include "ttpload.h"
@@ -244,7 +245,7 @@
   tt_check_trickyness_sfnt_ids( TT_Face  face )
   {
 #define TRICK_SFNT_IDS_PER_FACE   3
-#define TRICK_SFNT_IDS_NUM_FACES  13
+#define TRICK_SFNT_IDS_NUM_FACES  17
 
     static const tt_sfnt_id_rec sfnt_id[TRICK_SFNT_IDS_NUM_FACES]
                                        [TRICK_SFNT_IDS_PER_FACE] = {
@@ -317,6 +318,26 @@
         { 0x00000000, 0x00000000 }, /* cvt  */
         { 0x0d3de9cb, 0x00000141 }, /* fpgm */
         { 0xd4127766, 0x00002280 }  /* prep */
+      },
+      { /* NEC FA-Gothic, 1996 */
+        { 0x00000000, 0x00000000 }, /* cvt  */
+        { 0x4a692698, 0x000001f0 }, /* fpgm */
+        { 0x340d4346, 0x00001fca }  /* prep */
+      },
+      { /* NEC FA-Minchou, 1996 */
+        { 0x00000000, 0x00000000 }, /* cvt  */
+        { 0xcd34c604, 0x00000166 }, /* fpgm */
+        { 0x6cf31046, 0x000022b0 }  /* prep */
+      },
+      { /* NEC FA-RoundGothicB, 1996 */
+        { 0x00000000, 0x00000000 }, /* cvt  */
+        { 0x5da75315, 0x0000019d }, /* fpgm */
+        { 0x40745a5f, 0x000022e0 }  /* prep */
+      },
+      { /* NEC FA-RoundGothicM, 1996 */
+        { 0x00000000, 0x00000000 }, /* cvt  */
+        { 0xf055fc48, 0x000001c2 }, /* fpgm */
+        { 0x3900ded3, 0x00001e18 }  /* prep */
       }
     };
 
@@ -501,7 +522,7 @@
     if ( !sfnt )
     {
       FT_ERROR(( "tt_face_init: cannot access `sfnt' module\n" ));
-      error = TT_Err_Missing_Module;
+      error = FT_THROW( Missing_Module );
       goto Exit;
     }
 
@@ -531,7 +552,7 @@
 
     /* If we are performing a simple font format check, exit immediately. */
     if ( face_index < 0 )
-      return TT_Err_Ok;
+      return FT_Err_Ok;
 
     /* Load font directory */
     error = sfnt->load_face( stream, face, face_index, num_params, params );
@@ -631,7 +652,7 @@
     return error;
 
   Bad_Format:
-    error = TT_Err_Unknown_File_Format;
+    error = FT_THROW( Unknown_File_Format );
     goto Exit;
   }
 
@@ -732,7 +753,7 @@
       exec = ( (TT_Driver)FT_FACE_DRIVER( face ) )->context;
 
     if ( !exec )
-      return TT_Err_Could_Not_Find_Context;
+      return FT_THROW( Could_Not_Find_Context );
 
     TT_Load_Context( exec, face, size );
 
@@ -744,7 +765,7 @@
     exec->threshold = 0;
 
     exec->instruction_trap = FALSE;
-    exec->F_dot_P          = 0x10000L;
+    exec->F_dot_P          = 0x4000L;
 
     exec->pedantic_hinting = pedantic;
 
@@ -785,7 +806,7 @@
       }
     }
     else
-      error = TT_Err_Ok;
+      error = FT_Err_Ok;
 
     if ( !error )
       TT_Save_Context( exec, size );
@@ -826,7 +847,7 @@
       exec = ( (TT_Driver)FT_FACE_DRIVER( face ) )->context;
 
     if ( !exec )
-      return TT_Err_Could_Not_Find_Context;
+      return FT_THROW( Could_Not_Find_Context );
 
     TT_Load_Context( exec, face, size );
 
@@ -856,7 +877,27 @@
       }
     }
     else
-      error = TT_Err_Ok;
+      error = FT_Err_Ok;
+
+    /* UNDOCUMENTED!  The MS rasterizer doesn't allow the following */
+    /* graphics state variables to be modified by the CVT program.  */
+
+    exec->GS.dualVector.x = 0x4000;
+    exec->GS.dualVector.y = 0;
+    exec->GS.projVector.x = 0x4000;
+    exec->GS.projVector.y = 0x0;
+    exec->GS.freeVector.x = 0x4000;
+    exec->GS.freeVector.y = 0x0;
+
+    exec->GS.rp0 = 0;
+    exec->GS.rp1 = 0;
+    exec->GS.rp2 = 0;
+
+    exec->GS.gep0 = 1;
+    exec->GS.gep1 = 1;
+    exec->GS.gep2 = 1;
+
+    exec->GS.loop = 1;
 
     /* save as default graphics state */
     size->GS = exec->GS;
@@ -1003,7 +1044,7 @@
   tt_size_ready_bytecode( TT_Size  size,
                           FT_Bool  pedantic )
   {
-    FT_Error  error = TT_Err_Ok;
+    FT_Error  error = FT_Err_Ok;
 
 
     if ( !size->bytecode_ready )
@@ -1070,7 +1111,7 @@
   tt_size_init( FT_Size  ttsize )           /* TT_Size */
   {
     TT_Size   size  = (TT_Size)ttsize;
-    FT_Error  error = TT_Err_Ok;
+    FT_Error  error = FT_Err_Ok;
 
 #ifdef TT_USE_BYTECODE_INTERPRETER
     size->bytecode_ready = 0;
@@ -1126,7 +1167,7 @@
   tt_size_reset( TT_Size  size )
   {
     TT_Face           face;
-    FT_Error          error = TT_Err_Ok;
+    FT_Error          error = FT_Err_Ok;
     FT_Size_Metrics*  metrics;
 
 
@@ -1140,7 +1181,7 @@
     *metrics = size->root.metrics;
 
     if ( metrics->x_ppem < 1 || metrics->y_ppem < 1 )
-      return TT_Err_Invalid_PPem;
+      return FT_THROW( Invalid_PPem );
 
     /* This bit flag, if set, indicates that the ppems must be       */
     /* rounded to integers.  Nearly all TrueType fonts have this bit */
@@ -1170,16 +1211,14 @@
       size->ttmetrics.scale   = metrics->x_scale;
       size->ttmetrics.ppem    = metrics->x_ppem;
       size->ttmetrics.x_ratio = 0x10000L;
-      size->ttmetrics.y_ratio = FT_MulDiv( metrics->y_ppem,
-                                           0x10000L,
+      size->ttmetrics.y_ratio = FT_DivFix( metrics->y_ppem,
                                            metrics->x_ppem );
     }
     else
     {
       size->ttmetrics.scale   = metrics->y_scale;
       size->ttmetrics.ppem    = metrics->y_ppem;
-      size->ttmetrics.x_ratio = FT_MulDiv( metrics->x_ppem,
-                                           0x10000L,
+      size->ttmetrics.x_ratio = FT_DivFix( metrics->x_ppem,
                                            metrics->y_ppem );
       size->ttmetrics.y_ratio = 0x10000L;
     }
@@ -1219,15 +1258,21 @@
 
 
     if ( !TT_New_Context( driver ) )
-      return TT_Err_Could_Not_Find_Context;
+      return FT_THROW( Could_Not_Find_Context );
 
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+    driver->interpreter_version = TT_INTERPRETER_VERSION_38;
 #else
+    driver->interpreter_version = TT_INTERPRETER_VERSION_35;
+#endif
+
+#else /* !TT_USE_BYTECODE_INTERPRETER */
 
     FT_UNUSED( ttdriver );
 
-#endif
+#endif /* !TT_USE_BYTECODE_INTERPRETER */
 
-    return TT_Err_Ok;
+    return FT_Err_Ok;
   }
 
 
diff --git a/src/truetype/ttobjs.h b/src/truetype/ttobjs.h
index 47e4129..a11dd37 100644
--- a/src/truetype/ttobjs.h
+++ b/src/truetype/ttobjs.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    Objects manager (specification).                                     */
 /*                                                                         */
-/*  Copyright 1996-2009, 2011-2012 by                                      */
+/*  Copyright 1996-2009, 2011-2013 by                                      */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -173,11 +173,13 @@
   /*                                                                       */
   typedef struct  TT_DefRecord_
   {
-    FT_Int   range;      /* in which code range is it located? */
-    FT_Long  start;      /* where does it start?               */
-    FT_Long  end;        /* where does it end?                 */
-    FT_UInt  opc;        /* function #, or instruction code    */
-    FT_Bool  active;     /* is it active?                      */
+    FT_Int    range;          /* in which code range is it located?     */
+    FT_Long   start;          /* where does it start?                   */
+    FT_Long   end;            /* where does it end?                     */
+    FT_UInt   opc;            /* function #, or instruction code        */
+    FT_Bool   active;         /* is it active?                          */
+    FT_Bool   inline_delta;   /* is function that defines inline delta? */
+    FT_ULong  sph_fdef_flags; /* flags to identify special functions    */
 
   } TT_DefRecord, *TT_DefArray;
 
@@ -190,7 +192,7 @@
   {
     FT_Fixed    xx, xy;     /* transformation matrix coefficients */
     FT_Fixed    yx, yy;
-    FT_F26Dot6  ox, oy;     /* offsets        */
+    FT_F26Dot6  ox, oy;     /* offsets                            */
 
   } TT_Transform;
 
@@ -345,11 +347,12 @@
   /*                                                                       */
   typedef struct  TT_DriverRec_
   {
-    FT_DriverRec     root;
+    FT_DriverRec  root;
+
     TT_ExecContext   context;  /* execution context        */
     TT_GlyphZoneRec  zone;     /* glyph loader points zone */
 
-    void*            extension_component;
+    FT_UInt  interpreter_version;
 
   } TT_DriverRec;
 
@@ -427,6 +430,10 @@
   tt_slot_init( FT_GlyphSlot  slot );
 
 
+  /* auxiliary */
+#define IS_HINTED( flags )  ( ( flags & FT_LOAD_NO_HINTING ) == 0 )
+
+
 FT_END_HEADER
 
 #endif /* __TTOBJS_H__ */
diff --git a/src/truetype/ttpic.c b/src/truetype/ttpic.c
index 65ca845..edefae7 100644
--- a/src/truetype/ttpic.c
+++ b/src/truetype/ttpic.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType position independent code services for truetype module. */
 /*                                                                         */
-/*  Copyright 2009, 2010 by                                                */
+/*  Copyright 2009, 2010, 2012, 2013 by                                    */
 /*  Oran Agra and Mickey Gabel.                                            */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -22,30 +22,29 @@
 #include "ttpic.h"
 #include "tterrors.h"
 
+
 #ifdef FT_CONFIG_OPTION_PIC
 
   /* forward declaration of PIC init functions from ttdriver.c */
   FT_Error
   FT_Create_Class_tt_services( FT_Library           library,
                                FT_ServiceDescRec**  output_class );
-
   void
   FT_Destroy_Class_tt_services( FT_Library          library,
                                 FT_ServiceDescRec*  clazz );
-
   void
   FT_Init_Class_tt_service_gx_multi_masters(
     FT_Service_MultiMastersRec*  sv_mm );
-
   void
   FT_Init_Class_tt_service_truetype_glyf(
     FT_Service_TTGlyfRec*  sv_ttglyf );
 
+
   void
   tt_driver_class_pic_free( FT_Library  library )
   {
     FT_PIC_Container*  pic_container = &library->pic_container;
-    FT_Memory  memory = library->memory;
+    FT_Memory          memory        = library->memory;
 
 
     if ( pic_container->truetype )
@@ -66,18 +65,19 @@
   tt_driver_class_pic_init( FT_Library  library )
   {
     FT_PIC_Container*  pic_container = &library->pic_container;
-    FT_Error           error         = TT_Err_Ok;
-    TTModulePIC*       container;
+    FT_Error           error         = FT_Err_Ok;
+    TTModulePIC*       container     = NULL;
     FT_Memory          memory        = library->memory;
 
 
     /* allocate pointer, clear and set global container pointer */
-    if ( FT_ALLOC ( container, sizeof ( *container ) ) )
+    if ( FT_ALLOC( container, sizeof ( *container ) ) )
       return error;
     FT_MEM_SET( container, 0, sizeof ( *container ) );
     pic_container->truetype = container;
 
-    /* initialize pointer table - this is how the module usually expects this data */
+    /* initialize pointer table - this is how the module usually */
+    /* expects this data                                         */
     error = FT_Create_Class_tt_services( library,
                                          &container->tt_services );
     if ( error )
@@ -88,7 +88,8 @@
 #endif
     FT_Init_Class_tt_service_truetype_glyf(
       &container->tt_service_truetype_glyf );
-Exit:
+
+  Exit:
     if ( error )
       tt_driver_class_pic_free( library );
     return error;
diff --git a/src/truetype/ttpic.h b/src/truetype/ttpic.h
index 48f43a5..cfb4ee6 100644
--- a/src/truetype/ttpic.h
+++ b/src/truetype/ttpic.h
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    The FreeType position independent code services for truetype module. */
 /*                                                                         */
-/*  Copyright 2009 by                                                      */
+/*  Copyright 2009, 2012, 2013 by                                          */
 /*  Oran Agra and Mickey Gabel.                                            */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -23,29 +23,43 @@
 FT_BEGIN_HEADER
 
 #ifndef FT_CONFIG_OPTION_PIC
-#define FT_TT_SERVICES_GET                   tt_services
-#define FT_TT_SERVICE_GX_MULTI_MASTERS_GET   tt_service_gx_multi_masters
-#define FT_TT_SERVICE_TRUETYPE_GLYF_GET      tt_service_truetype_glyf
+
+#define TT_SERVICES_GET                  tt_services
+#define TT_SERVICE_GX_MULTI_MASTERS_GET  tt_service_gx_multi_masters
+#define TT_SERVICE_TRUETYPE_GLYF_GET     tt_service_truetype_glyf
+#define TT_SERVICE_PROPERTIES_GET        tt_service_properties
 
 #else /* FT_CONFIG_OPTION_PIC */
 
 #include FT_MULTIPLE_MASTERS_H
 #include FT_SERVICE_MULTIPLE_MASTERS_H
 #include FT_SERVICE_TRUETYPE_GLYF_H
+#include FT_SERVICE_PROPERTIES_H
 
-  typedef struct TTModulePIC_
+
+  typedef struct  TTModulePIC_
   {
-    FT_ServiceDescRec* tt_services;
+    FT_ServiceDescRec*          tt_services;
 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
-    FT_Service_MultiMastersRec tt_service_gx_multi_masters;
+    FT_Service_MultiMastersRec  tt_service_gx_multi_masters;
 #endif
-    FT_Service_TTGlyfRec tt_service_truetype_glyf;
+    FT_Service_TTGlyfRec        tt_service_truetype_glyf;
+    FT_Service_PropertiesRec    tt_service_properties;
+
   } TTModulePIC;
 
-#define GET_PIC(lib)                         ((TTModulePIC*)((lib)->pic_container.truetype))
-#define FT_TT_SERVICES_GET                   (GET_PIC(library)->tt_services)
-#define FT_TT_SERVICE_GX_MULTI_MASTERS_GET   (GET_PIC(library)->tt_service_gx_multi_masters)
-#define FT_TT_SERVICE_TRUETYPE_GLYF_GET      (GET_PIC(library)->tt_service_truetype_glyf)
+
+#define GET_PIC( lib )                                      \
+          ( (TTModulePIC*)((lib)->pic_container.truetype) )
+#define TT_SERVICES_GET                       \
+          ( GET_PIC( library )->tt_services )
+#define TT_SERVICE_GX_MULTI_MASTERS_GET                       \
+          ( GET_PIC( library )->tt_service_gx_multi_masters )
+#define TT_SERVICE_TRUETYPE_GLYF_GET                       \
+          ( GET_PIC( library )->tt_service_truetype_glyf )
+#define TT_SERVICE_PROPERTIES_GET                       \
+          ( GET_PIC( library )->tt_service_properties )
+
 
   /* see ttpic.c for the implementation */
   void
@@ -58,6 +72,7 @@
 
  /* */
 
+
 FT_END_HEADER
 
 #endif /* __TTPIC_H__ */
diff --git a/src/truetype/ttpload.c b/src/truetype/ttpload.c
index bb6005d..9723a51 100644
--- a/src/truetype/ttpload.c
+++ b/src/truetype/ttpload.c
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    TrueType-specific tables loader (body).                              */
 /*                                                                         */
-/*  Copyright 1996-2002, 2004-2012 by                                      */
+/*  Copyright 1996-2002, 2004-2013 by                                      */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -72,7 +72,7 @@
 
     /* it is possible that a font doesn't have a glyf table at all */
     /* or its size is zero                                         */
-    if ( error == TT_Err_Table_Missing )
+    if ( FT_ERR_EQ( error, Table_Missing ) )
       face->glyf_len = 0;
     else if ( error )
       goto Exit;
@@ -81,7 +81,7 @@
     error = face->goto_table( face, TTAG_loca, stream, &table_len );
     if ( error )
     {
-      error = TT_Err_Locations_Missing;
+      error = FT_THROW( Locations_Missing );
       goto Exit;
     }
 
@@ -92,7 +92,7 @@
       if ( table_len >= 0x40000L )
       {
         FT_TRACE2(( "table too large\n" ));
-        error = TT_Err_Invalid_Table;
+        error = FT_THROW( Invalid_Table );
         goto Exit;
       }
       face->num_locations = table_len >> shift;
@@ -104,7 +104,7 @@
       if ( table_len >= 0x20000L )
       {
         FT_TRACE2(( "table too large\n" ));
-        error = TT_Err_Invalid_Table;
+        error = FT_THROW( Invalid_Table );
         goto Exit;
       }
       face->num_locations = table_len >> shift;
@@ -296,7 +296,7 @@
 
       face->cvt_size = 0;
       face->cvt      = NULL;
-      error          = TT_Err_Ok;
+      error          = FT_Err_Ok;
 
       goto Exit;
     }
@@ -334,7 +334,7 @@
     FT_UNUSED( face   );
     FT_UNUSED( stream );
 
-    return TT_Err_Ok;
+    return FT_Err_Ok;
 
 #endif
   }
@@ -375,7 +375,7 @@
     {
       face->font_program      = NULL;
       face->font_program_size = 0;
-      error                   = TT_Err_Ok;
+      error                   = FT_Err_Ok;
 
       FT_TRACE2(( "is missing\n" ));
     }
@@ -396,7 +396,7 @@
     FT_UNUSED( face   );
     FT_UNUSED( stream );
 
-    return TT_Err_Ok;
+    return FT_Err_Ok;
 
 #endif
   }
@@ -436,7 +436,7 @@
     {
       face->cvt_program      = NULL;
       face->cvt_program_size = 0;
-      error                  = TT_Err_Ok;
+      error                  = FT_Err_Ok;
 
       FT_TRACE2(( "is missing\n" ));
     }
@@ -457,7 +457,7 @@
     FT_UNUSED( face   );
     FT_UNUSED( stream );
 
-    return TT_Err_Ok;
+    return FT_Err_Ok;
 
 #endif
   }
@@ -495,7 +495,7 @@
     /* this table is optional */
     error = face->goto_table( face, TTAG_hdmx, stream, &table_size );
     if ( error || table_size < 8 )
-      return TT_Err_Ok;
+      return FT_Err_Ok;
 
     if ( FT_FRAME_EXTRACT( table_size, face->hdmx_table ) )
       goto Exit;
@@ -525,7 +525,7 @@
 
     if ( version != 0 || num_records > 255 || record_size > 0x10001L )
     {
-      error = TT_Err_Invalid_File_Format;
+      error = FT_THROW( Invalid_File_Format );
       goto Fail;
     }
 
diff --git a/src/truetype/ttsubpix.c b/src/truetype/ttsubpix.c
new file mode 100644
index 0000000..28470ad
--- /dev/null
+++ b/src/truetype/ttsubpix.c
@@ -0,0 +1,1011 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ttsubpix.c                                                             */
+/*                                                                         */
+/*    TrueType Subpixel Hinting.                                           */
+/*                                                                         */
+/*  Copyright 2010-2013 by                                                 */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+#include <ft2build.h>
+#include FT_INTERNAL_DEBUG_H
+#include FT_INTERNAL_CALC_H
+#include FT_INTERNAL_STREAM_H
+#include FT_INTERNAL_SFNT_H
+#include FT_TRUETYPE_TAGS_H
+#include FT_OUTLINE_H
+#include FT_TRUETYPE_DRIVER_H
+
+#include "ttsubpix.h"
+
+
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* These rules affect how the TT Interpreter does hinting, with the      */
+  /* goal of doing subpixel hinting by (in general) ignoring x moves.      */
+  /* Some of these rules are fixes that go above and beyond the            */
+  /* stated techniques in the MS whitepaper on Cleartype, due to           */
+  /* artifacts in many glyphs.  So, these rules make some glyphs render    */
+  /* better than they do in the MS rasterizer.                             */
+  /*                                                                       */
+  /* "" string or 0 int/char indicates to apply to all glyphs.             */
+  /* "-" used as dummy placeholders, but any non-matching string works.    */
+  /*                                                                       */
+  /* Some of this could arguably be implemented in fontconfig, however:    */
+  /*                                                                       */
+  /*  - Fontconfig can't set things on a glyph-by-glyph basis.             */
+  /*  - The tweaks that happen here are very low-level, from an average    */
+  /*    user's point of view and are best implemented in the hinter.       */
+  /*                                                                       */
+  /* The goal is to make the subpixel hinting techniques as generalized    */
+  /* as possible across all fonts to prevent the need for extra rules such */
+  /* as these.                                                             */
+  /*                                                                       */
+  /* The rule structure is designed so that entirely new rules can easily  */
+  /* be added when a new compatibility feature is discovered.              */
+  /*                                                                       */
+  /* The rule structures could also use some enhancement to handle ranges. */
+  /*                                                                       */
+  /*     ****************** WORK IN PROGRESS *******************           */
+  /*                                                                       */
+
+  /* These are `classes' of fonts that can be grouped together and used in */
+  /* rules below.  A blank entry "" is required at the end of these!       */
+#define FAMILY_CLASS_RULES_SIZE  7
+
+  static const SPH_Font_Class FAMILY_CLASS_Rules
+                              [FAMILY_CLASS_RULES_SIZE] =
+  {
+    { "MS Legacy Fonts",
+      { "Aharoni",
+        "Andale Mono",
+        "Andalus",
+        "Angsana New",
+        "AngsanaUPC",
+        "Arabic Transparent",
+        "Arial Black",
+        "Arial Narrow",
+        "Arial Unicode MS",
+        "Arial",
+        "Batang",
+        "Browallia New",
+        "BrowalliaUPC",
+        "Comic Sans MS",
+        "Cordia New",
+        "CordiaUPC",
+        "Courier New",
+        "DFKai-SB",
+        "David Transparent",
+        "David",
+        "DilleniaUPC",
+        "Estrangelo Edessa",
+        "EucrosiaUPC",
+        "FangSong_GB2312",
+        "Fixed Miriam Transparent",
+        "FrankRuehl",
+        "Franklin Gothic Medium",
+        "FreesiaUPC",
+        "Garamond",
+        "Gautami",
+        "Georgia",
+        "Gulim",
+        "Impact",
+        "IrisUPC",
+        "JasmineUPC",
+        "KaiTi_GB2312",
+        "KodchiangUPC",
+        "Latha",
+        "Levenim MT",
+        "LilyUPC",
+        "Lucida Console",
+        "Lucida Sans Unicode",
+        "MS Gothic",
+        "MS Mincho",
+        "MV Boli",
+        "Mangal",
+        "Marlett",
+        "Microsoft Sans Serif",
+        "Mingliu",
+        "Miriam Fixed",
+        "Miriam Transparent",
+        "Miriam",
+        "Narkisim",
+        "Palatino Linotype",
+        "Raavi",
+        "Rod Transparent",
+        "Rod",
+        "Shruti",
+        "SimHei",
+        "Simplified Arabic Fixed",
+        "Simplified Arabic",
+        "Simsun",
+        "Sylfaen",
+        "Symbol",
+        "Tahoma",
+        "Times New Roman",
+        "Traditional Arabic",
+        "Trebuchet MS",
+        "Tunga",
+        "Verdana",
+        "Webdings",
+        "Wingdings",
+        "",
+      },
+    },
+    { "Core MS Legacy Fonts",
+      { "Arial Black",
+        "Arial Narrow",
+        "Arial Unicode MS",
+        "Arial",
+        "Comic Sans MS",
+        "Courier New",
+        "Garamond",
+        "Georgia",
+        "Impact",
+        "Lucida Console",
+        "Lucida Sans Unicode",
+        "Microsoft Sans Serif",
+        "Palatino Linotype",
+        "Tahoma",
+        "Times New Roman",
+        "Trebuchet MS",
+        "Verdana",
+        "",
+      },
+    },
+    { "Apple Legacy Fonts",
+      { "Geneva",
+        "Times",
+        "Monaco",
+        "Century",
+        "Chalkboard",
+        "Lobster",
+        "Century Gothic",
+        "Optima",
+        "Lucida Grande",
+        "Gill Sans",
+        "Baskerville",
+        "Helvetica",
+        "Helvetica Neue",
+        "",
+      },
+    },
+    { "Legacy Sans Fonts",
+      { "Andale Mono",
+        "Arial Unicode MS",
+        "Arial",
+        "Century Gothic",
+        "Comic Sans MS",
+        "Franklin Gothic Medium",
+        "Geneva",
+        "Lucida Console",
+        "Lucida Grande",
+        "Lucida Sans Unicode",
+        "Lucida Sans Typewriter",
+        "Microsoft Sans Serif",
+        "Monaco",
+        "Tahoma",
+        "Trebuchet MS",
+        "Verdana",
+        "",
+      },
+    },
+
+    { "Misc Legacy Fonts",
+      { "Dark Courier", "", }, },
+    { "Verdana Clones",
+      { "DejaVu Sans",
+        "Bitstream Vera Sans", "", }, },
+    { "Verdana and Clones",
+      { "DejaVu Sans",
+        "Bitstream Vera Sans",
+        "Verdana", "", }, },
+  };
+
+
+  /* Define this to force natural (i.e. not bitmap-compatible) widths.     */
+  /* The default leans strongly towards natural widths except for a few    */
+  /* legacy fonts where a selective combination produces nicer results.    */
+/* #define FORCE_NATURAL_WIDTHS   */
+
+
+  /* Define `classes' of styles that can be grouped together and used in   */
+  /* rules below.  A blank entry "" is required at the end of these!       */
+#define STYLE_CLASS_RULES_SIZE  5
+
+  const SPH_Font_Class STYLE_CLASS_Rules
+                       [STYLE_CLASS_RULES_SIZE] =
+  {
+    { "Regular Class",
+      { "Regular",
+        "Book",
+        "Medium",
+        "Roman",
+        "Normal",
+        "",
+      },
+    },
+    { "Regular/Italic Class",
+      { "Regular",
+        "Book",
+        "Medium",
+        "Italic",
+        "Oblique",
+        "Roman",
+        "Normal",
+        "",
+      },
+    },
+    { "Bold/BoldItalic Class",
+      { "Bold",
+        "Bold Italic",
+        "Black",
+        "",
+      },
+    },
+    { "Bold/Italic/BoldItalic Class",
+      { "Bold",
+        "Bold Italic",
+        "Black",
+        "Italic",
+        "Oblique",
+        "",
+      },
+    },
+    { "Regular/Bold Class",
+      { "Regular",
+        "Book",
+        "Medium",
+        "Normal",
+        "Roman",
+        "Bold",
+        "Black",
+        "",
+      },
+    },
+  };
+
+
+  /* Force special legacy fixes for fonts.                                 */
+#define COMPATIBILITY_MODE_RULES_SIZE  1
+
+  const SPH_TweakRule  COMPATIBILITY_MODE_Rules
+                       [COMPATIBILITY_MODE_RULES_SIZE] =
+  {
+    { "-", 0, "", 0 },
+  };
+
+
+  /* Don't do subpixel (ignore_x_mode) hinting; do normal hinting.         */
+#define PIXEL_HINTING_RULES_SIZE  2
+
+  const SPH_TweakRule  PIXEL_HINTING_Rules
+                       [PIXEL_HINTING_RULES_SIZE] =
+  {
+    /* these characters are almost always safe */
+    { "Courier New", 12, "Italic", 'z' },
+    { "Courier New", 11, "Italic", 'z' },
+  };
+
+
+  /* Subpixel hinting ignores SHPIX rules on X.  Force SHPIX for these.    */
+#define DO_SHPIX_RULES_SIZE  1
+
+  const SPH_TweakRule  DO_SHPIX_Rules
+                       [DO_SHPIX_RULES_SIZE] =
+  {
+    { "-", 0, "", 0 },
+  };
+
+
+  /* Skip Y moves that start with a point that is not on a Y pixel         */
+  /* boundary and don't move that point to a Y pixel boundary.             */
+#define SKIP_NONPIXEL_Y_MOVES_RULES_SIZE  4
+
+  const SPH_TweakRule  SKIP_NONPIXEL_Y_MOVES_Rules
+                       [SKIP_NONPIXEL_Y_MOVES_RULES_SIZE] =
+  {
+    /* fix vwxyz thinness*/
+    { "Consolas", 0, "", 0 },
+    /* Fix thin middle stems */
+    { "Core MS Legacy Fonts", 0, "Regular", 0 },
+    /* Cyrillic small letter I */
+    { "Legacy Sans Fonts", 0, "", 0 },
+    /* Fix artifacts with some Regular & Bold */
+    { "Verdana Clones", 0, "", 0 },
+  };
+
+
+#define SKIP_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE  1
+
+  const SPH_TweakRule  SKIP_NONPIXEL_Y_MOVES_Rules_Exceptions
+                       [SKIP_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE] =
+  {
+    /* Fixes < and > */
+    { "Courier New", 0, "Regular", 0 },
+  };
+
+
+  /* Skip Y moves that start with a point that is not on a Y pixel         */
+  /* boundary and don't move that point to a Y pixel boundary.             */
+#define SKIP_NONPIXEL_Y_MOVES_DELTAP_RULES_SIZE  2
+
+  const SPH_TweakRule  SKIP_NONPIXEL_Y_MOVES_DELTAP_Rules
+                       [SKIP_NONPIXEL_Y_MOVES_DELTAP_RULES_SIZE] =
+  {
+    /* Maintain thickness of diagonal in 'N' */
+    { "Times New Roman", 0, "Regular/Bold Class", 'N' },
+    { "Georgia", 0, "Regular/Bold Class", 'N' },
+  };
+
+
+  /* Skip Y moves that move a point off a Y pixel boundary.                */
+#define SKIP_OFFPIXEL_Y_MOVES_RULES_SIZE  1
+
+  const SPH_TweakRule  SKIP_OFFPIXEL_Y_MOVES_Rules
+                       [SKIP_OFFPIXEL_Y_MOVES_RULES_SIZE] =
+  {
+    { "-", 0, "", 0 },
+  };
+
+
+#define SKIP_OFFPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE  1
+
+  const SPH_TweakRule  SKIP_OFFPIXEL_Y_MOVES_Rules_Exceptions
+                       [SKIP_OFFPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE] =
+  {
+    { "-", 0, "", 0 },
+  };
+
+
+  /* Round moves that don't move a point to a Y pixel boundary.            */
+#define ROUND_NONPIXEL_Y_MOVES_RULES_SIZE  2
+
+  const SPH_TweakRule  ROUND_NONPIXEL_Y_MOVES_Rules
+                       [ROUND_NONPIXEL_Y_MOVES_RULES_SIZE] =
+  {
+    /* Droid font instructions don't snap Y to pixels */
+    { "Droid Sans", 0, "Regular/Italic Class", 0 },
+    { "Droid Sans Mono", 0, "", 0 },
+  };
+
+
+#define ROUND_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE  1
+
+  const SPH_TweakRule  ROUND_NONPIXEL_Y_MOVES_Rules_Exceptions
+                       [ROUND_NONPIXEL_Y_MOVES_RULES_EXCEPTIONS_SIZE] =
+  {
+    { "-", 0, "", 0 },
+  };
+
+
+  /* Allow a Direct_Move along X freedom vector if matched.                */
+#define ALLOW_X_DMOVE_RULES_SIZE  1
+
+  const SPH_TweakRule  ALLOW_X_DMOVE_Rules
+                       [ALLOW_X_DMOVE_RULES_SIZE] =
+  {
+    /* Fixes vanishing diagonal in 4 */
+    { "Verdana", 0, "Regular", '4' },
+  };
+
+
+  /* Return MS rasterizer version 35 if matched.                           */
+#define RASTERIZER_35_RULES_SIZE  8
+
+  const SPH_TweakRule  RASTERIZER_35_Rules
+                       [RASTERIZER_35_RULES_SIZE] =
+  {
+    /* This seems to be the only way to make these look good */
+    { "Times New Roman", 0, "Regular", 'i' },
+    { "Times New Roman", 0, "Regular", 'j' },
+    { "Times New Roman", 0, "Regular", 'm' },
+    { "Times New Roman", 0, "Regular", 'r' },
+    { "Times New Roman", 0, "Regular", 'a' },
+    { "Times New Roman", 0, "Regular", 'n' },
+    { "Times New Roman", 0, "Regular", 'p' },
+    { "Times", 0, "", 0 },
+  };
+
+
+  /* Don't round to the subpixel grid.  Round to pixel grid.               */
+#define NORMAL_ROUND_RULES_SIZE  1
+
+  const SPH_TweakRule  NORMAL_ROUND_Rules
+                       [NORMAL_ROUND_RULES_SIZE] =
+  {
+    /* Fix serif thickness for certain ppems */
+    /* Can probably be generalized somehow   */
+    { "Courier New", 0, "", 0 },
+  };
+
+
+  /* Skip IUP instructions if matched.                                     */
+#define SKIP_IUP_RULES_SIZE  1
+
+  const SPH_TweakRule  SKIP_IUP_Rules
+                       [SKIP_IUP_RULES_SIZE] =
+  {
+    { "Arial", 13, "Regular", 'a' },
+  };
+
+
+  /* Skip MIAP Twilight hack if matched.                                   */
+#define MIAP_HACK_RULES_SIZE  1
+
+  const SPH_TweakRule  MIAP_HACK_Rules
+                       [MIAP_HACK_RULES_SIZE] =
+  {
+    { "Geneva", 12, "", 0 },
+  };
+
+
+  /* Skip DELTAP instructions if matched.                                  */
+#define ALWAYS_SKIP_DELTAP_RULES_SIZE  23
+
+  const SPH_TweakRule  ALWAYS_SKIP_DELTAP_Rules
+                       [ALWAYS_SKIP_DELTAP_RULES_SIZE] =
+  {
+    { "Georgia", 0, "Regular", 'k' },
+    /* fix various problems with e in different versions */
+    { "Trebuchet MS", 14, "Regular", 'e' },
+    { "Trebuchet MS", 13, "Regular", 'e' },
+    { "Trebuchet MS", 15, "Regular", 'e' },
+    { "Trebuchet MS", 0, "Italic", 'v' },
+    { "Trebuchet MS", 0, "Italic", 'w' },
+    { "Trebuchet MS", 0, "Regular", 'Y' },
+    { "Arial", 11, "Regular", 's' },
+    /* prevent problems with '3' and others */
+    { "Verdana", 10, "Regular", 0 },
+    { "Verdana", 9, "Regular", 0 },
+    /* Cyrillic small letter short I */
+    { "Legacy Sans Fonts", 0, "", 0x438 },
+    { "Legacy Sans Fonts", 0, "", 0x439 },
+    { "Arial", 10, "Regular", '6' },
+    { "Arial", 0, "Bold/BoldItalic Class", 'a' },
+    /* Make horizontal stems consistent with the rest */
+    { "Arial", 24, "Bold", 'a' },
+    { "Arial", 25, "Bold", 'a' },
+    { "Arial", 24, "Bold", 's' },
+    { "Arial", 25, "Bold", 's' },
+    { "Arial", 34, "Bold", 's' },
+    { "Arial", 35, "Bold", 's' },
+    { "Arial", 36, "Bold", 's' },
+    { "Arial", 25, "Regular", 's' },
+    { "Arial", 26, "Regular", 's' },
+  };
+
+
+  /* Always do DELTAP instructions if matched.                             */
+#define ALWAYS_DO_DELTAP_RULES_SIZE  1
+
+  const SPH_TweakRule  ALWAYS_DO_DELTAP_Rules
+                       [ALWAYS_DO_DELTAP_RULES_SIZE] =
+  {
+    { "-", 0, "", 0 },
+  };
+
+
+  /* Don't allow ALIGNRP after IUP.                                        */
+#define NO_ALIGNRP_AFTER_IUP_RULES_SIZE  1
+
+  static const SPH_TweakRule  NO_ALIGNRP_AFTER_IUP_Rules
+                              [NO_ALIGNRP_AFTER_IUP_RULES_SIZE] =
+  {
+    /* Prevent creation of dents in outline */
+    { "-", 0, "", 0 },
+  };
+
+
+  /* Don't allow DELTAP after IUP.                                         */
+#define NO_DELTAP_AFTER_IUP_RULES_SIZE  1
+
+  static const SPH_TweakRule  NO_DELTAP_AFTER_IUP_Rules
+                              [NO_DELTAP_AFTER_IUP_RULES_SIZE] =
+  {
+    { "-", 0, "", 0 },
+  };
+
+
+  /* Don't allow CALL after IUP.                                           */
+#define NO_CALL_AFTER_IUP_RULES_SIZE  1
+
+  static const SPH_TweakRule  NO_CALL_AFTER_IUP_Rules
+                              [NO_CALL_AFTER_IUP_RULES_SIZE] =
+  {
+    /* Prevent creation of dents in outline */
+    { "-", 0, "", 0 },
+  };
+
+
+  /* De-embolden these glyphs slightly.                                    */
+#define DEEMBOLDEN_RULES_SIZE  9
+
+  static const SPH_TweakRule  DEEMBOLDEN_Rules
+                              [DEEMBOLDEN_RULES_SIZE] =
+  {
+    { "Courier New", 0, "Bold", 'A' },
+    { "Courier New", 0, "Bold", 'W' },
+    { "Courier New", 0, "Bold", 'w' },
+    { "Courier New", 0, "Bold", 'M' },
+    { "Courier New", 0, "Bold", 'X' },
+    { "Courier New", 0, "Bold", 'K' },
+    { "Courier New", 0, "Bold", 'x' },
+    { "Courier New", 0, "Bold", 'z' },
+    { "Courier New", 0, "Bold", 'v' },
+  };
+
+
+  /* Embolden these glyphs slightly.                                       */
+#define EMBOLDEN_RULES_SIZE  2
+
+  static const SPH_TweakRule  EMBOLDEN_Rules
+                              [EMBOLDEN_RULES_SIZE] =
+  {
+    { "Courier New", 0, "Regular", 0 },
+    { "Courier New", 0, "Italic", 0 },
+  };
+
+
+  /* This is a CVT hack that makes thick horizontal stems on 2, 5, 7       */
+  /* similar to Windows XP.                                                */
+#define TIMES_NEW_ROMAN_HACK_RULES_SIZE  12
+
+  static const SPH_TweakRule  TIMES_NEW_ROMAN_HACK_Rules
+                              [TIMES_NEW_ROMAN_HACK_RULES_SIZE] =
+  {
+    { "Times New Roman", 16, "Italic", '2' },
+    { "Times New Roman", 16, "Italic", '5' },
+    { "Times New Roman", 16, "Italic", '7' },
+    { "Times New Roman", 16, "Regular", '2' },
+    { "Times New Roman", 16, "Regular", '5' },
+    { "Times New Roman", 16, "Regular", '7' },
+    { "Times New Roman", 17, "Italic", '2' },
+    { "Times New Roman", 17, "Italic", '5' },
+    { "Times New Roman", 17, "Italic", '7' },
+    { "Times New Roman", 17, "Regular", '2' },
+    { "Times New Roman", 17, "Regular", '5' },
+    { "Times New Roman", 17, "Regular", '7' },
+  };
+
+
+  /* This fudges distance on 2 to get rid of the vanishing stem issue.     */
+  /* A real solution to this is certainly welcome.                         */
+#define COURIER_NEW_2_HACK_RULES_SIZE  15
+
+  static const SPH_TweakRule  COURIER_NEW_2_HACK_Rules
+                              [COURIER_NEW_2_HACK_RULES_SIZE] =
+  {
+    { "Courier New", 10, "Regular", '2' },
+    { "Courier New", 11, "Regular", '2' },
+    { "Courier New", 12, "Regular", '2' },
+    { "Courier New", 13, "Regular", '2' },
+    { "Courier New", 14, "Regular", '2' },
+    { "Courier New", 15, "Regular", '2' },
+    { "Courier New", 16, "Regular", '2' },
+    { "Courier New", 17, "Regular", '2' },
+    { "Courier New", 18, "Regular", '2' },
+    { "Courier New", 19, "Regular", '2' },
+    { "Courier New", 20, "Regular", '2' },
+    { "Courier New", 21, "Regular", '2' },
+    { "Courier New", 22, "Regular", '2' },
+    { "Courier New", 23, "Regular", '2' },
+    { "Courier New", 24, "Regular", '2' },
+  };
+
+
+#ifndef FORCE_NATURAL_WIDTHS
+
+  /* Use compatible widths with these glyphs.  Compatible widths is always */
+  /* on when doing B/W TrueType instructing, but is used selectively here, */
+  /* typically on glyphs with 3 or more vertical stems.                    */
+#define COMPATIBLE_WIDTHS_RULES_SIZE  38
+
+  static const SPH_TweakRule  COMPATIBLE_WIDTHS_Rules
+                              [COMPATIBLE_WIDTHS_RULES_SIZE] =
+  {
+    { "Arial Unicode MS", 12, "Regular Class", 'm' },
+    { "Arial Unicode MS", 14, "Regular Class", 'm' },
+    /* Cyrillic small letter sha */
+    { "Arial", 10, "Regular Class", 0x448 },
+    { "Arial", 11, "Regular Class", 'm' },
+    { "Arial", 12, "Regular Class", 'm' },
+    /* Cyrillic small letter sha */
+    { "Arial", 12, "Regular Class", 0x448 },
+    { "Arial", 13, "Regular Class", 0x448 },
+    { "Arial", 14, "Regular Class", 'm' },
+    /* Cyrillic small letter sha */
+    { "Arial", 14, "Regular Class", 0x448 },
+    { "Arial", 15, "Regular Class", 0x448 },
+    { "Arial", 17, "Regular Class", 'm' },
+    { "DejaVu Sans", 15, "Regular Class", 0 },
+    { "Microsoft Sans Serif", 11, "Regular Class", 0 },
+    { "Microsoft Sans Serif", 12, "Regular Class", 0 },
+    { "Segoe UI", 11, "Regular Class", 0 },
+    { "Monaco", 0, "Regular Class", 0 },
+    { "Segoe UI", 12, "Regular Class", 'm' },
+    { "Segoe UI", 14, "Regular Class", 'm' },
+    { "Tahoma", 11, "Regular Class", 0 },
+    { "Times New Roman", 16, "Regular Class", 'c' },
+    { "Times New Roman", 16, "Regular Class", 'm' },
+    { "Times New Roman", 16, "Regular Class", 'o' },
+    { "Times New Roman", 16, "Regular Class", 'w' },
+    { "Trebuchet MS", 11, "Regular Class", 0 },
+    { "Trebuchet MS", 12, "Regular Class", 0 },
+    { "Trebuchet MS", 14, "Regular Class", 0 },
+    { "Trebuchet MS", 15, "Regular Class", 0 },
+    { "Ubuntu", 12, "Regular Class", 'm' },
+    /* Cyrillic small letter sha */
+    { "Verdana", 10, "Regular Class", 0x448 },
+    { "Verdana", 11, "Regular Class", 0x448 },
+    { "Verdana and Clones", 12, "Regular Class", 'i' },
+    { "Verdana and Clones", 12, "Regular Class", 'j' },
+    { "Verdana and Clones", 12, "Regular Class", 'l' },
+    { "Verdana and Clones", 12, "Regular Class", 'm' },
+    { "Verdana and Clones", 13, "Regular Class", 'i' },
+    { "Verdana and Clones", 13, "Regular Class", 'j' },
+    { "Verdana and Clones", 13, "Regular Class", 'l' },
+    { "Verdana and Clones", 14, "Regular Class", 'm' },
+  };
+
+
+  /* Scaling slightly in the x-direction prior to hinting results in       */
+  /* more visually pleasing glyphs in certain cases.                       */
+  /* This sometimes needs to be coordinated with compatible width rules.   */
+  /* A value of 1000 corresponds to a scaled value of 1.0.                 */
+
+#define X_SCALING_RULES_SIZE  50
+
+  static const SPH_ScaleRule  X_SCALING_Rules[X_SCALING_RULES_SIZE] =
+  {
+    { "DejaVu Sans", 12, "Regular Class", 'm', 950 },
+    { "Verdana and Clones", 12, "Regular Class", 'a', 1100 },
+    { "Verdana and Clones", 13, "Regular Class", 'a', 1050 },
+    { "Arial", 11, "Regular Class", 'm', 975 },
+    { "Arial", 12, "Regular Class", 'm', 1050 },
+    /* Cyrillic small letter el */
+    { "Arial", 13, "Regular Class", 0x43B, 950 },
+    { "Arial", 13, "Regular Class", 'o', 950 },
+    { "Arial", 13, "Regular Class", 'e', 950 },
+    { "Arial", 14, "Regular Class", 'm', 950 },
+    /* Cyrillic small letter el */
+    { "Arial", 15, "Regular Class", 0x43B, 925 },
+    { "Bitstream Vera Sans", 10, "Regular/Italic Class", 0, 1100 },
+    { "Bitstream Vera Sans", 12, "Regular/Italic Class", 0, 1050 },
+    { "Bitstream Vera Sans", 16, "Regular Class", 0, 1050 },
+    { "Bitstream Vera Sans", 9, "Regular/Italic Class", 0, 1050 },
+    { "DejaVu Sans", 12, "Regular Class", 'l', 975 },
+    { "DejaVu Sans", 12, "Regular Class", 'i', 975 },
+    { "DejaVu Sans", 12, "Regular Class", 'j', 975 },
+    { "DejaVu Sans", 13, "Regular Class", 'l', 950 },
+    { "DejaVu Sans", 13, "Regular Class", 'i', 950 },
+    { "DejaVu Sans", 13, "Regular Class", 'j', 950 },
+    { "DejaVu Sans", 10, "Regular/Italic Class", 0, 1100 },
+    { "DejaVu Sans", 12, "Regular/Italic Class", 0, 1050 },
+    { "Georgia", 10, "", 0, 1050 },
+    { "Georgia", 11, "", 0, 1100 },
+    { "Georgia", 12, "", 0, 1025 },
+    { "Georgia", 13, "", 0, 1050 },
+    { "Georgia", 16, "", 0, 1050 },
+    { "Georgia", 17, "", 0, 1030 },
+    { "Liberation Sans", 12, "Regular Class", 'm', 1100 },
+    { "Lucida Grande", 11, "Regular Class", 'm', 1100 },
+    { "Microsoft Sans Serif", 11, "Regular Class", 'm', 950 },
+    { "Microsoft Sans Serif", 12, "Regular Class", 'm', 1050 },
+    { "Segoe UI", 12, "Regular Class", 'H', 1050 },
+    { "Segoe UI", 12, "Regular Class", 'm', 1050 },
+    { "Segoe UI", 14, "Regular Class", 'm', 1050 },
+    { "Tahoma", 11, "Regular Class", 'i', 975 },
+    { "Tahoma", 11, "Regular Class", 'l', 975 },
+    { "Tahoma", 11, "Regular Class", 'j', 900 },
+    { "Tahoma", 11, "Regular Class", 'm', 918 },
+    { "Verdana", 10, "Regular/Italic Class", 0, 1100 },
+    { "Verdana", 12, "Regular Class", 'm', 975 },
+    { "Verdana", 12, "Regular/Italic Class", 0, 1050 },
+    { "Verdana", 13, "Regular/Italic Class", 'i', 950 },
+    { "Verdana", 13, "Regular/Italic Class", 'j', 950 },
+    { "Verdana", 13, "Regular/Italic Class", 'l', 950 },
+    { "Verdana", 16, "Regular Class", 0, 1050 },
+    { "Verdana", 9, "Regular/Italic Class", 0, 1050 },
+    { "Times New Roman", 16, "Regular Class", 'm', 918 },
+    { "Trebuchet MS", 11, "Regular Class", 'm', 800 },
+    { "Trebuchet MS", 12, "Regular Class", 'm', 800 },
+  };
+
+#else
+
+#define COMPATIBLE_WIDTHS_RULES_SIZE  1
+
+  static const SPH_TweakRule  COMPATIBLE_WIDTHS_Rules
+                              [COMPATIBLE_WIDTHS_RULES_SIZE] =
+  {
+    { "-", 0, "", 0 },
+  };
+
+
+#define X_SCALING_RULES_SIZE  1
+
+  static const SPH_ScaleRule  X_SCALING_Rules
+                              [X_SCALING_RULES_SIZE] =
+  {
+    { "-", 0, "", 0, 1000 },
+  };
+
+#endif /* FORCE_NATURAL_WIDTHS */
+
+
+  FT_LOCAL_DEF( FT_Bool )
+  is_member_of_family_class( const FT_String*  detected_font_name,
+                             const FT_String*  rule_font_name )
+  {
+    FT_UInt  i, j;
+
+
+    /* Does font name match rule family? */
+    if ( strcmp( detected_font_name, rule_font_name ) == 0 )
+      return TRUE;
+
+    /* Is font name a wildcard ""? */
+    if ( strcmp( rule_font_name, "" ) == 0 )
+      return TRUE;
+
+    /* Is font name contained in a class list? */
+    for ( i = 0; i < FAMILY_CLASS_RULES_SIZE; i++ )
+    {
+      if ( strcmp( FAMILY_CLASS_Rules[i].name, rule_font_name ) == 0 )
+      {
+        for ( j = 0; j < SPH_MAX_CLASS_MEMBERS; j++ )
+        {
+          if ( strcmp( FAMILY_CLASS_Rules[i].member[j], "" ) == 0 )
+            continue;
+          if ( strcmp( FAMILY_CLASS_Rules[i].member[j],
+                       detected_font_name ) == 0 )
+            return TRUE;
+        }
+      }
+    }
+
+    return FALSE;
+  }
+
+
+  FT_LOCAL_DEF( FT_Bool )
+  is_member_of_style_class( const FT_String*  detected_font_style,
+                            const FT_String*  rule_font_style )
+  {
+    FT_UInt  i, j;
+
+
+    /* Does font style match rule style? */
+    if ( strcmp( detected_font_style, rule_font_style ) == 0 )
+      return TRUE;
+
+    /* Is font style a wildcard ""? */
+    if ( strcmp( rule_font_style, "" ) == 0 )
+      return TRUE;
+
+    /* Is font style contained in a class list? */
+    for ( i = 0; i < STYLE_CLASS_RULES_SIZE; i++ )
+    {
+      if ( strcmp( STYLE_CLASS_Rules[i].name, rule_font_style ) == 0 )
+      {
+        for ( j = 0; j < SPH_MAX_CLASS_MEMBERS; j++ )
+        {
+          if ( strcmp( STYLE_CLASS_Rules[i].member[j], "" ) == 0 )
+            continue;
+          if ( strcmp( STYLE_CLASS_Rules[i].member[j],
+                       detected_font_style ) == 0 )
+            return TRUE;
+        }
+      }
+    }
+
+    return FALSE;
+  }
+
+
+  FT_LOCAL_DEF( FT_Bool )
+  sph_test_tweak( TT_Face               face,
+                  const FT_String*      family,
+                  FT_UInt               ppem,
+                  const FT_String*      style,
+                  FT_UInt               glyph_index,
+                  const SPH_TweakRule*  rule,
+                  FT_UInt               num_rules )
+  {
+    FT_UInt  i;
+
+
+    /* rule checks may be able to be optimized further */
+    for ( i = 0; i < num_rules; i++ )
+    {
+      if ( family                                                   &&
+           ( is_member_of_family_class ( family, rule[i].family ) ) )
+        if ( rule[i].ppem == 0    ||
+             rule[i].ppem == ppem )
+          if ( style                                             &&
+               is_member_of_style_class ( style, rule[i].style ) )
+            if ( rule[i].glyph == 0                                ||
+                 FT_Get_Char_Index( (FT_Face)face,
+                                    rule[i].glyph ) == glyph_index )
+        return TRUE;
+    }
+
+    return FALSE;
+  }
+
+
+  static FT_UInt
+  scale_test_tweak( TT_Face               face,
+                    const FT_String*      family,
+                    FT_UInt               ppem,
+                    const FT_String*      style,
+                    FT_UInt               glyph_index,
+                    const SPH_ScaleRule*  rule,
+                    FT_UInt               num_rules )
+  {
+    FT_UInt  i;
+
+
+    /* rule checks may be able to be optimized further */
+    for ( i = 0; i < num_rules; i++ )
+    {
+      if ( family                                                   &&
+           ( is_member_of_family_class ( family, rule[i].family ) ) )
+        if ( rule[i].ppem == 0    ||
+             rule[i].ppem == ppem )
+          if ( style                                            &&
+               is_member_of_style_class( style, rule[i].style ) )
+            if ( rule[i].glyph == 0                                ||
+                 FT_Get_Char_Index( (FT_Face)face,
+                                    rule[i].glyph ) == glyph_index )
+        return rule[i].scale;
+    }
+
+    return 1000;
+  }
+
+
+  FT_LOCAL_DEF( FT_UInt )
+  sph_test_tweak_x_scaling( TT_Face           face,
+                            const FT_String*  family,
+                            FT_UInt           ppem,
+                            const FT_String*  style,
+                            FT_UInt           glyph_index )
+  {
+    return scale_test_tweak( face, family, ppem, style, glyph_index,
+                             X_SCALING_Rules, X_SCALING_RULES_SIZE );
+  }
+
+
+#define TWEAK_RULES( x )                                       \
+  if ( sph_test_tweak( face, family, ppem, style, glyph_index, \
+                       x##_Rules, x##_RULES_SIZE ) )           \
+    loader->exec->sph_tweak_flags |= SPH_TWEAK_##x;
+
+#define TWEAK_RULES_EXCEPTIONS( x )                                        \
+  if ( sph_test_tweak( face, family, ppem, style, glyph_index,             \
+                       x##_Rules_Exceptions, x##_RULES_EXCEPTIONS_SIZE ) ) \
+    loader->exec->sph_tweak_flags &= ~SPH_TWEAK_##x;
+
+
+  FT_LOCAL_DEF( void )
+  sph_set_tweaks( TT_Loader  loader,
+                  FT_UInt    glyph_index )
+  {
+    TT_Face     face   = (TT_Face)loader->face;
+    FT_String*  family = face->root.family_name;
+    int         ppem   = loader->size->metrics.x_ppem;
+    FT_String*  style  = face->root.style_name;
+
+
+    /* don't apply rules if style isn't set */
+    if ( !face->root.style_name )
+      return;
+
+#ifdef SPH_DEBUG_MORE_VERBOSE
+    printf( "%s,%d,%s,%c=%d ",
+            family, ppem, style, glyph_index, glyph_index );
+#endif
+
+    TWEAK_RULES( PIXEL_HINTING );
+
+    if ( loader->exec->sph_tweak_flags & SPH_TWEAK_PIXEL_HINTING )
+    {
+      loader->exec->ignore_x_mode = FALSE;
+      return;
+    }
+
+    TWEAK_RULES( ALLOW_X_DMOVE );
+    TWEAK_RULES( ALWAYS_DO_DELTAP );
+    TWEAK_RULES( ALWAYS_SKIP_DELTAP );
+    TWEAK_RULES( DEEMBOLDEN );
+    TWEAK_RULES( DO_SHPIX );
+    TWEAK_RULES( EMBOLDEN );
+    TWEAK_RULES( MIAP_HACK );
+    TWEAK_RULES( NORMAL_ROUND );
+    TWEAK_RULES( NO_ALIGNRP_AFTER_IUP );
+    TWEAK_RULES( NO_CALL_AFTER_IUP );
+    TWEAK_RULES( NO_DELTAP_AFTER_IUP );
+    TWEAK_RULES( RASTERIZER_35 );
+    TWEAK_RULES( SKIP_IUP );
+
+    TWEAK_RULES( SKIP_OFFPIXEL_Y_MOVES );
+    TWEAK_RULES_EXCEPTIONS( SKIP_OFFPIXEL_Y_MOVES );
+
+    TWEAK_RULES( SKIP_NONPIXEL_Y_MOVES_DELTAP );
+
+    TWEAK_RULES( SKIP_NONPIXEL_Y_MOVES );
+    TWEAK_RULES_EXCEPTIONS( SKIP_NONPIXEL_Y_MOVES );
+
+    TWEAK_RULES( ROUND_NONPIXEL_Y_MOVES );
+    TWEAK_RULES_EXCEPTIONS( ROUND_NONPIXEL_Y_MOVES );
+
+    if ( loader->exec->sph_tweak_flags & SPH_TWEAK_RASTERIZER_35 )
+    {
+      if ( loader->exec->rasterizer_version != TT_INTERPRETER_VERSION_35 )
+      {
+        loader->exec->rasterizer_version = TT_INTERPRETER_VERSION_35;
+        loader->exec->size->cvt_ready    = FALSE;
+
+        tt_size_ready_bytecode(
+          loader->exec->size,
+          FT_BOOL( loader->load_flags & FT_LOAD_PEDANTIC ) );
+      }
+      else
+        loader->exec->rasterizer_version = TT_INTERPRETER_VERSION_35;
+    }
+    else
+    {
+      if ( loader->exec->rasterizer_version  !=
+           SPH_OPTION_SET_RASTERIZER_VERSION )
+      {
+        loader->exec->rasterizer_version = SPH_OPTION_SET_RASTERIZER_VERSION;
+        loader->exec->size->cvt_ready    = FALSE;
+
+        tt_size_ready_bytecode(
+          loader->exec->size,
+          FT_BOOL( loader->load_flags & FT_LOAD_PEDANTIC ) );
+      }
+      else
+        loader->exec->rasterizer_version = SPH_OPTION_SET_RASTERIZER_VERSION;
+    }
+
+    if ( IS_HINTED( loader->load_flags ) )
+    {
+      TWEAK_RULES( TIMES_NEW_ROMAN_HACK );
+      TWEAK_RULES( COURIER_NEW_2_HACK );
+    }
+
+    if ( sph_test_tweak( face, family, ppem, style, glyph_index,
+           COMPATIBILITY_MODE_Rules, COMPATIBILITY_MODE_RULES_SIZE ) )
+      loader->exec->face->sph_compatibility_mode = TRUE;
+
+
+    if ( IS_HINTED( loader->load_flags ) )
+    {
+      if ( sph_test_tweak( face, family, ppem, style, glyph_index,
+             COMPATIBLE_WIDTHS_Rules, COMPATIBLE_WIDTHS_RULES_SIZE ) )
+        loader->exec->compatible_widths |= TRUE;
+    }
+  }
+
+#else /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
+  /* ANSI C doesn't like empty source files */
+  typedef int  _tt_subpix_dummy;
+
+#endif /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
+
+/* END */
diff --git a/src/truetype/ttsubpix.h b/src/truetype/ttsubpix.h
new file mode 100644
index 0000000..8a54fc7
--- /dev/null
+++ b/src/truetype/ttsubpix.h
@@ -0,0 +1,110 @@
+/***************************************************************************/
+/*                                                                         */
+/*  ttsubpix.h                                                             */
+/*                                                                         */
+/*    TrueType Subpixel Hinting.                                           */
+/*                                                                         */
+/*  Copyright 2010-2013 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 __TTSUBPIX_H__
+#define __TTSUBPIX_H__
+
+#include <ft2build.h>
+#include "ttobjs.h"
+#include "ttinterp.h"
+
+
+FT_BEGIN_HEADER
+
+
+#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* ID flags to identify special functions at FDEF and runtime.           */
+  /*                                                                       */
+  /*                                                                       */
+#define SPH_FDEF_INLINE_DELTA_1       0x0000001
+#define SPH_FDEF_INLINE_DELTA_2       0x0000002
+#define SPH_FDEF_DIAGONAL_STROKE      0x0000004
+#define SPH_FDEF_VACUFORM_ROUND_1     0x0000008
+#define SPH_FDEF_TTFAUTOHINT_1        0x0000010
+#define SPH_FDEF_SPACING_1            0x0000020
+#define SPH_FDEF_SPACING_2            0x0000040
+#define SPH_FDEF_TYPEMAN_STROKES      0x0000080
+#define SPH_FDEF_TYPEMAN_DIAGENDCTRL  0x0000100
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* Tweak flags that are set for each glyph by the below rules.           */
+  /*                                                                       */
+  /*                                                                       */
+#define SPH_TWEAK_ALLOW_X_DMOVE                   0x0000001
+#define SPH_TWEAK_ALWAYS_DO_DELTAP                0x0000002
+#define SPH_TWEAK_ALWAYS_SKIP_DELTAP              0x0000004
+#define SPH_TWEAK_COURIER_NEW_2_HACK              0x0000008
+#define SPH_TWEAK_DEEMBOLDEN                      0x0000010
+#define SPH_TWEAK_DO_SHPIX                        0x0000020
+#define SPH_TWEAK_EMBOLDEN                        0x0000040
+#define SPH_TWEAK_MIAP_HACK                       0x0000080
+#define SPH_TWEAK_NORMAL_ROUND                    0x0000100
+#define SPH_TWEAK_NO_ALIGNRP_AFTER_IUP            0x0000200
+#define SPH_TWEAK_NO_CALL_AFTER_IUP               0x0000400
+#define SPH_TWEAK_NO_DELTAP_AFTER_IUP             0x0000800
+#define SPH_TWEAK_PIXEL_HINTING                   0x0001000
+#define SPH_TWEAK_RASTERIZER_35                   0x0002000
+#define SPH_TWEAK_ROUND_NONPIXEL_Y_MOVES          0x0004000
+#define SPH_TWEAK_SKIP_IUP                        0x0008000
+#define SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES           0x0010000
+#define SPH_TWEAK_SKIP_OFFPIXEL_Y_MOVES           0x0020000
+#define SPH_TWEAK_TIMES_NEW_ROMAN_HACK            0x0040000
+#define SPH_TWEAK_SKIP_NONPIXEL_Y_MOVES_DELTAP    0x0080000
+
+
+  FT_LOCAL( FT_Bool )
+  sph_test_tweak( TT_Face               face,
+                  const FT_String*      family,
+                  FT_UInt               ppem,
+                  const FT_String*      style,
+                  FT_UInt               glyph_index,
+                  const SPH_TweakRule*  rule,
+                  FT_UInt               num_rules );
+
+  FT_LOCAL( FT_UInt )
+  sph_test_tweak_x_scaling( TT_Face           face,
+                            const FT_String*  family,
+                            FT_UInt           ppem,
+                            const FT_String*  style,
+                            FT_UInt           glyph_index );
+
+  FT_LOCAL( void )
+  sph_set_tweaks( TT_Loader  loader,
+                  FT_UInt    glyph_index );
+
+
+  /* These macros are defined absent a method for setting them */
+#define SPH_OPTION_BITMAP_WIDTHS           FALSE
+#define SPH_OPTION_SET_SUBPIXEL            TRUE
+#define SPH_OPTION_SET_GRAYSCALE           FALSE
+#define SPH_OPTION_SET_COMPATIBLE_WIDTHS   FALSE
+#define SPH_OPTION_SET_RASTERIZER_VERSION  38
+
+#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */
+
+
+FT_END_HEADER
+
+#endif /* __TTSUBPIX_H__ */
+
+/* END */